xref: /openbsd-src/regress/sys/netinet6/frag6/frag6_unfragsize.py (revision 8f79da2a7ab2d3087d9588c271f22381fe816d25)
1*8f79da2aSbluhm#!/usr/local/bin/python3
2*8f79da2aSbluhm
3*8f79da2aSbluhmprint("ping6 fragments with options total larger than IP maximum packet")
4*8f79da2aSbluhm
5*8f79da2aSbluhm#           |--------|
6*8f79da2aSbluhm#                     ...                                  ...
7*8f79da2aSbluhm#                                                             |--------|
8*8f79da2aSbluhm# drop first fragment with ECN conflict, reinsert with longer unfrag part
9*8f79da2aSbluhm# |---------|
10*8f79da2aSbluhm# HopByHop|---------|
11*8f79da2aSbluhm
12*8f79da2aSbluhmimport os
13*8f79da2aSbluhmfrom addr import *
14*8f79da2aSbluhmfrom scapy.all import *
15*8f79da2aSbluhm
16*8f79da2aSbluhmpid=os.getpid()
17*8f79da2aSbluhmeid=pid & 0xffff
18*8f79da2aSbluhmpayload=b"ABCDEFGHIJKLMNOP"
19*8f79da2aSbluhmpacket=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/ \
20*8f79da2aSbluhm    ICMPv6EchoRequest(id=eid, data=4095*payload)
21*8f79da2aSbluhmplen=IPv6(raw(packet)).plen
22*8f79da2aSbluhmprint("plen=%u" % (plen))
23*8f79da2aSbluhmif plen != 0xfff8:
24*8f79da2aSbluhm	print("PLEN!=%u" % (0xfff8))
25*8f79da2aSbluhm	exit(2)
26*8f79da2aSbluhmbytes=bytes(packet)
27*8f79da2aSbluhm
28*8f79da2aSbluhmfrag=[]
29*8f79da2aSbluhmfid=pid & 0xffffffff
30*8f79da2aSbluhmoff=2**7
31*8f79da2aSbluhmwhile off < 2**13:
32*8f79da2aSbluhm	frag.append(IPv6ExtHdrFragment(nh=58, id=fid, offset=off)/ \
33*8f79da2aSbluhm	    bytes[40+off*8:40+off*8+2**10])
34*8f79da2aSbluhm	off+=2**7
35*8f79da2aSbluhmeth=[]
36*8f79da2aSbluhmfor f in frag:
37*8f79da2aSbluhm	pkt=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/f
38*8f79da2aSbluhm	eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/pkt)
39*8f79da2aSbluhm
40*8f79da2aSbluhm# first fragment with ECN to be dropped
41*8f79da2aSbluhmeth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/
42*8f79da2aSbluhm    IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6, tc=3)/
43*8f79da2aSbluhm    IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes[40:40+2**10])
44*8f79da2aSbluhm
45*8f79da2aSbluhm# resend first fragment with unfragmentable part too long for IP plen
46*8f79da2aSbluhmeth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/
47*8f79da2aSbluhm    IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/
48*8f79da2aSbluhm    IPv6ExtHdrHopByHop(options=PadN(optdata="\0"*4))/
49*8f79da2aSbluhm    IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes[40:40+2**10])
50*8f79da2aSbluhm
51*8f79da2aSbluhmif os.fork() == 0:
52*8f79da2aSbluhm	time.sleep(1)
53*8f79da2aSbluhm	sendp(eth, iface=LOCAL_IF)
54*8f79da2aSbluhm	os._exit(0)
55*8f79da2aSbluhm
56*8f79da2aSbluhmans=sniff(iface=LOCAL_IF, timeout=3, filter=
57*8f79da2aSbluhm    "ip6 and src "+REMOTE_ADDR6+" and dst "+LOCAL_ADDR6+" and icmp6")
58*8f79da2aSbluhmfor a in ans:
59*8f79da2aSbluhm	print("type %d" % (a.payload.payload.type))
60*8f79da2aSbluhm	print("icmp %s" % (icmp6types[a.payload.payload.type]))
61*8f79da2aSbluhm	if a and a.type == ETH_P_IPV6 and \
62*8f79da2aSbluhm	    ipv6nh[a.payload.nh] == 'ICMPv6' and \
63*8f79da2aSbluhm	    icmp6types[a.payload.payload.type] == 'Parameter problem':
64*8f79da2aSbluhm		print("code=%u" % (a.payload.payload.code))
65*8f79da2aSbluhm		# 0: 'erroneous header field encountered'
66*8f79da2aSbluhm		if a.payload.payload.code != 0:
67*8f79da2aSbluhm			print("WRONG PARAMETER PROBLEM CODE")
68*8f79da2aSbluhm			exit(1)
69*8f79da2aSbluhm		ptr=a.payload.payload.ptr
70*8f79da2aSbluhm		print("ptr=%u" % (ptr))
71*8f79da2aSbluhm		# 42: sizeof IPv6 header + offset in fragment header
72*8f79da2aSbluhm		if ptr != 42:
73*8f79da2aSbluhm			print("PTR!=%u" % (ptr))
74*8f79da2aSbluhm			exit(1)
75*8f79da2aSbluhm		exit(0)
76*8f79da2aSbluhmprint("NO ICMP PARAMETER PROBLEM")
77*8f79da2aSbluhmexit(2)
78