【发布时间】:2015-12-12 20:38:05
【问题描述】:
我想问一下我根据ICMPv6协议计算16位校验和的解决方案是否正确。我尝试关注Wikipedia,但我主要不确定两件事。
首先是the packet length 的意思——它是没有校验和的整个ICMPv6 数据包的数据包长度,还是只有有效负载?它是否像 IPv6 一样以八位字节表示?这个 ICMPv6 回显请求的长度是多少?
6000 # beginning of IPv6 packet
0000 0000 3a00 FE80 0000 0000 0000 0202
B3FF FE1E 8329 FE80 0000 0000 0000 0202
B3FF FE1E 8330
8000 xxxx # this is beginning of the ICMP packet - type and checksum
a088 0000 0001 # from here including this line I compute the length
0203 0405 0607 0809 0a0b 0c0d 0e0f 1011
1213 1415 1617 1819 1a1b 1c1d 1e1f 2021
2223 2425 2627 2829 2a2b 2c2d 2e2f 3031
3233
这是否意味着上面的长度是 56 个八位字节,正如我在下面的代码中所说的那样?
然后我很难理解这个(再次来自 wiki)。
在这个伪标头之后,校验和继续以 ICMPv6 消息,其中校验和最初设置为零。这 校验和计算是根据互联网协议执行的 标准使用 16 位的补码求和,然后是 补充校验和本身并将其插入校验和 字段
这是否意味着我也应该将校验和字段上带有 0000 的整个 ICMPv6 帧添加到校验和中?
我尝试在 Python 中为此编写一个简单的程序:
# START OF Pseudo header
# we are doing 16 bit checksum hence quadruplets
## source IP
sip = ['FE80', '0000', '0000', '0000', '0202', 'B3FF', 'FE1E', '8329']
## destination IP
dip = ['FE80', '0000', '0000', '0000', '0202', 'B3FF', 'FE1E', '8330']
## next header - 32 bits, permanently set to (58)_dec ~ (88)_hex
nh = ['0000', '0088']
## packet length -> see my question above: (56)_dec ~ (38)_hex
lng = ['0038']
png = "8000 0000 a088 0000 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 3031 3233".split(" ")
# END OF PSEUDO HEADER
tot = sip + dip + lng + nh + png # from what the sum is going to be counted
stot = sum([int(x, 16) for x in tot]) % 65535 # we are in 16 bits world
rstot = 65535 - stot # wrap around
res = hex(rstot) # convert to hex
print(stot, rstot)
print(res)
check = bin(rstot + stot)
print(check) # all ones
用于以下 ICMPv6 ping 请求(带有 IPv6 标头):
d392 30fb 0001 d393 30fb 0001 86dd 6000
0000 0000 3a00 FE80 0000 0000 0000 0202
B3FF FE1E 8329 FE80 0000 0000 0000 0202
B3FF FE1E 8330 8000 xxxx a088 0000 0001
0203 0405 0607 0809 0a0b 0c0d 0e0f 1011
1213 1415 1617 1819 1a1b 1c1d 1e1f 2021
2223 2425 2627 2829 2a2b 2c2d 2e2f 3031
3233
它给出了输出:
27741 37794
0xe672 # correct?
0b1111111111111111
所以我应该将xxxx 替换为e672。这是正确的吗?当我尝试使用wireshark 计算时,我得到了不同的答案。
【问题讨论】: