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