tcpchecksum calculator
I've written small code for calculating tcp checksum. This is working fine if TCP payload is of even length. But if it is odd length, it is coming 1 less. Can someone help me identifying where the issue(s) is ....
static uint32_t check_sum_step( uint32_t check_sum, const uint16_t new )
{
uint32_t over_flow;
check_sum += htons(new);
while( check_sum & 0xffff0000 )
{
over_flow = check_sum >> 16;
check_sum &= 0x0000ffff;
check_sum += over_flow;
}
return check_sum;
}
uint16_t tcp_udp_check_sum_16_rfc( char const * const begin_ptr, char * const end_ptr, uint8_t *src_ip_8, uint8_t const *dest_ip_8, const uint8_t ip_addr_size_bits, const uint8_t protocol )
{
uint16_t const * const begin = (uint16_t*)begin_ptr;
uint16_t const * const end = (uint16_t*)end_ptr;
uint16_t const * const src_ip_16 = (uint16_t*)src_ip_8;
uint16_t const * const dest_ip_16 = (uint16_t*)dest_ip_8;
const uint8_t ip_addr_size_bits_16 = ip_addr_size_bits/16;
uint16_t const *addr = begin;
uint32_t check_sum = 0;
uint16_t i;
for( i=0; i<ip_addr_size_bits_16; i++ )
{
check_sum = check_sum_step( check_sum, src_ip_16[i] );
check_sum = check_sum_step( check_sum, dest_ip_16[i] );
}
end_ptr[0] = 0;
for( ; addr<end; addr++ )
{
check_sum = check_sum_step( check_sum, addr[0] );
}
check_sum = check_sum + protocol + ( (uint16_t)( end_ptr - begin_ptr ) );
check_sum = check_sum_step( check_sum, 0 );
check_sum = ~check_sum;
return (uint16_t)check_sum;
}
/* int main()
{
uint8_t src_ipv4_addr[4] = { 192, 168, 10, 11 };
uint8_t dest_ipv4_addr[4] = { 192, 168, 10, 22 };
char tcp_hdr_payload[] = { 0xb3, 0xa4, 0x2a, 0xf8, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0xc9, 0x50, 0x10, 0x1b, 0x5d, 0xc4, 0xad, 0x00, 0x00, 0x62, 0x62, 0x62, 0x62, 0x03 };
uint16_t checksum = tcp_udp_check_sum_16_rfc( tcp_hdr_payload, tcp_hdr_payload+20+5, src_ipv4_addr, dest_ipv4_addr, 32, IPPROTO_TCP );
printf( "%s %d checksum: %u\n", __func__, __LINE__, checksum );
}
*/