How is the ospf checksum calculated?

1.4k views Asked by At

I'm having trouble getting an accurate checksum calculated. My router is rejecting my Hello messages because of it. Here's the package in hex (starting from the ospf header)

                                           vv vv <-- my program's checksum
0000   02 01 00 30 c0 a8 03 0a 00 00 00 00 f3 84 00 00  ...0............
0010   00 00 00 00 00 00 00 00 ff ff ff 00 00 0a 00 01  ................
0020   00 00 00 28 c0 a8 03 0a c0 a8 03 0a              ...(........

Wireshark calls 0xf384 bogus and says the expected value is 0xb382. I've confirmed that my algorythm picks the bytes in pairs and in the right order and then adds them together:

0201 + 0030 + c0a8 + ... + 030a

There is no authentication to worry about. We weren't even taught how to set it up. Lastly, here's my shot at calculating the checksum:

OspfHeader result;

result.Type = type;
result.VersionNumber = 0x02;
result.PacketLength = htons(24 + content_len);
result.AuthType = htons(auth_type);
result.AuthValue = auth_val;
result.AreaId = area_id;
result.RouterId = router_id;

uint16_t header_buffer[12];
memcpy(header_buffer, &result, 24);

uint32_t checksum;
for(int i = 0; i < 8; i++)
{
    checksum += ntohs(header_buffer[i]);
    checksum = (checksum & 0xFFFF) + (checksum >> 16);
}

for(int i = 0; i + 1 < content_len; i += 2)
{
    checksum += (content_buffer[i] << 8) + content_buffer[i+1];
    checksum = (checksum & 0xFFF) + (checksum >> 16);
}

result.Checksum = htons(checksum xor 0xFFFF);

return result;

I'm not sure where exactly I messed up here. Any clues?

1

There are 1 answers

0
Andrew On
Mac_3.2.57$cat ospfCheckSum2.c
#include <stdio.h>

int main(void){

    // array was wrong len
    unsigned short header_buffer[22] = {
        0x0201, 0x0030, 0xc0a8, 0x030a,
        0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000,
        0xffff, 0xff00, 0x000a, 0x0001,
        0x0000, 0x0028, 0xc0a8, 0x030a,
        0xc0a8, 0x030a
    };
    // note ospf len is also wrong, BTW
    
    // was not init'd
    unsigned int checksum = 0;

    // was only scanning 8 vs 22
    for(int i = 0; i < 22; i++)
    {
        checksum += header_buffer[i];
        checksum = (checksum & 0xFFFF) + (checksum >> 16);
    }
    
    // len not odd, so this is not needed
    //for(int i = 0; i + 1 < content_len; i += 2)
    //{
    //    checksum += (content_buffer[i] << 8) + content_buffer[i+1];
    //    checksum = (checksum & 0xFFF) + (checksum >> 16);
    //}
    
    printf("result is %04x\n", checksum ^ 0xFFFF); // no "xor" for me (why not do ~ instead?)

    // also: where/what is: content_len, content_buffer, result, OspfHeader 

    return(0);
}
Mac_3.2.57$cc ospfCheckSum2.c
Mac_3.2.57$./a.out 
result is b382
Mac_3.2.57$