1#!/usr/local/bin/python2.7
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=100 * "ABCDEFGHIJKLMNOP"
18packet=IP(src=LOCAL_ADDR, dst=REMOTE_ADDR)/ \
19    ICMP(type='echo-request', id=eid)/payload
20request_cksum=ICMP(str(packet.payload)).chksum
21print "request cksum=%#x" % (request_cksum)
22frag=[]
23fid=pid & 0xffff
24frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid, flags='MF')/
25    str(packet)[20:36])
26offset=2
27chunk=4
28while 40+8*(offset+chunk) < len(payload):
29	frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
30	    frag=offset, flags='MF')/
31	    str(packet)[20+(8*offset):20+8*(offset+chunk)])
32	offset+=chunk
33frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
34	frag=offset)/str(packet)[20+(8*offset):])
35eth=[]
36for f in frag:
37	eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/f)
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    "ip and src "+REMOTE_ADDR+" and dst "+LOCAL_ADDR+" and icmp")
46for a in ans:
47	if a and a.type == ETH_P_IP and \
48	    a.payload.proto == 1 and \
49	    a.payload.frag == 0 and a.payload.flags == 1 and \
50	    icmptypes[a.payload.payload.type] == 'echo-reply':
51		id=a.payload.payload.id
52		print "id=%#x" % (id)
53		if id != eid:
54			print "WRONG ECHO REPLY ID"
55			exit(2)
56		reply_cksum=a.payload.payload.chksum
57		print "reply cksum=%#x" % (reply_cksum)
58		# change request checksum incrementaly and check with reply
59		diff_cksum=~(~reply_cksum+~(~request_cksum+~0x0800+0x0000))
60		if diff_cksum & 0xffff != 0xffff and diff_cksum & 0xffff != 0:
61			print "CHECKSUM ERROR diff cksum=%#x" % (diff_cksum)
62			exit(1)
63		exit(0)
64print "NO ECHO REPLY"
65exit(2)
66