2 * $Id: aecho.c,v 1.9 2009-10-14 01:38:28 didg Exp $
4 * Copyright (c) 1990,1991 Regents of The University of Michigan.
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.
17 * Research Systems Unix Group
18 * The University of Michigan
20 * 535 W. William Street
23 * netatalk@itd.umich.edu
27 * AppleTalk Echo Protocol Client
32 #endif /* HAVE_CONFIG_H */
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
46 #endif /* HAVE_NETDB_H */
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>
57 /* FIXME/SOCKLEN_T: socklen_t is a unix98 feature */
59 #define SOCKLEN_T unsigned int
60 #endif /* ! SOCKLEN_T */
62 static struct sockaddr_at target;
64 static unsigned int nsent = 0, nrecv = 0;
65 static time_t totalms = 0, minms = -1, maxms = -1;
66 static unsigned int pings = 0;
68 static void usage(char *);
70 static void done(int sig _U_)
73 printf( "\n----%d.%d AEP Statistics----\n",
74 ntohs( target.sat_addr.s_net ), target.sat_addr.s_node );
75 printf( "%d packets sent, %d packets received, %d%% packet loss\n",
76 nsent, nrecv, (( nsent - nrecv ) * 100 ) / nsent );
78 printf( "round-trip (ms) min/avg/max = %ld/%ld/%ld\n",
79 minms, totalms / nrecv, maxms );
85 static void aep_send(int sig _U_)
89 static unsigned int seq = 0;
94 memcpy( p, &seq, sizeof( unsigned int ));
95 p += sizeof( unsigned int );
98 if ( gettimeofday( &tv, (struct timezone *)0 ) < 0 ) {
99 perror( "gettimeofday" );
102 memcpy( p, &tv, sizeof( struct timeval ));
103 p += sizeof( struct timeval );
105 if ( netddp_sendto( sock, buf, p - buf, 0, (struct sockaddr *) &target,
106 sizeof( struct sockaddr_at )) < 0 ) {
111 if (pings && nsent > pings) done(0);
114 int main(int ac, char **av)
119 struct sockaddr_at sat, saddr;
120 struct timeval tv, atv;
122 char *obj = NULL, *type = "Workstation", *zone = "*";
127 char buf[ 1024 ], *p;
133 memset(&saddr, 0, sizeof(saddr));
134 while (( cc = getopt( ac, av, "c:A:" )) != EOF ) {
137 if (!atalk_aton(optarg, &saddr.sat_addr)) {
138 fprintf(stderr, "Bad address.\n");
144 pings = atoi( optarg );
152 if ( ac - optind != 1 ) {
158 * Save the port, since nbp_lookup calls getservbyname() to get the
161 if (( se = getservbyname( "echo", "ddp" )) == NULL )
164 port = ntohs( se->s_port );
166 memset( &target, 0, sizeof( struct sockaddr_at ));
168 target.sat_len = sizeof( struct sockaddr_at );
170 target.sat_family = AF_APPLETALK;
171 if ( !atalk_aton( av[ optind ], &target.sat_addr )) {
172 if ( nbp_name( av[ optind ], &obj, &type, &zone ) || !obj ) {
173 fprintf( stderr, "Bad name: %s\n", av[ optind ] );
176 if ( nbp_lookup( obj, type, zone, &nn, 1, &saddr.sat_addr) <= 0 ) {
177 fprintf( stderr, "Can't find: %s\n", av[ optind ] );
180 memcpy( &target, &nn.nn_sat, sizeof( struct sockaddr_at ));
182 target.sat_port = port;
184 if ((sock = netddp_open(saddr.sat_addr.s_net || saddr.sat_addr.s_node ?
185 &saddr : NULL, NULL)) < 0) {
190 sv.sa_handler = aep_send;
191 sigemptyset( &sv.sa_mask );
192 sigaddset( &sv.sa_mask, SIGINT );
193 sv.sa_flags = SA_RESTART;
194 if ( sigaction( SIGALRM, &sv, (struct sigaction *)0 ) < 0 ) {
195 perror( "sigaction" );
199 sv.sa_handler = done;
200 sigemptyset( &sv.sa_mask );
201 sigaddset( &sv.sa_mask, SIGALRM );
202 sv.sa_flags = SA_RESTART;
203 if ( sigaction( SIGINT, &sv, (struct sigaction *)0 ) < 0 ) {
204 perror( "sigaction" );
208 it.it_interval.tv_sec = 1L;
209 it.it_interval.tv_usec = 0L;
210 it.it_value.tv_sec = 1L;
211 it.it_value.tv_usec = 0L;
213 if ( setitimer( ITIMER_REAL, &it, (struct itimerval *)0 ) < 0 ) {
214 perror( "setitimer" );
219 satlen = sizeof( struct sockaddr_at );
220 if (( cc = netddp_recvfrom( sock, buf, sizeof( buf ), 0,
221 (struct sockaddr *) &sat,
223 if ( errno == EINTR ) {
227 perror( "recvfrom" );
232 if ( *p++ != DDPTYPE_AEP || *p++ != AEPOP_REPLY ) {
233 fprintf( stderr, "%s: bad packet!\n", av[ 0 ] );
236 if ( gettimeofday( &tv, (struct timezone *)0 ) < 0 ) {
237 perror( "gettimeofday" );
240 memcpy( &seq, p, sizeof( unsigned int ));
241 p += sizeof( unsigned int );
242 memcpy( &atv, p, sizeof( struct timeval ));
244 ms = ( tv.tv_sec - atv.tv_sec ) * 1000 +
245 ( tv.tv_usec - atv.tv_usec ) / 1000;
250 if ( ms < minms || minms == -1 ) {
253 printf( "%d bytes from %u.%u: aep_seq=%d. time=%ld. ms\n",
254 cc, ntohs( sat.sat_addr.s_net ), sat.sat_addr.s_node,
256 if (pings && seq + 1 >= pings) done(0);
260 static void usage( char * av0 )
262 fprintf( stderr, "usage:\t%s [-A source address ] [-c count] ( addr | nbpname )\n", av0 );