xref: /openbsd-src/regress/sys/netinet/frag/frag_overindex.py (revision 973a68518aa41045fe1413aa3bbe246a4ca04cc4)
1#!/usr/local/bin/python3
2
3print("ping fragment that overlaps the first fragment at index boundary")
4
5#                               index boundary 4096 |
6# |--------------|
7#                 ....
8#                     |--------------|
9#                                              |XXXX-----|
10#                                    |--------------|
11
12# this should trigger "frag index %d, new %d" log in kernel
13
14import os
15from addr import *
16from scapy.all import *
17
18pid=os.getpid()
19eid=pid & 0xffff
20payload=b"ABCDEFGHIJKLMNOP"
21dummy=b"01234567"
22fragsize=64
23boundary=4096
24fragnum=int(boundary/fragsize)
25packet=IP(src=LOCAL_ADDR, dst=REMOTE_ADDR)/ \
26    ICMP(type='echo-request', id=eid)/ \
27    (int((boundary+8)/len(payload)) * payload)
28frag=[]
29fid=pid & 0xffff
30for i in range(fragnum-1):
31	frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
32	    frag=(i*fragsize)>>3, flags='MF')/
33	    bytes(packet)[20+i*fragsize:20+(i+1)*fragsize])
34frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
35    frag=(boundary-8)>>3)/
36    (dummy+bytes(packet)[20+boundary:20+boundary+8]))
37frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
38    frag=(boundary-fragsize)>>3, flags='MF')/
39    bytes(packet)[20+boundary-fragsize:20+boundary])
40eth=[]
41for f in frag:
42	eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/f)
43
44if os.fork() == 0:
45	time.sleep(1)
46	for e in eth:
47		sendp(e, iface=LOCAL_IF)
48		time.sleep(0.001)
49	os._exit(0)
50
51ans=sniff(iface=LOCAL_IF, timeout=5, filter=
52    "ip and src "+REMOTE_ADDR+" and dst "+LOCAL_ADDR+" and icmp")
53for a in ans:
54	if a and a.type == ETH_P_IP and \
55	    a.payload.proto == 1 and \
56	    a.payload.frag == 0 and \
57	    icmptypes[a.payload.payload.type] == 'echo-reply':
58		id=a.payload.payload.id
59		print("id=%#x" % (id))
60		if id != eid:
61			print("WRONG ECHO REPLY ID")
62			exit(2)
63		exit(0)
64print("NO ECHO REPLY")
65exit(1)
66