From 7885effce1b8cb087bb76c278537f6bbc3cf33ff Mon Sep 17 00:00:00 2001 From: "Andrey Jr. Melnikov" Date: Fri, 9 Oct 2015 12:55:43 +0300 Subject: [PATCH 1/2] Fix checksum generation --- src/socket4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/socket4.c b/src/socket4.c index f1bdf5e..ac760fb 100644 --- a/src/socket4.c +++ b/src/socket4.c @@ -96,6 +96,7 @@ int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, icp->icmp_type = ICMP_ECHO; icp->icmp_code = 0; + icp->icmp_cksum = 0; icp->icmp_seq = htons(icmp_seq_nr); icp->icmp_id = htons(icmp_id_nr); From 4e14f407aac419609556871a0ac965009460277e Mon Sep 17 00:00:00 2001 From: "Andrey Jr. Melnikov" Date: Fri, 9 Oct 2015 13:05:05 +0300 Subject: [PATCH 2/2] Use more readably cksum variant and move function into v4 sockets code. --- src/fping.c | 49 ------------------------------------------------- src/socket4.c | 19 ++++++++++++++++++- 2 files changed, 18 insertions(+), 50 deletions(-) diff --git a/src/fping.c b/src/fping.c index 4a6b5d9..9e9aa5f 100644 --- a/src/fping.c +++ b/src/fping.c @@ -316,7 +316,6 @@ char *na_cat( char *name, struct in_addr ipaddr ); void crash_and_burn( char *message ); void errno_crash_and_burn( char *message ); char *get_host_by_address( struct in_addr in ); -int in_cksum( unsigned short *p, int n ); void u_sleep( int u_sec ); int recvfrom_wto( int s, char *buf, int len, struct sockaddr *saddr, socklen_t *saddr_len, long timo ); void remove_job( HOST_ENTRY *h ); @@ -1799,54 +1798,6 @@ int handle_random_icmp(FPING_ICMPHDR *p, struct sockaddr *addr, socklen_t addr_l } /* handle_random_icmp() */ -/************************************************************ - - Function: in_cksum - -************************************************************* - - Inputs: unsigned 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. - -************************************************************/ - -int in_cksum( unsigned short *p, int n ) -{ - register unsigned short answer; - register long sum = 0; - unsigned short odd_byte = 0; - - while( n > 1 ) - { - sum += *p++; - n -= 2; - - }/* WHILE */ - - - /* mop up an odd byte, if necessary */ - if( n == 1 ) - { - *( unsigned char* )( &odd_byte ) = *( unsigned 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 diff --git a/src/socket4.c b/src/socket4.c index ac760fb..12b7803 100644 --- a/src/socket4.c +++ b/src/socket4.c @@ -87,6 +87,23 @@ void socket_set_src_addr_ipv4(int s, FPING_INADDR src_addr) errno_crash_and_burn( "cannot bind source address" ); } +unsigned short calcsum(unsigned short *buffer, int length) +{ + unsigned long sum; + + // initialize sum to zero and loop until length (in words) is 0 + for (sum=0; length>1; length-=2) // sizeof() returns number of bytes, we're interested in number of words + sum += *buffer++; // add 1 word of buffer to sum and proceed to the next + + // we may have an extra byte + if (length==1) + sum += (char)*buffer; + + sum = (sum >> 16) + (sum & 0xFFFF); // add high 16 to low 16 + sum += (sum >> 16); // add carry + return ~sum; +} + int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, uint16_t icmp_seq_nr, uint16_t icmp_id_nr) { struct icmp *icp; @@ -106,7 +123,7 @@ int socket_sendto_ping_ipv4(int s, struct sockaddr *saddr, socklen_t saddr_len, } } - icp->icmp_cksum = in_cksum((unsigned short*) icp, ping_pkt_size ); + icp->icmp_cksum = calcsum((unsigned short *) icp, ping_pkt_size); n = sendto(s, icp, ping_pkt_size, 0, saddr, saddr_len);