我在计算我的数据包的正确 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 位校验和。甚至假设字节数仅用于测试目的。sum 是我保存 32 位和的变量(当 16 位和溢出时,我可以将溢出保持在高 16 位一半)。随着 for i 循环遍历数据的 16 位块并将它们相加,增加数据指针(增加 16 位它是 u_short),有一个 if 测试来跳过标头的校验和部分.. 可以看出在 rfc 791 中,校验和部分是标头中的第 6 个 16 位块(在我的情况下为 5,因为我从 0 开始计数)。数据相加后,我将高 16 位添加到低 16 位,并将 32 位 int 折叠成 16 位短。最后,我反转位(一个补码)并将 32 位缩短为 16 位并将其返回给调用者函数。
这没有提供从 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
查克:3db8 查克:0264
查克:9615 查克:0000
chck:edef mychck:ff64
查克:59f1 查克:0164
查克:49f1 查克:0264
查克:a3d4 查克:0c77
查克:e36b 查克:0264
chck:aad4 mychck:0c77
查克:46d1 查克:0c77
查克:f40b 查克:0264
查克:a8d4 查克:0c77
我下载了在网上运行的其他代码示例,当 pcap 将数据包转发到我的代码时,这些示例都没有给出每个 IP 标头包含的结果。
可以的话请帮忙,谢谢。