xref: /openbsd-src/regress/sys/netinet/pmtu/tcp_connect.py (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1#!/usr/local/bin/python2.7
2
3import os
4import threading
5from addr import *
6from scapy.all import *
7
8class Sniff1(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(Sniff1, self).__init__()
16	def run(self):
17		self.captured = sniff(iface=LOCAL_IF, filter=self.filter,
18		    count=1, timeout=3)
19		if self.captured:
20			self.packet = self.captured[0]
21
22ip=IP(src=FAKE_NET_ADDR, dst=REMOTE_ADDR)
23tport=os.getpid() & 0xffff
24
25print "Send SYN packet, receive SYN+ACK."
26syn=TCP(sport=tport, dport='chargen', seq=1, flags='S', window=(2**16)-1)
27synack=sr1(ip/syn, iface=LOCAL_IF, timeout=5)
28
29if synack is None:
30	print "ERROR: no SYN+ACK from chargen server received"
31	exit(1)
32
33print "Send ACK packet, receive chargen data."
34ack=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='A',
35    ack=synack.seq+1, window=(2**16)-1)
36data=sr1(ip/ack, iface=LOCAL_IF, timeout=5)
37
38if data is None:
39	print "ERROR: no data from chargen server received"
40	exit(1)
41
42print "Fill our receive buffer."
43time.sleep(1)
44
45# sr1 cannot be used, TCP data will not match outgoing ICMP packet
46sniffer = Sniff1()
47sniffer.filter = \
48    "ip and src %s and tcp port %u and dst %s and tcp port %u" % \
49    (ip.dst, syn.dport, ip.src, syn.sport)
50sniffer.start()
51time.sleep(1)
52
53print "Send ICMP fragmentation needed packet with MTU 1300."
54icmp=ICMP(type="dest-unreach", code="fragmentation-needed",
55    nexthopmtu=1300)/data
56send(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR)/icmp, iface=LOCAL_IF)
57
58print "Path MTU discovery will resend first data with length 1300."
59sniffer.join(timeout=5)
60ans = sniffer.packet
61
62if len(ans) == 0:
63	print "ERROR: no data retransmit from chargen server received"
64	exit(1)
65data=ans[0]
66
67print "Cleanup the other's socket with a reset packet."
68rst=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='AR',
69    ack=synack.seq+1)
70send(ip/rst, iface=LOCAL_IF)
71
72len = data.len
73print "len=%d" % len
74if len != 1300:
75	print "ERROR: TCP data packet len is %d, expected 1300." % len
76	exit(1)
77
78exit(0)
79