How do I validate the ICMPv6 checksum? (Why am do I keep getting a checksum of 0x3fff?)

前端 未结 3 1809
不知归路
不知归路 2021-01-13 05:05

I\'m working on a Linux userspace program that receives IPv6 router advertisement packets. As part of RFC4861 I need to verify the ICMPv6 checksum. Based on my research, mos

3条回答
  •  梦毁少年i
    2021-01-13 06:02

    The while loop is overkill. The body will only happen once.

    while (checksum >> 16 != 0)
        checksum = (checksum & 0xffff) + (checksum >> 16);
    
    checksum = ~checksum;
    
    return (uint16_t)checksum;
    

    Instead

    checksum += checksum >> 16;
    
    return (uint16_t)~checksum;
    

    This is unnecessary. len is always 16-bit

    temp.dword = htonl(len);
    checksum += temp.word[0];
    checksum += temp.word[1];
    

    This is unnecessary. The constant is always 00 00 00 58, so just add 58.

    temp.byte[0] = 0;
    temp.byte[1] = 0;
    temp.byte[2] = 0;
    temp.byte[3] = 58; // ICMPv6
    checksum += temp.word[0];
    checksum += temp.word[1];
    

    Your algorithm looks generally right otherwise, except for the way you handle the endianness of the integers and the last byte odd-numbered byte. From how I read the protocol, the bytes are to be summed in big-endian order, i.e., the bytes 0xAB 0xCD are to be interpreted as the 16-bit 0xABCD. Your code depends on the ordering of your machine.

    The order that the integers are built will affect the number of carries, which you are adding correctly into the checksum. But if your code matches your target machine, then the last odd-numbered byte is wrong. 0xAB would result in 0xAB00, not 0x00AB as written.

提交回复
热议问题