xref: /openbsd-src/regress/sys/netinet/pmtu/tcp_atomicfrag6.py (revision c90a81c56dcebd6a1b73fe4aff9b03385b8e63b3)
1#!/usr/local/bin/python2.7
2
3import os
4import threading
5from addr import *
6from scapy.all import *
7
8class Sniff(threading.Thread):
9	filter = None
10	captured = None
11	packet = None
12	def __init__(self):
13		# clear packets buffered by scapy bpf
14		sniff(iface=LOCAL_IF, timeout=1)
15		super(Sniff, self).__init__()
16	def run(self):
17		self.captured = sniff(iface=LOCAL_IF, filter=self.filter,
18		    timeout=3)
19		if self.captured:
20			self.packet = self.captured[0]
21
22e=Ether(src=LOCAL_MAC, dst=REMOTE_MAC)
23ip6=IPv6(src=FAKE_NET_ADDR6, dst=REMOTE_ADDR6)
24tport=os.getpid() & 0xffff
25
26print "Send SYN packet, receive SYN+ACK."
27syn=TCP(sport=tport, dport='chargen', seq=1, flags='S', window=(2**16)-1)
28synack=srp1(e/ip6/syn, iface=LOCAL_IF, timeout=5)
29
30if synack is None:
31	print "ERROR: no SYN+ACK from chargen server received"
32	exit(1)
33
34print "Send ACK packet, receive chargen data."
35ack=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='A',
36    ack=synack.seq+1, window=(2**16)-1)
37data=srp1(e/ip6/ack, iface=LOCAL_IF, timeout=5)
38
39if data is None:
40	print "ERROR: no data from chargen server received"
41	exit(1)
42
43print "Fill our receive buffer."
44time.sleep(1)
45
46# srp1 cannot be used, fragment answer will not match outgoing ICMP6 packet
47sniffer = Sniff()
48sniffer.filter = \
49    "ip6 and src "+ip6.dst+" and dst "+ip6.src+" and proto ipv6-frag"
50sniffer.start()
51time.sleep(1)
52
53print "Send ICMP6 packet too big packet with MTU 1272."
54icmp6=ICMPv6PacketTooBig(mtu=1272)/data.payload
55sendp(e/IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/icmp6, iface=LOCAL_IF)
56
57print "Path MTU discovery will not resend data, ICMP6 packet is ignored."
58sniffer.join(timeout=5)
59
60print "IPv6 atomic fragments must not be generated."
61frag=None
62for a in sniffer.captured:
63	fh=a.payload.payload
64	if fh.offset != 0 or fh.nh != (ip6/syn).nh:
65		continue
66	th=fh.payload
67	if th.sport != syn.dport or th.dport != syn.sport:
68		continue
69	frag=a
70	break
71
72if frag is not None:
73	print "ERROR: matching IPv6 fragment TCP answer found"
74	exit(1)
75
76print "Send ACK again to trigger retransmit."
77data=srp1(e/ip6/ack, iface=LOCAL_IF, timeout=5)
78
79if data is None:
80	print "ERROR: no data retransmit from chargen server received"
81	exit(1)
82
83print "Cleanup the other's socket with a reset packet."
84rst=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='AR',
85    ack=synack.seq+1)
86sendp(e/ip6/rst, iface=LOCAL_IF)
87
88len = data.plen + len(IPv6())
89print "len=%d" % len
90if len != 1500:
91	print "ERROR: TCP data packet len is %d, expected 1500." % len
92	exit(1)
93
94exit(0)
95