work on ipv4/ipv6 unification

pull/89/merge
David Schweikert 8 years ago
parent e71164de22
commit c090cd770d

@ -334,7 +334,6 @@ void print_netdata( void );
void print_global_stats( void ); void print_global_stats( void );
void main_loop(); void main_loop();
void finish(); void finish();
int handle_random_icmp( FPING_ICMPHDR *p, struct sockaddr *addr, socklen_t addr_len);
char *sprint_tm( int t ); char *sprint_tm( int t );
void ev_enqueue(HOST_ENTRY *h); void ev_enqueue(HOST_ENTRY *h);
HOST_ENTRY *ev_dequeue(); HOST_ENTRY *ev_dequeue();
@ -1661,13 +1660,229 @@ int receive_packet(int socket,
return recv_len; return recv_len;
} }
#ifndef IPV6
int decode_icmp_ipv4(
struct sockaddr *response_addr,
size_t response_addr_len,
char *reply_buf,
size_t reply_buf_len,
unsigned short *id,
unsigned short *seq
)
{
struct ip *ip = (struct ip *) reply_buf;
struct icmp *icp;
int hlen = 0;
#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
if( reply_buf_len < hlen + ICMP_MINLEN ) {
/* too short */
if( verbose_flag )
{
char buf[INET6_ADDRSTRLEN];
getnameinfo((struct sockaddr *)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
printf( "received packet too short for ICMP (%d bytes from %s)\n", (int) reply_buf_len, buf);
}
return 0;
}
icp = (struct icmp *)(reply_buf + hlen);
if( icp->icmp_type != ICMP_ECHOREPLY )
{
/* Handle other ICMP packets */
struct icmp *sent_icmp;
SEQMAP_VALUE *seqmap_value;
char addr_ascii[INET6_ADDRSTRLEN];
HOST_ENTRY *h;
/* reply icmp packet (hlen + ICMP_MINLEN) followed by "sent packet" (ip + icmp headers) */
if(reply_buf_len < hlen + ICMP_MINLEN + sizeof(struct ip) + ICMP_MINLEN) {
/* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
return 0;
}
sent_icmp = (struct icmp *) (reply_buf + hlen + ICMP_MINLEN + sizeof(struct ip));
if(sent_icmp->icmp_type != ICMP_ECHO || ntohs(sent_icmp->icmp_id) != ident) {
/* not caused by us */
return 0;
}
seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp_seq), &current_time);
if(seqmap_value == NULL) {
return 0;
}
getnameinfo(response_addr, response_addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
switch(icp->icmp_type) {
case ICMP_UNREACH:
h = table[seqmap_value->host_nr];
if( icp->icmp_code > ICMP_UNREACH_MAXTYPE ) {
print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s",
addr_ascii, h->host );
}
else {
print_warning("%s from %s for ICMP Echo sent to %s",
icmp_unreach_str[icp->icmp_code], addr_ascii, h->host);
}
if( inet_addr( h->host ) == INADDR_NONE )
print_warning(" (%s)", addr_ascii);
print_warning("\n" );
num_othericmprcvd++;
break;
case ICMP_SOURCEQUENCH:
case ICMP_REDIRECT:
case ICMP_TIMXCEED:
case ICMP_PARAMPROB:
h = table[seqmap_value->host_nr];
if(icp->icmp_type <= ICMP_TYPE_STR_MAX) {
print_warning("%s from %s for ICMP Echo sent to %s",
icmp_type_str[icp->icmp_type], addr_ascii, h->host );
}
else {
print_warning("ICMP %d from %s for ICMP Echo sent to %s",
icp->icmp_type, addr_ascii, h->host );
}
if( inet_addr( h->host ) == INADDR_NONE )
print_warning(" (%s)", addr_ascii );
print_warning( "\n" );
num_othericmprcvd++;
break;
}
return 0;
}
*id = ntohs(icp->icmp_id);
*seq = ntohs(icp->icmp_seq);
return 1; // success
}
#else
// IPV6
int decode_icmp_ipv6(
struct sockaddr *response_addr,
size_t response_addr_len,
char *reply_buf,
size_t reply_buf_len,
unsigned short *id,
unsigned short *seq
)
{
struct icmp6_hdr *icp;
if( reply_buf_len < sizeof(FPING_ICMPHDR) )
{
if( verbose_flag )
{
char buf[INET6_ADDRSTRLEN];
getnameinfo((struct sockaddr *)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
printf( "received packet too short for ICMP (%d bytes from %s)\n", (int) reply_buf_len, buf);
}
return 0; /* too short */
}
icp = (struct icmp6_hdr *) reply_buf;
if( icp->icmp6_type != ICMP6_ECHO_REPLY )
{
/* Handle other ICMP packets */
struct icmp6_hdr *sent_icmp;
SEQMAP_VALUE *seqmap_value;
char addr_ascii[INET6_ADDRSTRLEN];
HOST_ENTRY *h;
/* reply icmp packet (ICMP_MINLEN) followed by "sent packet" (ip + icmp headers) */
if(reply_buf_len < ICMP_MINLEN + sizeof(struct ip) + ICMP_MINLEN) {
/* discard ICMP message if we can't tell that it was caused by us (i.e. if the "sent packet" is not included). */
return 0;
}
sent_icmp = (struct icmp6_hdr *) (reply_buf + sizeof(struct icmp6_hdr) + sizeof(struct ip));
if(sent_icmp->icmp6_type != ICMP_ECHO || ntohs(sent_icmp->icmp6_id) != ident) {
/* not caused by us */
return 0;
}
seqmap_value = seqmap_fetch(ntohs(sent_icmp->icmp6_seq), &current_time);
if(seqmap_value == NULL) {
return 0;
}
getnameinfo(response_addr, response_addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
switch(icp->icmp6_type) {
case ICMP_UNREACH:
h = table[seqmap_value->host_nr];
if( icp->icmp6_code > ICMP_UNREACH_MAXTYPE ) {
print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s",
addr_ascii, h->host );
}
else {
print_warning("%s from %s for ICMP Echo sent to %s",
icmp_unreach_str[icp->icmp6_code], addr_ascii, h->host);
}
if( inet_addr( h->host ) == INADDR_NONE )
print_warning(" (%s)", addr_ascii);
print_warning("\n" );
num_othericmprcvd++;
break;
case ICMP_SOURCEQUENCH:
case ICMP_REDIRECT:
case ICMP_TIMXCEED:
case ICMP_PARAMPROB:
h = table[seqmap_value->host_nr];
if(icp->icmp6_type <= ICMP_TYPE_STR_MAX) {
print_warning("%s from %s for ICMP Echo sent to %s",
icmp_type_str[icp->icmp6_type], addr_ascii, h->host );
}
else {
print_warning("ICMP %d from %s for ICMP Echo sent to %s",
icp->icmp6_type, addr_ascii, h->host );
}
if( inet_addr( h->host ) == INADDR_NONE )
print_warning(" (%s)", addr_ascii );
print_warning( "\n" );
num_othericmprcvd++;
break;
}
return 0;
}
*id = ntohs(icp->icmp6_id);
*seq = ntohs(icp->icmp6_seq);
return 1;
}
#endif
int wait_for_reply(long wait_time) int wait_for_reply(long wait_time)
{ {
int result; int result;
static char buffer[4096]; static char buffer[4096];
struct sockaddr_storage response_addr; struct sockaddr_storage response_addr;
int hlen = 0;
FPING_ICMPHDR *icp;
int n, avg; int n, avg;
HOST_ENTRY *h; HOST_ENTRY *h;
long this_reply; long this_reply;
@ -1675,9 +1890,8 @@ int wait_for_reply(long wait_time)
struct timeval *sent_time; struct timeval *sent_time;
struct timeval recv_time; struct timeval recv_time;
SEQMAP_VALUE *seqmap_value; SEQMAP_VALUE *seqmap_value;
#ifndef IPV6 unsigned short id;
struct ip *ip; unsigned short seq;
#endif
// Wait for the socket to become ready // Wait for the socket to become ready
if(wait_time) { if(wait_time) {
@ -1708,73 +1922,30 @@ int wait_for_reply(long wait_time)
if(result <= 0) { if(result <= 0) {
return 0; return 0;
} }
// Process ICMP packet and retrieve id/seq
// unsigned short icmp_id;
// unsigned short icmp_seq
//#ifndef IPV6
// if(!process_icmp_ipv4(response_addr, sizeof(response_addr), buffer, sizeof(buffer),
// &icmp_id, &icmp_seq))
//#else
// if(!process_icmp_ipv6(response_addr, sizeof(response_addr), buffer, sizeof(buffer)
// &icmp_id, &icmp_seq))
//#endif
// {
// return(1);
// }
#ifndef IPV6
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 )
#else
if( result < sizeof(FPING_ICMPHDR) )
#endif
{
if( verbose_flag )
{
char buf[INET6_ADDRSTRLEN];
getnameinfo((struct sockaddr *)&response_addr, sizeof(response_addr), buf, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
printf( "received packet too short for ICMP (%d bytes from %s)\n", result, buf);
}
return( 1 ); /* too short */
}/* IF */
gettimeofday( &current_time, &tz ); gettimeofday( &current_time, &tz );
icp = ( FPING_ICMPHDR* )( buffer + hlen ); // Process ICMP packet and retrieve id/seq
#ifndef IPV6 #ifndef IPV6
if( icp->icmp_type != ICMP_ECHOREPLY ) if(!decode_icmp_ipv4(
#else #else
if( icp->icmp6_type != ICMP6_ECHO_REPLY ) if(!decode_icmp_ipv6(
#endif #endif
{ (struct sockaddr *) &response_addr,
/* handle some problem */ sizeof(response_addr),
if( handle_random_icmp( icp, (struct sockaddr *)&response_addr, sizeof(response_addr) ) ) buffer,
num_othericmprcvd++; sizeof(buffer),
return 1; &id,
}/* IF */ &seq)
) {
return(1);
}
#ifndef IPV6 if( id != ident ) {
if( ntohs(icp->icmp_id) != ident )
#else
if( ntohs(icp->icmp6_id) != ident )
#endif
return 1; /* packet received, but not the one we are looking for! */ return 1; /* packet received, but not the one we are looking for! */
}
#ifndef IPV6 seqmap_value = seqmap_fetch(seq, &current_time);
seqmap_value = seqmap_fetch(ntohs(icp->icmp_seq), &current_time);
#else
seqmap_value = seqmap_fetch(ntohs(icp->icmp6_seq), &current_time);
#endif
if(seqmap_value == NULL) { if(seqmap_value == NULL) {
return 1; return 1;
} }
@ -1924,118 +2095,6 @@ int wait_for_reply(long wait_time)
} /* wait_for_reply() */ } /* wait_for_reply() */
/************************************************************
Function: handle_random_icmp
************************************************************/
int handle_random_icmp(FPING_ICMPHDR *p, struct sockaddr *addr, socklen_t addr_len)
{
FPING_ICMPHDR *sent_icmp;
unsigned char *c;
HOST_ENTRY *h;
SEQMAP_VALUE *seqmap_value;
char addr_ascii[INET6_ADDRSTRLEN];
unsigned short icmp_type;
unsigned short icmp_code;
unsigned short sent_icmp_type;
unsigned short sent_icmp_seq;
unsigned short sent_icmp_id;
getnameinfo((struct sockaddr *) addr, addr_len, addr_ascii, INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
c = ( unsigned char* )p;
sent_icmp = ( FPING_ICMPHDR* )( c + 28 );
#ifndef IPV6
icmp_type = p->icmp_type;
icmp_code = p->icmp_code;
sent_icmp_type = sent_icmp->icmp_type;
sent_icmp_seq = sent_icmp->icmp_seq;
sent_icmp_id = sent_icmp->icmp_id;
#else
icmp_type = p->icmp6_type;
icmp_code = p->icmp6_code;
sent_icmp_type = sent_icmp->icmp6_type;
sent_icmp_seq = sent_icmp->icmp6_seq;
sent_icmp_id = sent_icmp->icmp6_id;
#endif
switch(icmp_type)
{
case ICMP_UNREACH:
seqmap_value = seqmap_fetch(ntohs(sent_icmp_seq), &current_time);
if( ( sent_icmp_type == ICMP_ECHO ) &&
( ntohs(sent_icmp_id) == ident ) &&
( seqmap_value != NULL ) )
{
/* this is a response to a ping we sent */
h = table[ntohs(sent_icmp_seq) % num_hosts];
if( icmp_code > ICMP_UNREACH_MAXTYPE ) {
print_warning("ICMP Unreachable (Invalid Code) from %s for ICMP Echo sent to %s",
addr_ascii, h->host );
}
else {
print_warning("%s from %s for ICMP Echo sent to %s",
icmp_unreach_str[icmp_code], addr_ascii, h->host);
}
if( inet_addr( h->host ) == INADDR_NONE )
print_warning(" (%s)", addr_ascii);
print_warning("\n" );
}
return 1;
case ICMP_SOURCEQUENCH:
case ICMP_REDIRECT:
case ICMP_TIMXCEED:
case ICMP_PARAMPROB:
seqmap_value = seqmap_fetch(ntohs(sent_icmp_seq), &current_time);
if( ( sent_icmp_type == ICMP_ECHO ) &&
( ntohs(sent_icmp_id) == ident ) &&
( seqmap_value != NULL ) )
{
/* this is a response to a ping we sent */
h = table[ntohs(sent_icmp_seq) % num_hosts];
if(icmp_type <= ICMP_TYPE_STR_MAX) {
print_warning("%s from %s for ICMP Echo sent to %s",
icmp_type_str[icmp_type], addr_ascii, h->host );
}
else {
print_warning("ICMP %d from %s for ICMP Echo sent to %s",
icmp_type, addr_ascii, h->host );
}
if( inet_addr( h->host ) == INADDR_NONE )
print_warning(" (%s)", addr_ascii );
print_warning( "\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: add_name Function: add_name

Loading…
Cancel
Save