1#!/usr/local/bin/python3
2
3print("fragments of a large packet that has to be refragmented by reflector")
4
5# |--------|
6#          |------------------|
7#                              ...
8#                                 |------------------|
9#                                                    |----|
10
11import os
12from addr import *
13from scapy.all import *
14
15pid=os.getpid()
16eid=pid & 0xffff
17payload=b"ABCDEFGHIJKLMNOP" * 100
18packet=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/ \
19    ICMPv6EchoRequest(id=eid, data=payload)
20request_cksum=ICMPv6Unknown(bytes(packet.payload)).cksum
21print("request cksum=%#x" % (request_cksum))
22frag=[]
23fid=pid & 0xffffffff
24frag.append(IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes(packet)[40:56])
25offset=2
26chunk=4
27while 40+8*(offset+chunk) < len(payload):
28	frag.append(IPv6ExtHdrFragment(nh=58, id=fid,
29	    offset=offset, m=1)/
30	    bytes(packet)[40+(8*offset):40+8*(offset+chunk)])
31	offset+=chunk
32frag.append(IPv6ExtHdrFragment(nh=58, id=fid,
33    offset=offset)/bytes(packet)[40+(8*offset):])
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 proto ipv6-frag")
46for a in ans:
47	if a and a.type == ETH_P_IPV6 and \
48	    ipv6nh[a.payload.nh] == 'Fragment Header' and \
49	    a.payload.payload.offset == 0 and \
50	    ipv6nh[a.payload.payload.nh] == 'ICMPv6' and \
51	    icmp6types[a.payload.payload.payload.type] == 'Echo Reply':
52		id=a.payload.payload.payload.id
53		print("id=%#x" % (id))
54		if id != eid:
55			print("WRONG ECHO REPLY ID")
56			exit(2)
57		reply_cksum=a.payload.payload.payload.cksum
58		print("reply cksum=%#x" % (reply_cksum))
59		# change request checksum incrementaly and check with reply
60		diff_cksum=~(~reply_cksum+~(~request_cksum+~0x8000+0x8100))
61		if diff_cksum & 0xffff != 0xffff and diff_cksum & 0xffff != 0:
62			print("CHECKSUM ERROR diff cksum=%#x" % (diff_cksum))
63			exit(1)
64		exit(0)
65print("NO ECHO REPLY")
66exit(2)
67