Hi,
I was trying to tftpboot and had an issue with files of odd-length.
As it turns out, I think the in_cksum() that's called for UDP payload
cannot handle a payload length that's not aligned to 16 bytes.
I don't know how in_cksum() is supposed to work exactly, but it looks
like the first step is summing up all bytes. The code is using 16-
byte blocks, apart from some oddbyte magic.
First of all, why is there a while loop around code that already
consumes the whole length? That can be done in a single step
without the loop. Why does it continue of there's an "oddbyte"?
If I simplify that whole construct, consuming in 16-bytes step
until there's only one left, then summing that one, in_cksum()
works for me.
Can someone please help me have a look?
Patrick
diff --git a/sys/lib/libsa/in_cksum.c b/sys/lib/libsa/in_cksum.c
index d3f2e6ac978..57ded38a7b7 100644
--- a/sys/lib/libsa/in_cksum.c
+++ b/sys/lib/libsa/in_cksum.c
@@ -59,31 +59,24 @@
int
in_cksum(const void *p, int len)
{
- int sum = 0, oddbyte = 0, v = 0;
const u_char *cp = p;
+ int sum = 0;
/* we assume < 2^16 bytes being summed */
- while (len > 0) {
- if (oddbyte) {
- sum += v + *cp++;
- len--;
- }
+ while (len > 1) {
if (((long)cp & 1) == 0) {
- while ((len -= 2) >= 0) {
- sum += *(const u_short *)cp;
- cp += 2;
- }
+ sum += *(const u_short *)cp;
+ cp += 2;
} else {
- while ((len -= 2) >= 0) {
- sum += *cp++ << 8;
- sum += *cp++;
- }
+ sum += *cp++ << 8;
+ sum += *cp++;
}
- if ((oddbyte = len & 1) != 0)
- v = *cp << 8;
+ len -= 2;
+ }
+ if (len > 0) {
+ sum += *cp++;
+ len--;
}
- if (oddbyte)
- sum += v;
sum = (sum >> 16) + (sum & 0xffff); /* add in accumulated carries */
sum += sum >> 16; /* add potential last carry */
return (0xffff & ~sum);