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
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