$OpenBSD: patch-fping_c,v 1.7 2007/07/13 08:13:22 djm Exp $ --- fping.c.orig Thu Jul 12 12:36:46 2007 +++ fping.c Thu Jul 12 12:36:50 2007 @@ -42,7 +42,6 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define IPV6 1 /* This should be a compiler option, or even better be done from the Makefile... ;) */ #ifndef _NO_PROTO #if !__STDC__ && !defined( __cplusplus ) && !defined( FUNCPROTO ) \ @@ -67,7 +66,7 @@ extern "C" /*** autoconf includes ***/ - +#include #include #include #include @@ -88,7 +87,6 @@ extern "C" #include #include -#include #include #include @@ -112,6 +110,10 @@ extern "C" #include #include +#if (defined(__unix__) || defined(unix)) && !defined(USG) +#include +#endif + /* RS6000 has sys/select.h */ #ifdef HAVE_SYS_SELECT_H #include @@ -123,10 +125,16 @@ extern "C" /*** externals ***/ +#ifndef __OpenBSD__ extern char *optarg; extern int optind,opterr; extern int h_errno; +#endif +#ifdef HAVE_PROGNAME +extern char *__progname; +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ @@ -246,13 +254,13 @@ typedef struct host_entry struct timeval last_send_time; /* time of last packet sent */ int num_sent; /* number of ping packets sent */ int num_recv; /* number of pings received */ - int max_reply; /* longest response time */ - int min_reply; /* shortest response time */ + long max_reply; /* longest response time */ + long min_reply; /* shortest response time */ int total_time; /* sum of response times */ int num_sent_i; /* number of ping packets sent */ int num_recv_i; /* number of pings received */ - int max_reply_i; /* longest response time */ - int min_reply_i; /* shortest response time */ + long max_reply_i; /* longest response time */ + long min_reply_i; /* shortest response time */ int total_time_i; /* sum of response times */ int *resp_times; /* individual response times */ #if defined( DEBUG ) || defined( _DEBUG ) @@ -283,6 +291,12 @@ u_int ping_pkt_size; u_int count = 1; u_int trials; u_int report_interval = 0; +int src_addr_present = 0; +#ifndef IPV6 +struct in_addr src_addr; +#else +struct in6_addr src_addr; +#endif /* global stats */ long max_reply = 0; @@ -408,6 +422,11 @@ int main( int argc, char **argv ) struct protoent *proto; char *buf; uid_t uid; +#ifndef IPV6 + struct sockaddr_in sa; +#else + struct sockaddr_in6 sa; +#endif /* check if we are root */ if( geteuid() ) @@ -482,7 +501,11 @@ int main( int argc, char **argv ) }/* IF */ - prog = argv[0]; +#ifdef HAVE_PROGNAME + prog = __progname; +#else + prog = (prog = strrchr(argv[0], '/')) ? prog + 1 : argv[0]; +#endif ident = getpid() & 0xFFFF; verbose_flag = 1; @@ -491,7 +514,7 @@ int main( int argc, char **argv ) /* get command line options */ - while( ( c = getopt( argc, argv, "gedhlmnqusaAvz:t:i:p:f:r:c:b:C:Q:B:" ) ) != EOF ) + while( ( c = getopt( argc, argv, "gedhlmnqusaAvz:t:i:p:f:r:c:b:C:Q:B:S:" ) ) != EOF ) { switch( c ) { @@ -502,9 +525,9 @@ int main( int argc, char **argv ) break; case 'r': - if( !( retry = ( u_int )atoi( optarg ) ) ) - usage(); + retry = ( u_int )atoi( optarg ); + break; case 'i': @@ -639,6 +662,16 @@ int main( int argc, char **argv ) generate_flag = 1; break; + case 'S': +#ifndef IPV6 + if( ! inet_pton( AF_INET, optarg, &src_addr ) ) +#else + if( ! inet_pton( AF_INET6, optarg, &src_addr ) ) +#endif + usage(); + src_addr_present = 1; + break; + default: usage(); break; @@ -808,8 +841,13 @@ int main( int argc, char **argv ) else if( filename ) { FILE *ping_file; +#ifdef MAXHOSTNAMELEN + char line[MAXHOSTNAMELEN]; + char host[MAXHOSTNAMELEN]; +#else char line[132]; char host[132]; +#endif char *p; if( strcmp( filename, "-" ) == 0 ) @@ -823,6 +861,7 @@ int main( int argc, char **argv ) while( fgets( line, 132, ping_file ) ) { + line[132-1] = '\0'; if( sscanf( line, "%s", host ) != 1 ) continue; @@ -962,6 +1001,22 @@ int main( int argc, char **argv ) if( !num_hosts ) exit( 2 ); + /* set the source address */ + + if( src_addr_present ) + { + memset( &sa, 0, sizeof( sa ) ); +#ifndef IPV6 + sa.sin_family = AF_INET; + sa.sin_addr = src_addr; +#else + sa.sin6_family = AF_INET6; + sa.sin6_addr = src_addr; +#endif + if ( bind( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 ) + errno_crash_and_burn( "cannot bind source address" ); + } + /* allocate array to hold outstanding ping requests */ table = ( HOST_ENTRY** )malloc( sizeof( HOST_ENTRY* ) * num_hosts ); @@ -1503,7 +1558,6 @@ void send_ping( int s, HOST_ENTRY *h ) memset( buffer, 0, ping_pkt_size * sizeof( char ) ); icp = ( FPING_ICMPHDR* )buffer; - gettimeofday( &h->last_send_time, &tz ); #ifndef IPV6 icp->icmp_type = ICMP_ECHO; icp->icmp_code = 0; @@ -1512,6 +1566,8 @@ void send_ping( int s, HOST_ENTRY *h ) icp->icmp_id = ident; pdp = ( PING_DATA* )( buffer + SIZE_ICMP_HDR ); + /* set the time at the very last possible point */ + gettimeofday(&h->last_send_time,&tz); pdp->ping_ts = h->last_send_time; pdp->ping_count = h->num_sent; @@ -1523,6 +1579,8 @@ void send_ping( int s, HOST_ENTRY *h ) icp->icmp6_id = ident; pdp = ( PING_DATA* )( buffer + SIZE_ICMP_HDR ); + /* set the time at the very last possible point */ + gettimeofday(&h->last_send_time,&tz); pdp->ping_ts = h->last_send_time; pdp->ping_count = h->num_sent; @@ -1611,6 +1669,9 @@ int wait_for_reply( void ) result = recvfrom_wto( s, buffer, sizeof(buffer), &response_addr, select_time ); + /* get time of receipt as close to the real time as possible */ + gettimeofday(¤t_time,&tz); + if( result < 0 ) return 0; /* timeout */ @@ -1625,7 +1686,7 @@ int wait_for_reply( void ) ip = ( struct ip* )buffer; #ifndef IPV6 -#if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) +#if defined( __alpha__ ) && defined(__osf1__) && __STDC__ && !defined( __GLIBC__ ) /* The alpha headers are decidedly broken. * Using an ANSI compiler, it provides ip_vhl instead of ip_hl and * ip_v. So, to get ip_hl, we mask off the bottom four bits. @@ -1633,7 +1694,7 @@ int wait_for_reply( void ) hlen = ( ip->ip_vhl & 0x0F ) << 2; #else hlen = ip->ip_hl << 2; -#endif /* defined(__alpha__) && __STDC__ */ +#endif /* defined(__alpha__) && defined(__osf1__) && __STDC__ */ if( result < hlen + ICMP_MINLEN ) #else if( result < sizeof(FPING_ICMPHDR) ) @@ -1690,7 +1751,6 @@ int wait_for_reply( void ) h = table[n]; /* received ping is cool, so process it */ - gettimeofday( ¤t_time, &tz ); h->waiting = 0; h->timeout = timeout; h->num_recv++; @@ -2570,7 +2630,7 @@ char * sprint_tm( int t ) /* <= 0.99 ms */ if( t < 100 ) { - sprintf( buf, "0.%02d", t ); + snprintf( buf, sizeof(buf), "0.%02d", t ); return( buf ); }/* IF */ @@ -2578,7 +2638,7 @@ char * sprint_tm( int t ) /* 1.00 - 9.99 ms */ if( t < 1000 ) { - sprintf( buf, "%d.%02d", t / 100, t % 100 ); + snprintf( buf, sizeof(buf), "%d.%02d", t / 100, t % 100 ); return( buf ); }/* IF */ @@ -2586,13 +2646,13 @@ char * sprint_tm( int t ) /* 10.0 - 99.9 ms */ if( t < 10000 ) { - sprintf( buf, "%d.%d", t / 100, ( t % 100 ) / 10 ); + snprintf( buf, sizeof(buf), "%d.%d", t / 100, ( t % 100 ) / 10 ); return( buf ); }/* IF */ /* >= 100 ms */ - sprintf( buf, "%d", t / 100 ); + snprintf( buf, sizeof(buf), "%d", t / 100 ); return( buf ); } /* sprint_tm() */ @@ -2732,6 +2792,7 @@ void usage( void ) fprintf( stderr, " -Q n same as -q, but show summary every n seconds\n" ); fprintf( stderr, " -r n number of retries (default %d)\n", retry ); fprintf( stderr, " -s print final stats\n" ); + fprintf( stderr, " -S addr set source address\n" ); fprintf( stderr, " -t n individual target initial timeout (in millisec) (default %d)\n", timeout / 100 ); fprintf( stderr, " -u show targets that are unreachable\n" ); fprintf( stderr, " -v show version\n" );