1#!/usr/bin/env python3 2# 3# Copyright (c) 2025 Alexander Bluhm <bluhm@openbsd.org> 4 5from fragcommon import * 6 7# |--------| 8# |--------| 9# |-------| 10# |----| 11 12def send(src, dst, send_if, recv_if): 13 pid = os.getpid() 14 eid = pid & 0xffff 15 payload = b"ABCDEFGHIJKLMNOP" * 2 16 packet = sp.IP(src=src, dst=dst)/ \ 17 sp.ICMP(type='echo-request', id=eid) / payload 18 frag = [] 19 fid = pid & 0xffff 20 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 21 flags='MF') / bytes(packet)[20:36]) 22 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 23 frag=2, flags='MF') / bytes(packet)[36:52]) 24 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 25 frag=1, flags='MF') / bytes(packet)[28:44]) 26 frag.append(sp.IP(src=src, dst=dst, proto=1, id=fid, 27 frag=4) / bytes(packet)[52:60]) 28 eth=[] 29 for f in frag: 30 eth.append(sp.Ether()/f) 31 if os.fork() == 0: 32 time.sleep(1) 33 sp.sendp(eth, iface=send_if) 34 os._exit(0) 35 36 ans = sp.sniff(iface=recv_if, timeout=3, filter= 37 "ip and src " + dst + " and dst " + src + " and icmp") 38 for a in ans: 39 if a and a.type == sp.ETH_P_IP and \ 40 a.payload.proto == 1 and \ 41 a.payload.frag == 0 and a.payload.flags == 0 and \ 42 sp.icmptypes[a.payload.payload.type] == 'echo-reply': 43 id = a.payload.payload.id 44 print("id=%#x" % (id)) 45 if id != eid: 46 print("WRONG ECHO REPLY ID") 47 exit(2) 48 data = a.payload.payload.payload.load 49 print("payload=%s" % (data)) 50 if data == payload: 51 exit(0) 52 print("PAYLOAD!=%s" % (payload)) 53 exit(1) 54 print("NO ECHO REPLY") 55 exit(2) 56 57if __name__ == '__main__': 58 main(send) 59