我无法计算我的数据包的正确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头包含的结果。
请尽可能帮助,谢谢。
答案 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;
}