xref: /openbsd-src/regress/sys/kern/sosplice/scapy/scapy-delay-synack.py (revision 8feac64083c74a2316e2b206bf271dd90e50442a)
1*8feac640Sbluhm#!/usr/local/bin/python3
23488794cSbluhm# send data from client via relay before server handshake is completed
33488794cSbluhm
43488794cSbluhmimport os
53488794cSbluhmimport sys
63488794cSbluhmimport threading
73488794cSbluhmfrom addr import *
83488794cSbluhmfrom scapy.all import *
93488794cSbluhm
103488794cSbluhmclient=os.getpid() & 0xffff
113488794cSbluhmrelay=int(sys.argv[2])
123488794cSbluhmserver=int(sys.argv[1])
133488794cSbluhm
143488794cSbluhmclass Sniff1(threading.Thread):
153488794cSbluhm	filter = None
163488794cSbluhm	captured = None
173488794cSbluhm	packet = None
18925939b7Sbluhm	def __init__(self):
19925939b7Sbluhm		# clear packets buffered by scapy bpf
20925939b7Sbluhm		sniff(iface=LOCAL_IF, timeout=1)
21925939b7Sbluhm		super(Sniff1, self).__init__()
223488794cSbluhm	def run(self):
233488794cSbluhm		self.captured = sniff(iface=LOCAL_IF, filter=self.filter,
243488794cSbluhm		    count=1, timeout=5)
253488794cSbluhm		if self.captured:
263488794cSbluhm			self.packet = self.captured[0]
273488794cSbluhm
283488794cSbluhmip=IP(src=FAKE_NET_ADDR, dst=REMOTE_ADDR)
293488794cSbluhm
30*8feac640Sbluhmprint("Send SYN packet, receive SYN+ACK")
313488794cSbluhmsyn=TCP(sport=client, dport=relay, seq=0, flags='S', window=(2**16)-1)
323488794cSbluhmsynack=sr1(ip/syn, iface=LOCAL_IF, timeout=5)
333488794cSbluhm
343488794cSbluhmif synack is None:
35*8feac640Sbluhm	print("ERROR: No matching SYN+ACK packet received")
363488794cSbluhm	exit(1)
373488794cSbluhm
38*8feac640Sbluhmprint("Expect spliced SYN")
393488794cSbluhmsniffer = Sniff1();
403488794cSbluhmsniffer.filter = "src %s and dst %s and tcp port %u " \
413488794cSbluhm    "and tcp[tcpflags] = tcp-syn" % (ip.dst, ip.src, server)
423488794cSbluhmsniffer.start()
433488794cSbluhmtime.sleep(1)
443488794cSbluhm
45*8feac640Sbluhmprint("Send ACK packet to finish handshake")
463488794cSbluhmack=TCP(sport=synack.dport, dport=synack.sport,
473488794cSbluhm    seq=1, ack=synack.seq+1,  flags='A')
483488794cSbluhmsend(ip/ack, iface=LOCAL_IF)
493488794cSbluhm
503488794cSbluhmsniffer.join(timeout=7)
513488794cSbluhmspliced_syn = sniffer.packet
523488794cSbluhm
533488794cSbluhmif spliced_syn is None:
54*8feac640Sbluhm	print("ERROR: No spliced SYN packet received")
553488794cSbluhm	exit(1)
563488794cSbluhm
57*8feac640Sbluhmprint("Send 10 bytes payload")
583488794cSbluhmdata="0123456789"
593488794cSbluhmpayload=TCP(sport=synack.dport, dport=synack.sport,
603488794cSbluhm    seq=1, ack=synack.seq+1,  flags='AP')/data
613488794cSbluhmpayload_ack=sr1(ip/payload, iface=LOCAL_IF)
623488794cSbluhm
633488794cSbluhmif payload_ack is None:
64*8feac640Sbluhm	print("ERROR: No payload ACK packet received")
653488794cSbluhm	exit(1)
663488794cSbluhmif payload_ack.ack != len(data)+1:
67*8feac640Sbluhm	print("ERROR: Expected ack %d, got %d in payload ACK" %
68*8feac640Sbluhm	    (len(data)+1, payload_ack.ack))
693488794cSbluhm	exit(1)
703488794cSbluhm
713488794cSbluhmtime.sleep(1)
723488794cSbluhm
73*8feac640Sbluhmprint("Expect spliced payload")
743488794cSbluhmsniffer = Sniff1();
753488794cSbluhmsniffer.filter = "src %s and dst %s and tcp port %u " \
763488794cSbluhm    "and tcp[tcpflags] = tcp-ack|tcp-push" % (ip.dst, ip.src, server)
773488794cSbluhmsniffer.start()
783488794cSbluhmtime.sleep(1)
793488794cSbluhm
80*8feac640Sbluhmprint("Send spliced SYN+ACK packet to finish handshake")
813488794cSbluhmspliced_synack=TCP(sport=spliced_syn.dport, dport=spliced_syn.sport,
823488794cSbluhm    seq=0, ack=spliced_syn.seq+1, flags='SA')
833488794cSbluhmspliced_ack=sr1(ip/spliced_synack, iface=LOCAL_IF)
843488794cSbluhm
853488794cSbluhmif spliced_ack is None:
86*8feac640Sbluhm	print("ERROR: No spliced ACK packet received")
873488794cSbluhm	exit(1)
883488794cSbluhm
893488794cSbluhmsniffer.join(timeout=7)
903488794cSbluhmspliced_payload = sniffer.packet
913488794cSbluhm
923488794cSbluhmif spliced_payload is None:
93*8feac640Sbluhm	print("ERROR: No spliced payload packet received")
943488794cSbluhm	exit(1)
953488794cSbluhmif spliced_payload.seq != spliced_ack.seq:
96*8feac640Sbluhm	print("ERROR: Expected seq %d, got %d in spliced payload" %
97*8feac640Sbluhm	    (spliced_ack.seq, spliced_payload.seq))
983488794cSbluhm	exit(1)
993488794cSbluhmif spliced_payload.len-20-20 != len(data):
100*8feac640Sbluhm	print("ERROR: Expected len %d, got %d in spliced payload" %
101*8feac640Sbluhm	    (len(data), spliced_payload.len-20-20))
1023488794cSbluhm	exit(1)
1033488794cSbluhm
104*8feac640Sbluhmprint("Expect spliced ACK retransmission")
105925939b7Sbluhmsniffer = Sniff1();
106925939b7Sbluhmsniffer.filter = "src %s and dst %s and tcp port %u " \
107925939b7Sbluhm    "and tcp[tcpflags] = tcp-ack" % (ip.dst, ip.src, server)
108925939b7Sbluhmsniffer.start()
109925939b7Sbluhmtime.sleep(1)
110925939b7Sbluhm
111*8feac640Sbluhmprint("Retransmit spliced SYN+ACK packet to trigger ACK")
112925939b7Sbluhmsend(ip/spliced_synack, iface=LOCAL_IF)
113925939b7Sbluhm
114925939b7Sbluhmsniffer.join(timeout=7)
115925939b7Sbluhmspliced_ack_retrans = sniffer.packet
1163488794cSbluhm
1173488794cSbluhmif spliced_ack_retrans is None:
118*8feac640Sbluhm	print("ERROR: No spliced ACK retransmit packet received")
1193488794cSbluhm	exit(1)
1203488794cSbluhmif spliced_ack_retrans.seq != spliced_syn.seq+1+len(data):
121*8feac640Sbluhm	print("ERROR: Expected seq %d, got %d in retransmitted spliced ack" %
122*8feac640Sbluhm	    (spliced_syn.seq+1+len(data), spliced_ack_retrans.seq))
1233488794cSbluhm	exit(1)
1243488794cSbluhmif spliced_ack_retrans.ack != 1:
125*8feac640Sbluhm	print("ERROR: Expected ack %d, got %d in retransmitted spliced ack" %
126*8feac640Sbluhm	    (1, spliced_ack_retrans.ack))
1273488794cSbluhm	exit(1)
1283488794cSbluhmif spliced_ack_retrans.len-20-20 != 0:
129*8feac640Sbluhm	print("ERROR: Expected len %d, got %d in retransmitted spliced ack" %
130*8feac640Sbluhm	    (0, spliced_ack_retrans.len-20-20))
1313488794cSbluhm	exit(1)
1323488794cSbluhm
133*8feac640Sbluhmprint("Kill connections with RST")
1343488794cSbluhmspliced_rst=TCP(sport=spliced_ack.dport, dport=spliced_ack.sport,
1353488794cSbluhm    seq=1, ack=spliced_ack.seq, flags='RA')
1363488794cSbluhmsend(ip/spliced_rst, iface=LOCAL_IF)
1373488794cSbluhmrst=TCP(sport=synack.dport, dport=synack.sport,
1383488794cSbluhm    seq=payload_ack.ack, ack=synack.seq+1, flags='RA')
1393488794cSbluhmsend(ip/rst, iface=LOCAL_IF)
1403488794cSbluhm
1413488794cSbluhmexit(0)
142