summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldra.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/ldra.c b/ldra.c
index bdf4fbc..a6074d9 100644
--- a/ldra.c
+++ b/ldra.c
@@ -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;
}