#### 72 lines 2.0 KiB Python Raw Blame History

 ```#!/usr/bin/env python3 ``` ``` ``` ```# Code copied from /usr/lib/python3/dist-packages/scapy/utils.py ``` ``` ``` ```import struct ``` ```import array ``` ``` ``` ```if struct.pack("H",1) == b"\x00\x01": # big endian ``` ``` def checksum(pkt): ``` ``` if len(pkt) % 2 == 1: ``` ``` pkt += b"\0" ``` ``` s = sum(array.array("H", pkt)) ``` ``` s = (s >> 16) + (s & 0xffff) ``` ``` s += s >> 16 ``` ``` s = ~s ``` ``` return s & 0xffff ``` ```else: ``` ``` def checksum(pkt): ``` ``` # padding to even length ``` ``` if len(pkt) % 2 == 1: ``` ``` pkt += b"\0" ``` ``` ``` ``` # create array with unsigned shorts, ``` ``` # sum it up -> results in 16 bit uint (?) ``` ``` s = sum(array.array("H", pkt)) ``` ``` print("sum={}".format(s)) ``` ``` # This step is understood ``` ``` ``` ``` # (s & 0xffff) -> mask for 16 bit, truncate rest ``` ``` # (s >> 16) right shift by 16 bits ``` ``` # >>> 2**17 >> 16 ``` ``` # 2 ``` ``` # Basically: ``` ``` # add higher 16 bits to lower 16 bits ``` ``` ``` ``` s = (s >> 16) + (s & 0xffff) ``` ``` ``` ``` # Now we add the remaining possible 16 bits ``` ``` # i.e. above we take bits 0..15 + 16..31 ``` ``` # now we add [0..15 + 16..31] + "32..47" ``` ``` # I assume this is for catching the carry ``` ``` # over bits from the previous calculation ``` ``` s += s >> 16 ``` ``` ``` ``` # according to https://stackoverflow.com/questions/8305199/the-tilde-operator-in-python ``` ``` # ~ is the bitwise complement operator in python ``` ``` # which essentially calculates -x - 1 ``` ``` ``` ``` # 2 complement ``` ``` s = ~s ``` ``` ``` ``` # (s>>8)&0xff) -> filter bits 8..15 ``` ``` # | = bitwise OR ``` ``` # s<<8 : left shift everything in original s ``` ``` # | s<<8: ? ``` ``` # & 0xffff: filter / allow only 16 bits ``` ``` # Seems like the idea is to filter correctly for ``` ``` # 16 bit - unclear why "s & 0xffff" does not do the job ``` ``` ``` ``` return (((s>>8)&0xff)|s<<8) & 0xffff ``` ``` ``` ``` ``` ```if __name__ == '__main__': ``` ``` import sys ``` ``` pkt = sys.argv[1] ``` ``` pkt_bytes = pkt.encode('utf-8') ``` ``` print(pkt_bytes) ``` ``` print(checksum(pkt_bytes)) ``` ``` ``` ``` ipv4 = "AAAA" ``` ``` ipv6 = "BBAA" ```