]> arthur.barton.de Git - netatalk.git/blob - bin/aecho/aecho.c
Added checks for config.h in bin/ code
[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 <string.h>
41 #include <netdb.h>
42
43 #include <netatalk/endian.h>
44 #include <netatalk/at.h>
45 #include <atalk/compat.h>
46 #include <atalk/aep.h>
47 #include <atalk/nbp.h>
48 #include <atalk/netddp.h>
49 #include <atalk/ddp.h>
50
51 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
52 #ifndef SOCKLEN_T
53 #define SOCKLEN_T unsigned int
54 #endif
55
56 struct sockaddr_at      target;
57 int                     s, nsent = 0, nrecv = 0;
58 time_t                  totalms = 0, minms = -1, maxms = -1;
59 static unsigned int     pings = 0;
60
61 #if !defined( ibm032 ) && !defined( _IBMR2 )
62     void
63 #endif ibm032 _IBMR2
64 done()
65 {
66     if ( nsent > 0 ) {
67         printf( "\n----%d.%d AEP Statistics----\n",
68                 ntohs( target.sat_addr.s_net ), target.sat_addr.s_node );
69         printf( "%d packets sent, %d packets received, %d%% packet loss\n",
70                 nsent, nrecv, (( nsent - nrecv ) * 100 ) / nsent );
71         if ( nrecv > 0 ) {
72             printf( "round-trip (ms)  min/avg/max = %d/%d/%d\n",
73                     minms, totalms / nrecv, maxms );
74         }       
75     }
76     exit( 0 );
77 }
78   
79 #if !defined( ibm032 ) && !defined( _IBMR2 )
80     void
81 #endif ibm032 _IBMR2
82 aep_send()
83 {
84     struct timeval      tv;
85     char                *p, buf[ 1024 ];
86     static unsigned int seq = 0;
87
88     p = buf;
89     *p++ = DDPTYPE_AEP;
90     *p++ = AEPOP_REQUEST;
91     bcopy( &seq, p, sizeof( unsigned int ));
92     p += sizeof( unsigned int );
93     seq++;
94
95     if ( gettimeofday( &tv, (struct timezone *)0 ) < 0 ) {
96         perror( "gettimeofday" );
97         exit( 1 );
98     }
99     bcopy( &tv, p, sizeof( struct timeval ));
100     p += sizeof( struct timeval );
101
102     if ( netddp_sendto( s, buf, p - buf, 0, (struct sockaddr *) &target,
103             sizeof( struct sockaddr_at )) < 0 ) {
104         perror( "sendto" );
105         exit( 1 );
106     }
107     nsent++;
108     if (pings && nsent > pings) done();
109 }
110
111 main( ac, av )
112     int         ac;
113     char        **av;
114 {
115     struct servent      *se;
116     struct sigaction    sv;
117     struct itimerval    it;
118     struct sockaddr_at  sat, saddr;
119     struct timeval      tv, atv;
120     struct nbpnve       nn;
121     char                *obj = NULL, *type = "Workstation", *zone = "*";
122     int                 cc;
123     SOCKLEN_T           satlen;
124     unsigned int        seq;
125     time_t              ms;
126     char                buf[ 1024 ], *p;
127     unsigned char       port;
128
129     extern char         *optarg;
130     extern int          optind;
131   
132     memset(&saddr, 0, sizeof(saddr));
133     while (( cc = getopt( ac, av, "c:A:" )) != EOF ) {
134         switch ( cc ) {
135         case 'A':
136             if (!atalk_aton(optarg, &saddr.sat_addr)) {
137                 fprintf(stderr, "Bad address.\n");
138                 exit(1);
139             }
140           case 'c' :
141             pings = atoi( optarg );
142             break;
143
144         default :
145             usage( av[ 0 ] );
146             exit( 1 );
147         }
148     }
149     if ( ac - optind != 1 ) {
150         usage( av[ 0 ] );
151         exit( 1 );
152     }
153     
154     /*
155      * Save the port, since nbp_lookup calls getservbyname() to get the
156      * nbp port.
157      */
158     if (( se = getservbyname( "echo", "ddp" )) == NULL ) 
159        port = 4;
160     else
161        port = ntohs( se->s_port );
162
163     memset( &target, 0, sizeof( struct sockaddr_at ));
164 #ifdef BSD4_4
165     target.sat_len = sizeof( struct sockaddr_at );
166 #endif BSD4_4
167     target.sat_family = AF_APPLETALK;
168     if ( !atalk_aton( av[ optind ], &target.sat_addr )) {
169         if ( nbp_name( av[ optind ], &obj, &type, &zone ) || !obj ) {
170             fprintf( stderr, "Bad name: %s\n", av[ optind ] );
171             exit( 1 );
172         }
173         if ( nbp_lookup( obj, type, zone, &nn, 1, &saddr.sat_addr) <= 0 ) {
174             fprintf( stderr, "Can't find: %s\n", av[ optind ] );
175             exit( 1 );
176         }
177         memcpy( &target, &nn.nn_sat, sizeof( struct sockaddr_at ));
178     }
179     target.sat_port = port;
180
181     if ((s = netddp_open(saddr.sat_addr.s_net || saddr.sat_addr.s_node ? 
182                          &saddr : NULL, NULL)) < 0) {
183        perror("ddp_open");
184        exit(1);
185     }        
186
187     sv.sa_handler = aep_send;
188     sigemptyset( &sv.sa_mask );
189     sigaddset( &sv.sa_mask, SIGINT );
190     sv.sa_flags = SA_RESTART;
191     if ( sigaction( SIGALRM, &sv, (struct sigaction *)0 ) < 0 ) {
192         perror( "sigaction" );
193         exit( 1 );
194     }
195
196     sv.sa_handler = done;
197     sigemptyset( &sv.sa_mask );
198     sigaddset( &sv.sa_mask, SIGALRM );
199     sv.sa_flags = SA_RESTART;
200     if ( sigaction( SIGINT, &sv, (struct sigaction *)0 ) < 0 ) {
201         perror( "sigaction" );
202         exit( 1 );
203     }
204
205     it.it_interval.tv_sec = 1L;
206     it.it_interval.tv_usec = 0L;
207     it.it_value.tv_sec = 1L;
208     it.it_value.tv_usec = 0L;
209
210     if ( setitimer( ITIMER_REAL, &it, (struct itimerval *)0 ) < 0 ) {
211         perror( "setitimer" );
212         exit( 1 );
213     }
214
215     for (;;) {
216         satlen = sizeof( struct sockaddr_at );
217         if (( cc = netddp_recvfrom( s, buf, sizeof( buf ), 0, 
218                                     (struct sockaddr *) &sat,
219                                     &satlen )) < 0 ) {
220             if ( errno == EINTR ) {
221                 errno = 0;
222                 continue;
223             } else {
224                 perror( "recvfrom" );
225                 exit( 1 );
226             }
227         }
228         p = buf;
229         if ( *p++ != DDPTYPE_AEP || *p++ != AEPOP_REPLY ) {
230             fprintf( stderr, "%s: bad packet!\n", av[ 0 ] );
231             continue;
232         }
233         if ( gettimeofday( &tv, (struct timezone *)0 ) < 0 ) {
234             perror( "gettimeofday" );
235             exit( 1 );
236         }
237         bcopy( p, &seq, sizeof( unsigned int ));
238         p += sizeof( unsigned int );
239         bcopy( p, &atv, sizeof( struct timeval ));
240         nrecv++;
241         ms = ( tv.tv_sec - atv.tv_sec ) * 1000 +
242                 ( tv.tv_usec - atv.tv_usec ) / 1000;
243         totalms += ms;
244         if ( ms > maxms ) {
245             maxms = ms;
246         }
247         if ( ms < minms || minms == -1 ) {
248             minms = ms;
249         }
250         printf( "%d bytes from %u.%u: aep_seq=%d. time=%d. ms\n",
251                 cc, ntohs( sat.sat_addr.s_net ), sat.sat_addr.s_node,
252                 seq, ms );
253         if (pings && seq + 1 >= pings) done();
254     }
255 }
256
257 usage( av0 )
258 {
259     fprintf( stderr, "usage:\t%s [-A source address ] [-c count] ( addr | nbpname )\n", av0 );
260     exit( 1 );
261 }