阅读:2309回复:10
为什么ip包的包头20个字节相加的结果不是0xffff?
passthru mpsend函数中,如果packet有ip包,将包头每2个字节相加,结果应当是0xffff。但我测试的结果是:对tcp来说和为0xfffd,udp为0xb6d5?
很困惑,哪位大虾能指点迷津? |
|
|
沙发#
发布于:2002-07-10 15:32
passthru mpsend函数中,如果packet有ip包,将包头每2个字节相加,结果应当是0xffff。但我测试的结果是:对tcp来说和为0xfffd,udp为0xb6d5? ip chksum计算的时候需要把一些会被router修改的字段 设置为0。chksum的计算你在任何一本书里面都找得到, 很多地方也有source------不过大多数是汇编写的:-)。 |
|
|
板凳#
发布于:2002-07-10 16:18
老胡,俺搞不懂唉。
ip checksum的计算规则不是:先清零校验和字段,然后对ip header数据每16位求和,然后结果取反 吗? 如果按这个规则来说的话,ip header每16位的和(包含校验和)应当为0xffff才对呀。 按照你上一个帖子的说法,ip checksum 可能不是ip层做的,如果不在ip层做,ip checksum域可能为一个随机数或一个常数,(由于ip头不同)按照验证算法得到的值应该是不一样的。但是对所有tcp包我得到的验证值总是0xfffd。 请老胡指点。 |
|
|
地板#
发布于:2002-07-10 16:34
老胡,俺搞不懂唉。 你这个0xfffd是怎么得到的? 在imd里?(这有可能是一样的,因为imd得到的是一个没有计算 过ipchksum的数据包) 还是你用sniffer抓了个包看了看?(这不可能总是一样,除非 你的tcp包长度都一样,目的地址也一样) |
|
|
地下室#
发布于:2002-07-10 16:58
你这个0xfffd是怎么得到的? 老胡,我的0xfffd是ip header中每16位数据的和(包含校验和),不是校验和――checksum。 如果按照ip header的验证算法――ip header中每16位数据的和(包含校验和),它应当是0xffff才对。 我在imd中得到的这个值。 即使ip层随便填一个值或什么都不填,ip header的其他部分是不尽相同的,那么它们由验证算法得到的值也应该是不同的。 |
|
|
5楼#
发布于:2002-07-10 17:15
[quote]你这个0xfffd是怎么得到的? 老胡,我的0xfffd是ip header中每16位数据的和(包含校验和),不是校验和――checksum。 如果按照ip header的验证算法――ip header中每16位数据的和(包含校验和),它应当是0xffff才对。 我在imd中得到的这个值。 即使ip层随便填一个值或什么都不填,ip header的其他部分是不尽相同的,那么它们由验证算法得到的值也应该是不同的。 [/quote] 既然你在imd中得到的这个值... 我理解为你在imd中作了一个循环,自己把ipheader加了一遍。 可能性如下: 1、你算错了。 2、这个值是正常的,因为ip层交下来的数据中并不包括ipchksum, 所以出现任何值都是有可能的。请注意,ip层的动作很奇怪,并 不是一个包不算就所有的包都不算,这个似乎取决于某个隐藏在 某处的一个状态,我找了很久也没有找到,只是发现当ip发现 网卡有taskoffload功能的时候,ip自己算还是不算,完全取决 于ip自己,ip如果算了的话,会在oob上告诉网卡,如果不算, 也会在oob中告诉网卡。在这里做出任何假设都会导致错误。 (除非真正搞清楚了ip背后的策略,但是似乎是undocument的) 我的建议:你用sniffer抓一个数据包,注意这个sniffer最好在 目标主机上,或者在另外一个主机上,不要在发送主机上。 看看抓到的包的ip头和你imd中的ip头的区别。 |
|
|
6楼#
发布于:2002-07-10 17:21
谢谢老胡!!!!!
|
|
|
7楼#
发布于:2002-07-10 18:16
刚拜读两位的讨论。
很有收获,在此我问个可能很低级的问题,望两位赐教。 对于ipchksum的算法,有的书上是这样讲的:对ip首部每个16bit进行二进制反码求和。也有的书上是这样讲的:对ip首部每个16bit进行求和的反码。最可气的是清华的tcp/ip那本书上是:异或的反吗(肯定不对)。 另外看见的算法是:SHORT iphdr_cksum(USHORT *iph) { USHORT i; ULONG sum; i = 0; sum = 0; while(i++ < (sizeof(IP_HEADER)/2)) sum += *iph++; sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); sum = ~sum; return (USHORT)sum; } 感觉这可能是标准算法。 不过,这样检查校验的算法就不是:每16bit的和就不是0xffff了。 高不太明白。 还是留给明白的人解释吧。 嗬嗬! |
|
|
8楼#
发布于:2002-07-11 18:08
果真是这个算法。
另还有已优化的算法,写得不错。 看样,有病不能乱投医呀! 呵呵! |
|
|
9楼#
发布于:2002-07-11 22:47
呵呵!你的程序的算法得到的结果是对的!和什么详解上面的说法不一样!
|
|
10楼#
发布于:2002-07-12 22:43
[quote] [quote]你这个0xfffd是怎么得到的? 老胡,我的0xfffd是ip header中每16位数据的和(包含校验和),不是校验和――checksum。 如果按照ip header的验证算法――ip header中每16位数据的和(包含校验和),它应当是0xffff才对。 我在imd中得到的这个值。 即使ip层随便填一个值或什么都不填,ip header的其他部分是不尽相同的,那么它们由验证算法得到的值也应该是不同的。 [/quote] 既然你在imd中得到的这个值... 我理解为你在imd中作了一个循环,自己把ipheader加了一遍。 可能性如下: 1、你算错了。 2、这个值是正常的,因为ip层交下来的数据中并不包括ipchksum, 所以出现任何值都是有可能的。请注意,ip层的动作很奇怪,并 不是一个包不算就所有的包都不算,这个似乎取决于某个隐藏在 某处的一个状态,我找了很久也没有找到,只是发现当ip发现 网卡有taskoffload功能的时候,ip自己算还是不算,完全取决 于ip自己,ip如果算了的话,会在oob上告诉网卡,如果不算, 也会在oob中告诉网卡。在这里做出任何假设都会导致错误。 (除非真正搞清楚了ip背后的策略,但是似乎是undocument的) 我的建议:你用sniffer抓一个数据包,注意这个sniffer最好在 目标主机上,或者在另外一个主机上,不要在发送主机上。 看看抓到的包的ip头和你imd中的ip头的区别。 [/quote] 是由网卡来计算CHECKSUM还是由PROTOCOL来计算CHECKSUM可以通过 对NIC的发送OID查询来获得 OID_TCP_TASK_OFFLOAD task = NDIS_TASK_TCP_IP_CHECKSUM |
|
|