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