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