diff options
-rw-r--r-- | ldra.c | 28 |
1 files changed, 20 insertions, 8 deletions
@@ -118,28 +118,40 @@ int print_hex(const char *buf, size_t len) { fprintf(stderr, "\n\n"); } -u_int32_t complement(u_int32_t sum) { - /* carry adjustment */ + +/* creating an UDP checksum isn't all that magic. you can checksum + parts individually and add up the result and carry later, provided + that all parts except possibly the last one has an even number of + bytes. +*/ + +/* fixup carry and complement the sum, returning it in network byte order */ +u_int16_t complement(u_int32_t sum) { + /* carry adjustment */ while (sum >> 16) sum = (sum & 0xffff) + (sum >> 16); - sum = ~sum & 0xffff; - return (htons(sum)); + /* return the complement sum in network byte order */ + return htons(~sum); } -/* calulate a possibly partial checksum */ +/* calulate a possibly partial checksum + We consider buf a stream of 16bit numbers in network byte order. + Just sum them up, and leave the carry adjustment for later +*/ u_int32_t chksum(u_int8_t *buf, size_t n) { u_int32_t sum = 0; int i; - for (i = 0; i <(n & ~1U); i += 2) - sum += (u_int16_t)ntohs(*((u_int16_t *)(buf + i))); + /* this will limit the max buf length, but we cannot handle that large packets anyway */ + for (i = 0; i < (n & 0xfffe); i += 2) + sum += ntohs(*(u_int16_t *)(buf + i)); /* odd number of bytes? */ if (i < n) sum += buf[i] << 8; - return (sum); + return sum; } |