Question

As described in RFC1071, an extra 0-byte should be added to the last byte when calculating checksum in the situation of odd count of bytes:

enter image description here

But in the "C" code algorithm, only the last byte is added:

enter image description here

The above code does work on little-endian machine where [Z,0] equals Z, but I think there's some problem on big-endian one where [Z,0] equals Z*256.

So I wonder whether the example "C" code in RFC1071 only works on little-endian machine?

-------------New Added---------------

There's one more example of "breaking the sum into two groups" described in RFC1071:

enter image description here

We can just take the data here (addr[]={0x00, 0x01, 0xf2}) for example:

enter image description here

Here, "standard" represents the situation described in the formula [2], while "C-code" representing the C code algorithm situation.

As we can see, in "standard" situation, the final sum is f201 regardless of endian-difference since there's no endian-issue with the abstract form of [Z,0] after "Swap". But it matters in "C-code" situation because f2 is always the low-byte whether in big-endian or in little-endian.

Thus, the checksum is variable with the same data(addr&count) on different endian.

Was it helpful?

Solution

I think you're right. The code in the RFC adds the last byte in as low-order, regardless of whether it is on a litte-endian or big-endian machine.

In these examples of code on the web we see they have taken special care with the last byte:

https://github.com/sjaeckel/wireshark/blob/master/epan/in_cksum.c

and in

http://www.opensource.apple.com/source/tcpdump/tcpdump-23/tcpdump/print-ip.c

it does this:

if (nleft == 1)
    sum += htons(*(u_char *)w<<8);

Which means that this text in the RFC is incorrect:

Therefore, the sum may be calculated in exactly the same way regardless of the byte order ("big-endian" or "little-endian") of the underlaying hardware. For example, assume a "little- endian" machine summing data that is stored in memory in network ("big-endian") order. Fetching each 16-bit word will swap bytes, resulting in the sum; however, storing the result back into memory will swap the sum back into network byte order.

OTHER TIPS

The following code in place of the original odd byte handling is portable (i.e. will work on both big- and little-endian machines), and doesn't depend on an external function:

if (count > 0)
{
    char buf2[2] = {*addr, 0};
    sum += *(unsigned short *)buf2;
}

(Assumes addr is char * or const char *).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top