Python udp checksum calculation

I would like to calculate the checksum of the UDP header packet that I want to send:

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 (no problem) and calculate the checksum of this specific package. How can i do this?

Thanks!

EDIT: Yes, this is the IPv6 header for the ICMPv6 packet, anyway, what I would like to know is the formula and how it works.

I will give another example of the ICMP ping echo (v4) package:

 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.

+4
source share
2 answers

This is not like a UDP packet for me. It looks like the IPv6 header for the ICMPv6 packet, but the actual packet payload is missing.

IPv6 headers do not contain a checksum .

For ICMP , the checksum is "16-bit complement to one complement of ICMP messages, starting with the field type". Arithmetic with one addition implies special handling of carry bits.

 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 

To calculate the correct checksum, of course, you should start with the right msg , which means at least first reset the checksum field and may also require adding โ€œvirtual headersโ€ depending on the protocols, re using.

+8
source

There is a clear checksum function that correctly handles Endianness tasks in Scapy ( http://www.secdev.org/projects/scapy , GPLv2).

In Python 2.7, scapy 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 that uses the IP header checksum (IP, TCP, UDP, ICMP). However, UDP also has a special case where a checksum calculated as 0x0000 must be transmitted as 0xffff. The above function does not take this into account, so for UDP you will have to handle this special case.

+4
source

All Articles