]> arthur.barton.de Git - netatalk.git/blob - bin/aecho/aecho.c
massive commenting/autoconf changes
[netatalk.git] / bin / aecho / aecho.c
1 /*
2  * $Id: aecho.c,v 1.4 2001-06-29 14:14:46 rufustfirefly Exp $
3  *
4  * Copyright (c) 1990,1991 Regents of The University of Michigan.
5  * All Rights Reserved.
6  *
7  * Permission to use, copy, modify, and distribute this software and
8  * its documentation for any purpose and without fee is hereby granted,
9  * provided that the above copyright notice appears in all copies and
10  * that both that copyright notice and this permission notice appear
11  * in supporting documentation, and that the name of The University
12  * of Michigan not be used in advertising or publicity pertaining to
13  * distribution of the software without specific, written prior
14  * permission. This software is supplied as is without expressed or
15  * implied warranties of any kind.
16  *
17  *      Research Systems Unix Group
18  *      The University of Michigan
19  *      c/o Mike Clark
20  *      535 W. William Street
21  *      Ann Arbor, Michigan
22  *      +1-313-763-0525
23  *      netatalk@itd.umich.edu
24  */
25
26 /*
27  * AppleTalk Echo Protocol Client
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif /* HAVE_CONFIG_H */
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/time.h>
38 #include <errno.h>
39
40 #include <signal.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #ifdef HAVE_NETDB_H
45 #include <netdb.h>
46 #endif /* HAVE_NETDB_H */
47
48 #include <netatalk/endian.h>
49 #include <netatalk/at.h>
50 #include <atalk/compat.h>
51 #include <atalk/aep.h>
52 #include <atalk/nbp.h>
53 #include <atalk/netddp.h>
54 #include <atalk/ddp.h>
55 #include <atalk/util.h>
56
57 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
58 #ifndef SOCKLEN_T
59 #define SOCKLEN_T unsigned int
60 #endif /* ! SOCKLEN_T */
61
62 struct sockaddr_at      target;
63 int                     s, nsent = 0, nrecv = 0;
64 time_t                  totalms = 0, minms = -1, maxms = -1;
65 static unsigned int     pings = 0;
66
67 void usage(char *);
68
69 void done()
70 {
71     if ( nsent > 0 ) {
72         printf( "\n----%d.%d AEP Statistics----\n",
73                 ntohs( target.sat_addr.s_net ), target.sat_addr.s_node );
74         printf( "%d packets sent, %d packets received, %d%% packet loss\n",
75                 nsent, nrecv, (( nsent - nrecv ) * 100 ) / nsent );
76         if ( nrecv > 0 ) {
77             printf( "round-trip (ms)  min/avg/max = %ld/%ld/%ld\n",
78                     minms, totalms / nrecv, maxms );
79         }       
80     }
81     exit( 0 );
82 }
83   
84 void aep_send()
85 {
86     struct timeval      tv;
87     char                *p, buf[ 1024 ];
88     static unsigned int seq = 0;
89
90     p = buf;
91     *p++ = DDPTYPE_AEP;
92     *p++ = AEPOP_REQUEST;
93     bcopy( &seq, p, sizeof( unsigned int ));
94     p += sizeof( unsigned int );
95     seq++;
96
97     if ( gettimeofday( &tv, (struct timezone *)0 ) < 0 ) {
98         perror( "gettimeofday" );
99         exit( 1 );
100     }
101     bcopy( &tv, p, sizeof( struct timeval ));
102     p += sizeof( struct timeval );
103
104     if ( netddp_sendto( s, buf, p - buf, 0, (struct sockaddr *) &target,
105             sizeof( struct sockaddr_at )) < 0 ) {
106         perror( "sendto" );
107         exit( 1 );
108     }
109     nsent++;
110     if (pings && nsent > pings) done();
111 }
112
113 int main( ac, av )
114     int         ac;
115     char        **av;
116 {
117     struct servent      *se;
118     struct sigaction    sv;
119     struct itimerval    it;
120     struct sockaddr_at  sat, saddr;
121     struct timeval      tv, atv;
122     struct nbpnve       nn;
123     char                *obj = NULL, *type = "Workstation", *zone = "*";
124     int                 cc;
125     SOCKLEN_T           satlen;
126     unsigned int        seq;
127     time_t              ms;
128     char                buf[ 1024 ], *p;
129     unsigned char       port;
130
131     extern char         *optarg;
132     extern int          optind;
133   
134     memset(&saddr, 0, sizeof(saddr));
135     while (( cc = getopt( ac, av, "c:A:" )) != EOF ) {
136         switch ( cc ) {
137         case 'A':
138             if (!atalk_aton(optarg, &saddr.sat_addr)) {
139                 fprintf(stderr, "Bad address.\n");
140                 exit(1);
141             }
142           case 'c' :
143             pings = atoi( optarg );
144             break;
145
146         default :
147             usage( av[ 0 ] );
148             exit( 1 );
149         }
150     }
151     if ( ac - optind != 1 ) {
152         usage( av[ 0 ] );
153         exit( 1 );
154     }
155     
156     /*
157      * Save the port, since nbp_lookup calls getservbyname() to get the
158      * nbp port.
159      */
160     if (( se = getservbyname( "echo", "ddp" )) == NULL ) 
161        port = 4;
162     else
163        port = ntohs( se->s_port );
164
165     memset( &target, 0, sizeof( struct sockaddr_at ));
166 #ifdef BSD4_4
167     target.sat_len = sizeof( struct sockaddr_at );
168 #endif /* BSD4_4 */
169     target.sat_family = AF_APPLETALK;
170     if ( !atalk_aton( av[ optind ], &target.sat_addr )) {
171         if ( nbp_name( av[ optind ], &obj, &type, &zone ) || !obj ) {
172             fprintf( stderr, "Bad name: %s\n", av[ optind ] );
173             exit( 1 );
174         }
175         if ( nbp_lookup( obj, type, zone, &nn, 1, &saddr.sat_addr) <= 0 ) {
176             fprintf( stderr, "Can't find: %s\n", av[ optind ] );
177             exit( 1 );
178         }
179         memcpy( &target, &nn.nn_sat, sizeof( struct sockaddr_at ));
180     }
181     target.sat_port = port;
182
183     if ((s = netddp_open(saddr.sat_addr.s_net || saddr.sat_addr.s_node ? 
184                          &saddr : NULL, NULL)) < 0) {
185        perror("ddp_open");
186        exit(1);
187     }        
188
189     sv.sa_handler = aep_send;
190     sigemptyset( &sv.sa_mask );
191     sigaddset( &sv.sa_mask, SIGINT );
192     sv.sa_flags = SA_RESTART;
193     if ( sigaction( SIGALRM, &sv, (struct sigaction *)0 ) < 0 ) {
194         perror( "sigaction" );
195         exit( 1 );
196     }
197
198     sv.sa_handler = done;
199     sigemptyset( &sv.sa_mask );
200     sigaddset( &sv.sa_mask, SIGALRM );
201     sv.sa_flags = SA_RESTART;
202     if ( sigaction( SIGINT, &sv, (struct sigaction *)0 ) < 0 ) {
203         perror( "sigaction" );
204         exit( 1 );
205     }
206
207     it.it_interval.tv_sec = 1L;
208     it.it_interval.tv_usec = 0L;
209     it.it_value.tv_sec = 1L;
210     it.it_value.tv_usec = 0L;
211
212     if ( setitimer( ITIMER_REAL, &it, (struct itimerval *)0 ) < 0 ) {
213         perror( "setitimer" );
214         exit( 1 );
215     }
216
217     for (;;) {
218         satlen = sizeof( struct sockaddr_at );
219         if (( cc = netddp_recvfrom( s, buf, sizeof( buf ), 0, 
220                                     (struct sockaddr *) &sat,
221                                     &satlen )) < 0 ) {
222             if ( errno == EINTR ) {
223                 errno = 0;
224                 continue;
225             } else {
226                 perror( "recvfrom" );
227                 exit( 1 );
228             }
229         }
230         p = buf;
231         if ( *p++ != DDPTYPE_AEP || *p++ != AEPOP_REPLY ) {
232             fprintf( stderr, "%s: bad packet!\n", av[ 0 ] );
233             continue;
234         }
235         if ( gettimeofday( &tv, (struct timezone *)0 ) < 0 ) {
236             perror( "gettimeofday" );
237             exit( 1 );
238         }
239         bcopy( p, &seq, sizeof( unsigned int ));
240         p += sizeof( unsigned int );
241         bcopy( p, &atv, sizeof( struct timeval ));
242         nrecv++;
243         ms = ( tv.tv_sec - atv.tv_sec ) * 1000 +
244                 ( tv.tv_usec - atv.tv_usec ) / 1000;
245         totalms += ms;
246         if ( ms > maxms ) {
247             maxms = ms;
248         }
249         if ( ms < minms || minms == -1 ) {
250             minms = ms;
251         }
252         printf( "%d bytes from %u.%u: aep_seq=%d. time=%ld. ms\n",
253                 cc, ntohs( sat.sat_addr.s_net ), sat.sat_addr.s_node,
254                 seq, ms );
255         if (pings && seq + 1 >= pings) done();
256     }
257 }
258
259 void usage( char * av0 )
260 {
261     fprintf( stderr, "usage:\t%s [-A source address ] [-c count] ( addr | nbpname )\n", av0 );
262     exit( 1 );
263 }