📄 fping.c
字号:
} /* print_per_system_stats() *//************************************************************ Function: print_per_system_splits************************************************************* Inputs: void (none) Description: ************************************************************/#ifdef _NO_PROTOvoid print_per_system_splits()#elsevoid print_per_system_splits( void )#endif /* _NO_PROTO */{ int i, j, k, avg; HOST_ENTRY *h; char *buf; int bufsize; int resp; struct tm *curr_tm; bufsize = max_hostname_len + 1; buf = ( char* )malloc( bufsize ); if( !buf ) crash_and_burn( "can't malloc print buf" ); memset( buf, 0, bufsize ); fflush( stdout ); if( verbose_flag || per_recv_flag ) fprintf( stderr, "\n" ); curr_tm = localtime( ( time_t* )¤t_time.tv_sec ); fprintf( stderr, "[%2.2d:%2.2d:%2.2d]\n", curr_tm->tm_hour, curr_tm->tm_min, curr_tm->tm_sec ); for( i = 0; i < num_hosts; i++ ) { h = table[i]; fprintf( stderr, "%s%s :", h->host, h->pad ); if( h->num_recv_i <= h->num_sent_i ) { fprintf( stderr, " xmt/rcv/%%loss = %d/%d/%d%%", h->num_sent_i, h->num_recv_i, ( ( h->num_sent_i - h->num_recv_i ) * 100 ) / h->num_sent_i ); }/* IF */ else { fprintf( stderr, " xmt/rcv/%%return = %d/%d/%d%%", h->num_sent_i, h->num_recv_i, ( ( h->num_recv_i * 100 ) / h->num_sent_i ) ); }/* ELSE */ if( h->num_recv_i ) { avg = h->total_time_i / h->num_recv_i; fprintf( stderr, ", min/avg/max = %s", sprint_tm( h->min_reply_i ) ); fprintf( stderr, "/%s", sprint_tm( avg ) ); fprintf( stderr, "/%s", sprint_tm( h->max_reply_i ) ); }/* IF */ fprintf( stderr, "\n" ); h->num_sent_i = h->num_recv_i = h->max_reply_i = h->min_reply_i = h->total_time_i = 0; }/* FOR */ free( buf );} /* print_per_system_splits() *//************************************************************ Function: print_global_stats************************************************************* Inputs: void (none) Description: ************************************************************/#ifdef _NO_PROTOvoid print_global_stats()#elsevoid print_global_stats( void )#endif /* _NO_PROTO */{ fflush( stdout ); fprintf( stderr, "\n" ); fprintf( stderr, " %7d targets\n", num_hosts ); fprintf( stderr, " %7d alive\n", num_alive ); fprintf( stderr, " %7d unreachable\n" ,num_unreachable ); fprintf( stderr, " %7d unknown addresses\n", num_noaddress ); fprintf( stderr, "\n" ); fprintf( stderr, " %7d timeouts (waiting for response)\n", num_timeout ); fprintf( stderr, " %7d ICMP Echos sent\n", num_pingsent ); fprintf( stderr, " %7d ICMP Echo Replies received\n", num_pingreceived ); fprintf( stderr, " %7d other ICMP received\n", num_othericmprcvd ); fprintf( stderr, "\n" ); if( total_replies == 0 ) { min_reply = 0; max_reply = 0; total_replies = 1; sum_replies = 0; }/* IF */ fprintf( stderr, " %s ms (min round trip time)\n", sprint_tm( min_reply ) ); fprintf( stderr, " %s ms (avg round trip time)\n", sprint_tm( ( int )( sum_replies / total_replies ) ) ); fprintf( stderr, " %s ms (max round trip time)\n", sprint_tm( max_reply ) ); fprintf( stderr, " %12.3f sec (elapsed real time)\n", timeval_diff( &end_time, &start_time ) / 100000.0 ); fprintf( stderr, "\n" );} /* print_global_stats() *//************************************************************ Function: send_ping************************************************************* Inputs: int s, HOST_ENTRY *h Description: Compose and transmit an ICMP_ECHO REQUEST packet. The IP packet will be added on by the kernel. The ID field is our UNIX process ID, and the sequence number is an index into an array of outstanding ping requests. The sequence number will later be used to quickly figure out who the ping reply came from.************************************************************/#ifdef _NO_PROTOvoid send_ping( s, h )int s; HOST_ENTRY *h;#elsevoid send_ping( int s, HOST_ENTRY *h )#endif /* _NO_PROTO */{ char *buffer; struct icmp *icp; PING_DATA *pdp; int n; buffer = ( char* )malloc( ( size_t )ping_pkt_size ); if( !buffer ) crash_and_burn( "can't malloc ping packet" ); memset( buffer, 0, ping_pkt_size * sizeof( char ) ); icp = ( struct icmp* )buffer; gettimeofday( &h->last_send_time, &tz ); icp->icmp_type = ICMP_ECHO; icp->icmp_code = 0; icp->icmp_cksum = 0; icp->icmp_seq = h->i; icp->icmp_id = ident; pdp = ( PING_DATA* )( buffer + SIZE_ICMP_HDR ); pdp->ping_ts = h->last_send_time; pdp->ping_count = h->num_sent; icp->icmp_cksum = in_cksum( ( u_short* )icp, ping_pkt_size );#if defined(DEBUG) || defined(_DEBUG) if( trace_flag ) printf( "sending [%d] to %s\n", h->num_sent, h->host );#endif /* DEBUG || _DEBUG */ n = sendto( s, buffer, ping_pkt_size, 0, ( struct sockaddr* )&h->saddr, sizeof( struct sockaddr_in ) ); if( n < 0 || n != ping_pkt_size ) { if( verbose_flag || unreachable_flag ) { printf( "%s", h->host ); if( verbose_flag ) printf( " error while sending ping: %s\n", strerror( errno ) ); printf( "\n" ); }/* IF */ num_unreachable++; remove_job( h ); }/* IF */ else { /* mark this trial as outstanding */ if( !loop_flag ) h->resp_times[h->num_sent] = RESP_WAITING;#if defined( DEBUG ) || defined( _DEBUG ) if( sent_times_flag ) h->sent_times[h->num_sent] = timeval_diff( &h->last_send_time, &start_time );#endif /* DEBUG || _DEBUG */ h->num_sent++; h->num_sent_i++; h->waiting++; num_pingsent++; last_send_time = h->last_send_time; }/* ELSE */ free( buffer );} /* send_ping() *//************************************************************ Function: wait_for_reply************************************************************* Inputs: void (none) Returns: int Description: ************************************************************/#ifdef _NO_PROTOint wait_for_reply()#elseint wait_for_reply( void )#endif{ int result; static char buffer[4096]; struct sockaddr_in response_addr; struct ip *ip; int hlen; struct icmp *icp; int n, avg; HOST_ENTRY *h; long this_reply; int this_count; struct timeval sent_time; result = recvfrom_wto( s, buffer, 4096, ( struct sockaddr* )&response_addr, select_time ); if( result < 0 ) return 0; /* timeout */ #if defined( DEBUG ) || defined( _DEBUG ) if( randomly_lose_flag ) { if( ( random() & 0x07 ) <= lose_factor ) return 0; }/* IF */#endif /* DEBUG || _DEBUG */ ip = ( struct ip* )buffer;#if defined( __alpha__ ) && __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. */ hlen = ( ip->ip_vhl & 0x0F ) << 2;#else hlen = ip->ip_hl << 2;#endif /* defined(__alpha__) && __STDC__ */ if( result < hlen + ICMP_MINLEN ) { if( verbose_flag ) printf( "received packet too short for ICMP (%d bytes from %s)\n", result, inet_ntoa( response_addr.sin_addr ) ); return( 1 ); /* too short */ }/* IF */ icp = ( struct icmp* )( buffer + hlen ); if( icp->icmp_type != ICMP_ECHOREPLY ) { /* handle some problem */ if( handle_random_icmp( icp, result, &response_addr ) ) num_othericmprcvd++; return 1; }/* IF */ if( icp->icmp_id != ident ) return 1; /* packet received, but not the one we are looking for! */ num_pingreceived++; if( icp->icmp_seq >= ( n_short )num_hosts ) return( 1 ); /* packet received, don't worry about it anymore */ n = icp->icmp_seq; h = table[n]; /* received ping is cool, so process it */ gettimeofday( ¤t_time, &tz ); h->waiting = 0; h->timeout = timeout; h->num_recv++; h->num_recv_i++; memcpy( &sent_time, icp->icmp_data + offsetof( PING_DATA, ping_ts ), sizeof( sent_time ) ); memcpy( &this_count, icp->icmp_data, sizeof( this_count ) );#if defined( DEBUG ) || defined( _DEBUG ) if( trace_flag ) printf( "received [%d] from %s\n", this_count, h->host );#endif /* DEBUG || _DEBUG */ this_reply = timeval_diff( ¤t_time, &sent_time ); if( this_reply > max_reply ) max_reply = this_reply; if( this_reply < min_reply ) min_reply = this_reply; if( this_reply > h->max_reply ) h->max_reply = this_reply; if( this_reply < h->min_reply ) h->min_reply = this_reply; if( this_reply > h->max_reply_i ) h->max_reply_i = this_reply; if( this_reply < h->min_reply_i ) h->min_reply_i = this_reply; sum_replies += this_reply; h->total_time += this_reply; h->total_time_i += this_reply; total_replies++; /* note reply time in array, probably */ if( !loop_flag ) { if( ( this_count >= 0 ) && ( this_count < trials ) ) { if( h->resp_times[this_count] != RESP_WAITING ) { if( !per_recv_flag ) { fprintf( stderr, "%s : duplicate for [%d], %d bytes, %s ms", h->host, this_count, result, sprint_tm( this_reply ) ); if( response_addr.sin_addr.s_addr != h->saddr.sin_addr.s_addr ) fprintf( stderr, " [<- %s]", inet_ntoa( response_addr.sin_addr ) ); fprintf( stderr, "\n" ); }/* IF */ }/* IF */ else h->resp_times[this_count] = this_reply; }/* IF */ else { /* count is out of bounds?? */ fprintf( stderr, "%s : duplicate for [%d], %d bytes, %s ms\n", h->host, this_count, result, sprint_tm( this_reply ) ); }/* ELSE */ }/* IF */ if( h->num_recv == 1 ) { num_alive++; if( verbose_flag || alive_flag ) { printf( "%s", h->host ); if( verbose_flag ) printf( " is alive" ); if( elapsed_flag ) printf( " (%s ms)", sprint_tm( this_reply ) ); if( response_addr.sin_addr.s_addr != h->saddr.sin_addr.s_addr ) printf( " [<- %s]", inet_ntoa( response_addr.sin_addr ) ); printf( "\n" ); }/* IF */ }/* IF */ if( per_recv_flag ) { avg = h->total_time / h->num_recv; printf( "%s%s : [%d], %d bytes, %s ms", h->host, h->pad, this_count, result, sprint_tm( this_reply ) ); printf( " (%s avg, ", sprint_tm( avg ) ); if( h->num_recv <= h->num_sent ) { printf( "%d%% loss)", ( ( h->num_sent - h->num_recv ) * 100 ) / h->num_sent ); }/* IF */ else { printf( "%d%% return)", ( h->num_recv * 100 ) / h->num_sent ); }/* ELSE */ if( response_addr.sin_addr.s_addr != h->saddr.sin_addr.s_addr ) printf( " [<- %s]", inet_ntoa( response_addr.sin_addr ) ); printf( "\n" ); }/* IF */ return num_jobs;} /* wait_for_reply() *//************************************************************ Function: handle_random_icmp************************************************************* Inputs: struct icmp *p, int psize, struct sockaddr_in *addr Returns: int Description: ************************************************************/#ifdef _NO_PROTOint handle_random_icmp( p, psize, addr ) struct icmp *p; int psize; struct sockaddr_in *addr;#elseint handle_random_icmp( struct icmp *p, int psize, struct sockaddr_in *addr )#endif /* _NO_PROTO */{ struct icmp *sent_icmp; struct ip *sent_ip; u_char *c; HOST_ENTRY *h; c = ( u_char* )p; switch( p->icmp_type ) { case ICMP_UNREACH: sent_icmp = ( struct icmp* )( c + 28 ); if( ( sent_icmp->icmp_type == ICMP_ECHO ) && ( sent_icmp->icmp_id == ident ) && ( sent_icmp->icmp_seq < ( n_short )num_hosts ) ) { /* this is a response to a ping we sent */ h = table[sent_icmp->icmp_seq]; if( p->icmp_code > ICMP_UNREACH_MAXTYPE ) { fprintf( stderr, "ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s", inet_ntoa( addr->sin_addr ), h->host ); }/* IF */ else { fprintf( stderr, "%s from %s for ICMP Echo sent to %s", icmp_unreach_str[p->icmp_code], inet_ntoa( addr->sin_addr ), h->host ); }/* ELSE */ if( inet_addr( h->host ) == -1 ) fprintf( stderr, " (%s)", inet_ntoa( h->saddr.sin_addr ) ); fprintf( stderr, "\n" ); }/* IF */ return 1; case ICMP_SOURCEQUENCH: case ICMP_REDIRECT: case ICMP_TIMXCEED: case ICMP_PARAMPROB: sent_icmp = ( struct icmp* )( c + 28 ); if( ( sent_icmp->icmp_type = ICMP_ECHO ) && ( sent_icmp->icmp_id = ident ) && ( sent_icmp->icmp_seq < ( n_short )num_hosts ) ) { /* this is a response to a ping we sent */ h = table[sent_icmp->icmp_seq]; fprintf( stderr, "%s from %s for ICMP Echo sent to %s", icmp_type_str[p->icmp_type], inet_ntoa( addr->sin_addr ), h->host ); if( inet_addr( h->host ) == -1 ) fprintf( stderr, " (%s)", inet_ntoa( h->saddr.sin_addr ) ); fprintf( stderr, "\n" ); }/* IF */ return 2; /* no way to tell whether any of these are sent due to our ping */ /* or not (shouldn't be, of course), so just discard */ case ICMP_TSTAMP: case ICMP_TSTAMPREPLY: case ICMP_IREQ: case ICMP_IREQREPLY: case ICMP_MASKREQ: case ICMP_MASKREPLY: default: return 0; }/* SWITCH */} /* handle_random_icmp() *//************************************************************ Function: in_cksum************************************************************* Inputs: u_short *p, int n Returns: int Description: Checksum routine for Internet Protocol family headers (C Version) From ping examples in W.Richard Stevens "UNIX NETWORK PROGRAMMING" book.************************************************************/#ifdef _NO_PROTOint in_cksum( p, n )u_short *p; int n;#elseint in_cksum( u_short *p, int n )#endif /* _NO_PROTO */{ register u_short answer; register long sum = 0; u_short odd_byte = 0; while( n > 1 ) { sum += *p++; n -= 2; }/* WHILE */ /* mop up an odd byte, if necessary */ if( n == 1 ) { *( u_char* )( &odd_byte ) = *( u_char* )p; sum += odd_byte; }/* IF */ sum = ( sum >> 16 ) + ( sum & 0xffff ); /* add hi 16 to low 16 */ sum += ( sum >> 16 ); /* add carry */ answer = ~sum; /* ones-complement, truncate*/ return ( answer );} /* in_cksum() *//************************************************************ Function: add_name************************************************************* Inputs: char* name Description: process input name for addition to target list name can turn into multiple targets via multiple interfaces (-m) or via NIS groups************************************************************/#ifdef _NO_PROTOvoid add_name( name )char *name;#elsevoid add_name( char *name )#endif /* _NO_PROTO */{ struct hostent *host_ent; u_int ipaddress; struct in_addr *ipa = ( struct in_addr* )&ipaddress; struct in_addr *host_add; char *nm; int i = 0; if( ( ipaddress = inet_addr( name ) ) != -1 ) { /* input name is an IP addr, go with it */ if( name_flag ) { if( addr_flag ) add_addr( name, na_cat( get_host_by_address( *ipa ), *ipa ), *ipa ); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -