IP校验和计算不正确

时间:2012-09-10 22:47:09

标签: networking ip checksum

我无法计算我的数据包的正确ip校验和。这是代码,我将解释我在做什么和出了什么问题..

u_short checkSum(u_short *data, int byteCount){
int i, sum = 0;

for(i = 0; i < byteCount/2; i++){
    if(i == 5) continue;
    sum += *data++;
}

while(sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
return (u_short)~sum;
}

首先,我的函数通用于计算发送数据的16位校验和。假设bytecount甚至仅用于测试目的。 sum是我保持32位和的变量(当16位和溢出时,我可以将溢出保持在高16位的一半)。使用for i循环遍历数据的16位块并将它们相加,递增数据指针(通过16位,它是u_short),如果测试跳过标题的校验和部分,则有一个...正如可以看到的那样在rfc 791中,校验和部分是标题中的第6个16位块(在我的情况下为5,因为我从0开始计数)。在对数据求和之后,我将高16位加到低16位,并将32位int加到16位短路中。最后,我将这些位(一个补码)反转并缩短为16位的32位并将其返回给调用函数。

这不提供从pcap发送给我的正确校验和(我用它来嗅探数据包)。这就是我如何调用我的函数来比较结果..

if(etherHdr->ether_type == 8){
    ipHdr = (struct ip*) (packet + sizeof(struct ether_header));
    printf("chck: %04x mychck: %04x\n\n", ipHdr->ip_sum, checkSum((u_short*)ipHdr, sizeof(struct ip)));
}

if仅过滤掉IP数据包(以太网头类型字段中的代码8)..

这是我运行程序时的输出..

chck:ef66 mychck:06ee

chck:3db8 mychck:0264

chck:9615 mychck:0000

chck:edef mychck:ff64

chck:59f1 mychck:0164

chck:49f1 mychck:0264

chck:a3d4 mychck:0c77

chck:e36b mychck:0264

chck:aad4 mychck:0c77

chck:46d1 mychck:0c77

chck:f40b mychck:0264

chck:a8d4 mychck:0c77

我下载了在网上运行的其他代码示例,当pcap将数据包转发给我的代码时,这些代码都没有给出每个IP头包含的结果。

请尽可能帮助,谢谢。

2 个答案:

答案 0 :(得分:1)

RFC 1071中给出了正确的方法。你很近,但还没有雪茄。

答案 1 :(得分:0)

也许尝试使用这个源代码来计算校验和,我正在使用它,它对我的​​软件很有用。

            int
checksum
            (unsigned short *   data,
            int         length)
{
    register int                nleft   = length;
    register unsigned short     *   w   = data;
    register int                sum = 0;
    unsigned short              answer  = 0;

    while (nleft > 1)
    {
        sum     += *w++;
        nleft   -= 2;
    }

    if (nleft == 1)
    {
        *(unsigned char *)(&answer) = *(unsigned char *)w;
        sum+=answer;
    }

    sum = (sum>>16) + (sum & 0xffff);
    sum += (sum>>16);
    answer = ~sum;

    return answer;
}