c++ - Understanding the TCP checksum function -
i believe tcp checksum function following:
- break pseudoheader , tcp segment header , data 2 byte blocks.
- add 1 byte padding of 0s end of last block if it's not 2 bytes long, make 2 bytes.
- take one's complement of sum tcp checksum.
sounds simple enough. hence wrote own generic checksum function:
#include <inttypes.h> #include <arpa/inet.h> uint16_t checksum(uint16_t * data, int size) { uint16_t sum = 0; int = 0, length = size / 2; while (i < length) sum += data[i++]; if (size % 2) sum += data[i] & 0xff00; return htons(~sum); } however other people have written checksum functions seem more complicated. example:
uint16_t checksum(uint16_t * addr, int len) { int nleft = len; int sum = 0; uint16_t * w = addr; uint16_t answer = 0; while (nleft > 1) { sum += *w++; nleft -= sizeof(uint16_t); } if (nleft == 1) { *(uint8_t *) (&answer) = *(uint8_t *) w; sum += answer; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); answer = ~sum; return (answer); } i have few questions regarding code:
- what statement
*(uint8_t *) (&answer) = *(uint8_t *) w;do? why take sum as:
sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16);did way calculate tcp checksum change?
i don't see why sum = (sum >> 16) + (sum & 0xffff). consider sum 0xabcd:
0xabcd >> 16 == 0x0000 0xabcd & 0xffff == 0xabcd 0x0000 + 0xabcd == 0xabcd it seems redundant step. same goes next statement sum += (sum >> 16).
the checksum function appears big-endian processors only.
the first while loop optimized speed.
the &answer trick loads last byte (if there odd number of bytes) high byte of answer, leaving low byte zero, similar code data[i] & 0xff00. way works this
1) take address of answer (&answer) 2) convert byte pointer (uint8_t *) 2a) on big endian processor first byte of 16-bit quantity high byte 3) overwrite high byte last byte of data the checksum supposed computed carries added in. it's assumed here code running on machine int 32-bits. therefore, (sum & 0xffff) 16-bit checksum, , (sum >> 16) carry bits (if any) need added in. hence, line
sum = (sum >> 16) + (sum & 0xffff); adjusts sum include carries. however, line of code generate carry bit. next line sum += (sum >> 16) adds carry (if any) checksum.
finally, take ones-complement of answer. note htons not used since whole function implicitly assumes running on big endian processor.
Comments
Post a Comment