1527238f8Sbluhm#!/usr/local/bin/python3
2233b170eSbluhm
3527238f8Sbluhmprint("fragments of a large packet that has to be refragmented by reflector")
4fcb190aaSbluhm
5fcb190aaSbluhm# |--------|
6fcb190aaSbluhm#          |------------------|
7fcb190aaSbluhm#                              ...
8fcb190aaSbluhm#                                 |------------------|
9fcb190aaSbluhm#                                                    |----|
10fcb190aaSbluhm
11fcb190aaSbluhmimport os
12fcb190aaSbluhmfrom addr import *
13fcb190aaSbluhmfrom scapy.all import *
14fcb190aaSbluhm
159ae5678bSbluhmpid=os.getpid()
169ae5678bSbluhmeid=pid & 0xffff
17527238f8Sbluhmpayload=b"ABCDEFGHIJKLMNOP" * 100
187b3475a7Sbluhmpacket=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/ \
197b3475a7Sbluhm    ICMPv6EchoRequest(id=eid, data=payload)
20527238f8Sbluhmrequest_cksum=ICMPv6Unknown(bytes(packet.payload)).cksum
21527238f8Sbluhmprint("request cksum=%#x" % (request_cksum))
22fcb190aaSbluhmfrag=[]
239ae5678bSbluhmfid=pid & 0xffffffff
24527238f8Sbluhmfrag.append(IPv6ExtHdrFragment(nh=58, id=fid, m=1)/bytes(packet)[40:56])
25fcb190aaSbluhmoffset=2
26fcb190aaSbluhmchunk=4
27fcb190aaSbluhmwhile 40+8*(offset+chunk) < len(payload):
28*70d7d4e3Sbluhm	frag.append(IPv6ExtHdrFragment(nh=58, id=fid,
29*70d7d4e3Sbluhm	    offset=offset, m=1)/
30527238f8Sbluhm	    bytes(packet)[40+(8*offset):40+8*(offset+chunk)])
31fcb190aaSbluhm	offset+=chunk
32*70d7d4e3Sbluhmfrag.append(IPv6ExtHdrFragment(nh=58, id=fid,
33*70d7d4e3Sbluhm    offset=offset)/bytes(packet)[40+(8*offset):])
34fcb190aaSbluhmeth=[]
35fcb190aaSbluhmfor f in frag:
367b3475a7Sbluhm	pkt=IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/f
377b3475a7Sbluhm	eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/pkt)
38fcb190aaSbluhm
39fcb190aaSbluhmif os.fork() == 0:
40fcb190aaSbluhm	time.sleep(1)
417b3475a7Sbluhm	sendp(eth, iface=LOCAL_IF)
42fcb190aaSbluhm	os._exit(0)
43fcb190aaSbluhm
447b3475a7Sbluhmans=sniff(iface=LOCAL_IF, timeout=3, filter=
457b3475a7Sbluhm    "ip6 and src "+REMOTE_ADDR6+" and dst "+LOCAL_ADDR6+" and proto ipv6-frag")
46fcb190aaSbluhmfor a in ans:
479c70e3bfSbluhm	if a and a.type == ETH_P_IPV6 and \
48fcb190aaSbluhm	    ipv6nh[a.payload.nh] == 'Fragment Header' and \
49fcb190aaSbluhm	    a.payload.payload.offset == 0 and \
50fcb190aaSbluhm	    ipv6nh[a.payload.payload.nh] == 'ICMPv6' and \
51fcb190aaSbluhm	    icmp6types[a.payload.payload.payload.type] == 'Echo Reply':
52fcb190aaSbluhm		id=a.payload.payload.payload.id
53527238f8Sbluhm		print("id=%#x" % (id))
549ae5678bSbluhm		if id != eid:
55527238f8Sbluhm			print("WRONG ECHO REPLY ID")
56fcb190aaSbluhm			exit(2)
5709d57e28Sbluhm		reply_cksum=a.payload.payload.payload.cksum
58527238f8Sbluhm		print("reply cksum=%#x" % (reply_cksum))
5909d57e28Sbluhm		# change request checksum incrementaly and check with reply
6009d57e28Sbluhm		diff_cksum=~(~reply_cksum+~(~request_cksum+~0x8000+0x8100))
61f5f40516Sbluhm		if diff_cksum & 0xffff != 0xffff and diff_cksum & 0xffff != 0:
62527238f8Sbluhm			print("CHECKSUM ERROR diff cksum=%#x" % (diff_cksum))
6309d57e28Sbluhm			exit(1)
64fcb190aaSbluhm		exit(0)
65527238f8Sbluhmprint("NO ECHO REPLY")
66fcb190aaSbluhmexit(2)
67