checksum udp calculation python

﹥>﹥吖頭↗ 提交于 2019-11-28 09:30:19

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.

IPv6 headers do not contain a checksum.

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 arithmetic involves special treatment of the carry bit.

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.

There is a solid checksum function that correctly deals with endianness problems in Scapy (http://www.secdev.org/projects/scapy, GPLv2).

In Python 2.7, scapy's utils.py:

if struct.pack("H",1) == "\x00\x01": # big endian
    def checksum(pkt):
        if len(pkt) % 2 == 1:
            pkt += "\0"
        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 += "\0"
        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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!