RFC 1071 - Calculating IP header checksum confusion in C

2.4k views Asked by At

I'm trying to calculate a proper IP header checksum by using the example C code of RFC 1071 but have a problem that is best described with code:

Setting up the IP Header:

#include <linux/ip.h>

typedef struct iphdr tipheader;

int main(int argc, char **argv)
{
    tipheader * iphead = (tipheader *) malloc(sizeof(tipheader));
    iphead->ihl = 5;
    iphead->version = 4;
    iphead->tos = 0;
    iphead->tot_len = 60;
    ....
    unsigned short checksum = getChecksum((unsigned short *) iphead, 20);
}

Checksum function:

unsigned short getChecksum(unsigned short * iphead, int count)
{
    unsigned long int sum = 0;
    unsigned short checksum = 0;

    printf("\nStarting adress: %p\n", iphead);

    while(count > 1) {
        sum += * (unsigned short *) (iphead);
        count -=2;
        printf("a: %p, content is: %d, new sum: %ld\n", iphead, (unsigned short) *(iphead), sum);
        iphead++;
    }

    if(count > 0) {
        sum += * (unsigned short *) (iphead);
    }

    while(sum >> 16) {
        sum = (sum & 0xffff) + (sum >> 16);
    }

    checksum = ~sum;

    return checksum;
}

Iterating over the memory pointed to by iphead with an unsigned short pointer displays the following output after the first two iterations:

Starting address: 0x603090
a: 0x603090, content is: 69, new sum: 69
a: 0x603092, content is: 60, new sum: 129

So the pointer works 'as expected' and increases by 2 for every iteration. But why is the content of the first two bytes interpreted as 69 (0x45) where it should be 0x4500

Thx for the clarification

1

There are 1 answers

2
user3629249 On

the first two fields are only 4 bits long so, in memory is 0x4500.

However, due to Endian'ness, it is read as 0x0045.

When printing, unless forced otherwise, leading 0s are suppressed.

so the result is 0x45 = 69