1#!/usr/bin/env python3 2# 3# Copyright (c) 2025 Alexander Bluhm <bluhm@openbsd.org> 4 5from fragcommon import * 6 7# index boundary 4096 | 8# |--------------| 9# .... 10# |--------------| 11# |----------| 12# |XXXX----------| 13# |XXXX----| 14# |---| 15 16# this should trigger "frag tail overlap %d" and "frag head overlap %d" 17def send(src, dst, send_if, recv_if): 18 pid = os.getpid() 19 eid = pid & 0xffff 20 payload = b"ABCDEFGHIJKLMNOP" 21 dummy = b"01234567" 22 fragsize = 1024 23 boundary = 4096 24 fragnum = int(boundary / fragsize) 25 packet = sp.IP(src=src, dst=dst)/ \ 26 sp.ICMP(type='echo-request', id=eid)/ \ 27 ((int((boundary + fragsize) / len(payload)) + 1) * payload) 28 packet_length = len(packet) 29 frag = [] 30 fid = pid & 0xffff 31 for i in range(fragnum-1): 32 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 33 frag=(i * fragsize)>>3, flags='MF')/ 34 bytes(packet)[20 + i * fragsize:20 + (i + 1) * fragsize]) 35 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 36 frag=(boundary - fragsize) >> 3, flags='MF')/ 37 bytes(packet)[20 + boundary - fragsize:20 + boundary - len(dummy)]) 38 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 39 frag=(boundary - len(dummy)) >> 3, flags='MF')/ 40 (dummy+bytes(packet)[20 + boundary:20 + boundary + fragsize])) 41 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 42 frag=(boundary - 8 - len(dummy)) >> 3, flags='MF')/ 43 (dummy+bytes(packet)[20 + boundary - 8:20 + boundary])) 44 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 45 frag=(boundary + fragsize) >> 3)/bytes(packet)[20 + boundary + fragsize:]) 46 eth=[] 47 for f in frag: 48 eth.append(sp.Ether() / f) 49 50 if os.fork() == 0: 51 time.sleep(1) 52 for e in eth: 53 sp.sendp(e, iface=send_if) 54 time.sleep(0.001) 55 os._exit(0) 56 57 ans = sp.sniff(iface=recv_if, timeout=3, filter= 58 "ip and src " + dst + " and dst " + src + " and icmp") 59 for a in ans: 60 if a and a.type == sp.ETH_P_IP and \ 61 a.payload.proto == 1 and \ 62 a.payload.frag == 0 and \ 63 sp.icmptypes[a.payload.payload.type] == 'echo-reply': 64 id = a.payload.payload.id 65 print("id=%#x" % (id)) 66 if id != eid: 67 print("WRONG ECHO REPLY ID") 68 exit(2) 69 if a and a.type == sp.ETH_P_IP and \ 70 a.payload.proto == 1 and \ 71 a.payload.frag > 0 and \ 72 a.payload.flags == '': 73 length = (a.payload.frag << 3) + a.payload.len 74 print("len=%d" % (length)) 75 if length != packet_length: 76 print("WRONG ECHO REPLY LENGTH") 77 exit(1) 78 exit(0) 79 print("NO ECHO REPLY") 80 exit(1) 81 82if __name__ == '__main__': 83 main(send) 84