python 校验和udp计算python
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1767910/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
checksum udp calculation python
提问by n00bie
I'd like to calculate the checksum of an UDP header packet I want to send:
我想计算我要发送的 UDP 标头数据包的校验和:
packetosend = """60 00 00 00 00 24 3a 40 20 02 c0 a8 01 50 00 01 00 00
00 00 00 00 09 38 20 02 c0 a8 01 50 00 01 00 00 00 00 00 00 09 6f"""
so I need to join this utf-16 (not a problem) and calculate the checksum of thisspecific packet. How can I do that?
所以我需要加入这个utf-16(不是问题)并计算这个特定数据包的校验和。我怎样才能做到这一点?
Thanks!
谢谢!
EDIT: Yes it's an IPv6 header for an ICMPv6 packet, anyways what I would like to know is the formula, and how it works.
编辑:是的,它是 ICMPv6 数据包的 IPv6 标头,无论如何我想知道的是公式及其工作原理。
I'll give another example with an ICMP ping echo (v4) packet:
我将给出另一个带有 ICMP ping echo (v4) 数据包的示例:
packet = """
08 00 d1 15 76 0c 00 07 bf d3 55 4a ad b5 03 00 // "d1 15" is the packet checksum
08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17
18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37"""
Thanks.
谢谢。
回答by Jason Orendorff
This doesn't look like a UDP packet to me. It looks like an IPv6 header for an ICMPv6 packet, but the actual payload of the packet is missing.
对我来说,这看起来不像 UDP 数据包。它看起来像 ICMPv6 数据包的 IPv6 标头,但缺少数据包的实际负载。
IPv6 headers do not contain a checksum.
IPv6 标头不包含校验和。
For ICMP, the checksum is "the 16-bit one's complement of the one's complement sum of the ICMP message starting with the Type field." One's complement arithmeticinvolves special treatment of the carry bit.
对于ICMP,校验和是“从类型字段开始的 ICMP 消息的补码和的 16 位补码”。补码运算涉及进位位的特殊处理。
def carry_around_add(a, b):
c = a + b
return (c & 0xffff) + (c >> 16)
def checksum(msg):
s = 0
for i in range(0, len(msg), 2):
w = ord(msg[i]) + (ord(msg[i+1]) << 8)
s = carry_around_add(s, w)
return ~s & 0xffff
In order to calculate the right checksum, of course you have to start with the right msg
, which means at least zeroing out the checksum field first and may also require adding "virtual headers", depending on the protocols you're using.
为了计算正确的校验和,当然您必须从 right 开始msg
,这意味着至少首先将校验和字段清零,并且可能还需要添加“虚拟标头”,具体取决于您使用的协议。
回答by pfa
There is a solid checksum function that correctly deals with endianness problems in Scapy (http://www.secdev.org/projects/scapy, GPLv2).
有一个可靠的校验和函数可以正确处理 Scapy ( http://www.secdev.org/projects/scapy, GPLv2) 中的字节序问题。
In Python 2.7, scapy's utils.py:
在 Python 2.7 中,scapy 的 utils.py:
if struct.pack("H",1) == "\x00\x01": # big endian
def checksum(pkt):
if len(pkt) % 2 == 1:
pkt += "##代码##"
s = sum(array.array("H", pkt))
s = (s >> 16) + (s & 0xffff)
s += s >> 16
s = ~s
return s & 0xffff
else:
def checksum(pkt):
if len(pkt) % 2 == 1:
pkt += "##代码##"
s = sum(array.array("H", pkt))
s = (s >> 16) + (s & 0xffff)
s += s >> 16
s = ~s
return (((s>>8)&0xff)|s<<8) & 0xffff
This is correct for any protocol which uses the IP header checksum (IP, TCP, UDP, ICMP). However, UDP also has the special case that a checksum calculated as 0x0000 should be transmitted as 0xffff. The above function does not account for that, so for UDP you would have to handle that special case.
这对于使用 IP 报头校验和(IP、TCP、UDP、ICMP)的任何协议都是正确的。但是,UDP 也有特殊情况,即计算为 0x0000 的校验和应作为 0xffff 传输。上面的函数没有考虑到这一点,因此对于 UDP,您必须处理这种特殊情况。