计算 ICMPv6 的校验和

网络工程 协议理论 国际会议 射频卡 校验和 icmpv6
2021-07-12 08:23:29

参考 http://www.faqs.org/rfcs/rfc1071.html,我尝试推导出用于计算 ICMPv6 校验和的 c 代码。但是通过wireshark检查校验和解析,我发现从我的代码中得到的答案是错误的......

由wireshark解析的校验和是0x8e73。

以下是我的代码,与 RFC 中提到的完全相同。注意:数组数据是从 ICMPv6 获得的原始数据

unsigned short checksum(unsigned short *addr, unsigned short count)
{
    unsigned long sum;

    sum = 0;
    while (count > 1) {
            sum += *(unsigned short*)addr++;
            count -= 2;
            printf("sum is %x\n", sum);
    }

    /*  Add left-over byte, if any */
    if (count){
            sum += *(unsigned char *)addr;
            printf("in side left-over byte\n");
    }
    /*  Fold 32-bit sum to 16 bits */
    while (sum >> 16) {
            sum  = (sum & 0xffff) + (sum >> 16);
            printf("IN while:sum is %x\n", sum);
    }
    printf("sum is %x\n", sum);
    return (unsigned short)(~sum);
}

int main() {
    unsigned short count = 32;
    //data is the raw data for ICMPv6 got from wireshark, and I put the checksum field as 0x0000
    unsigned short data[] = {0x8800, 0x0000, 0x6000, 0x0000, 0xfe80, 0x0000, 0x0000, 0x0000, 0xb96b, 0x982f, 0x447a, 0x6a80, 0x0201, 0x6057, 0x187d, 0x7fad};


    printf("check sum is %x\n", checksum(data, 32));
    return 0;
}
2个回答

ICMP 和 ICMPv6 是两种不同的协议。对于 ICMPv6 校验和调用,请参阅RFC2463第 2.3 节和那里引用的文档。

感谢 Jens 的帮助。在寻找 RFC2463 之后。我为伪标头预先附加了以下数据。

unsigned short src_ip[8] = {0} //fill the source IP
unsigned short dst_ip[8] = {0} //fill the destination IP
//0x0020 is the packet length of ICMPv6
//fill 3bytes of zero and 0x3a is the type of ICMPv6, so we have
//0x00, 0x003a
unsigned short remain[] = {0x0020, 0x0000, 0x003a} 
unsigned short data[] = {} //as before

所以把这些数据拼接起来,发送给check_sum算法【这部分和icmp一样】,我们就可以推导出正确的校验和了!