diff options
author | Bjørn Mork <bjorn@mork.no> | 2011-11-09 16:08:09 +0100 |
---|---|---|
committer | Bjørn Mork <bjorn@mork.no> | 2011-11-09 16:20:38 +0100 |
commit | 60ec88353f7f35ebc1874bbdd2577e5665c03f0f (patch) | |
tree | 837195d8a8303858e2dd1e1cbd87d05186a8b4ba | |
parent | 6797bfacc8dab19bc5e383c6f3b631eeed324c5d (diff) |
simplify the chksum code
Signed-off-by: Bjørn Mork <bjorn@mork.no>
-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; } |