On Mon, May 18, 2020 at 03:50:05PM +0200, Patrick Wildt wrote:
> 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?
There are other versions of in_cksum in our tree.
Like: ./usr.sbin/ospfd/in_cksum.c
I'm surprised that the libsa code does no htons / ntohs conversions.
Also after looking at the ospfd/in_cksum.c code I wonder if the htons /
ntohs are actually reversed in that that code...
> 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);
>
--
:wq Claudio