master-thesis/bin/checksum_from_scapy.py

72 lines
2.0 KiB
Python

#!/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"