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