xref: /openbsd-src/regress/sys/net/pf_state/challenge_ack.py (revision ec1f834e2f1780578c47635e859df02886b12c25)
1*ec1f834eSbluhm#!/usr/local/bin/python3
267cf0727Sbluhm# check wether path mtu to dst is as expected
367cf0727Sbluhm
467cf0727Sbluhmimport os
567cf0727Sbluhmimport threading
667cf0727Sbluhmfrom addr import *
767cf0727Sbluhmfrom scapy.all import *
867cf0727Sbluhm
967cf0727Sbluhm#
1067cf0727Sbluhm# we can not use scapy's sr() function as receive side
1167cf0727Sbluhm# ignores the packet we expect to see. Packet is ignored
1267cf0727Sbluhm# due to mismatching sequence numbers. 'bogus_syn' is using
1367cf0727Sbluhm# seq = 1000000, while response sent back by PF has ack,
1467cf0727Sbluhm# which fits regular session opened by 'syn'.
1567cf0727Sbluhm#
16de0a526bSbluhmclass Sniff1(threading.Thread):
17de0a526bSbluhm	filter = None
1867cf0727Sbluhm	captured = None
19de0a526bSbluhm	packet = None
2067cf0727Sbluhm	def run(self):
21de0a526bSbluhm		self.captured = sniff(iface=LOCAL_IF, filter=self.filter,
22de0a526bSbluhm		    count=1, timeout=5)
23de0a526bSbluhm		if self.captured:
24de0a526bSbluhm			self.packet = self.captured[0]
2567cf0727Sbluhm
269ae5678bSbluhmtport=os.getpid() & 0xffff
2767cf0727Sbluhm
28de0a526bSbluhmip=IP(src=FAKE_NET_ADDR, dst=REMOTE_ADDR)
2967cf0727Sbluhm
30*ec1f834eSbluhmprint("Send SYN packet, receive SYN+ACK")
319ae5678bSbluhmsyn=TCP(sport=tport, dport='echo', seq=1, flags='S', window=(2**16)-1)
329ae5678bSbluhmsynack=sr1(ip/syn, iface=LOCAL_IF, timeout=5)
3305420020Sbluhm
349ae5678bSbluhmif synack is None:
35*ec1f834eSbluhm	print("ERROR: no matching SYN+ACK packet received")
3605420020Sbluhm	exit(1)
3767cf0727Sbluhm
38*ec1f834eSbluhmprint("Send ACK packet to finish handshake.")
399ae5678bSbluhmack=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='A',
409ae5678bSbluhm    ack=synack.seq+1)
4167cf0727Sbluhmsend(ip/ack, iface=LOCAL_IF)
4267cf0727Sbluhm
43*ec1f834eSbluhmprint("Connection is established, send bogus SYN, expect challenge ACK")
449ae5678bSbluhmbogus_syn=TCP(sport=syn.sport, dport=syn.dport, seq=1000000, flags='S',
4567cf0727Sbluhm    window=(2**16)-1)
46de0a526bSbluhmsniffer = Sniff1();
479ae5678bSbluhmsniffer.filter = "src %s and tcp port %u and dst %s and tcp port %u " \
489ae5678bSbluhm    "and tcp[tcpflags] = tcp-ack" % (ip.dst, syn.dport, ip.src, syn.sport)
4967cf0727Sbluhmsniffer.start()
509a7ee091Sbluhmtime.sleep(1)
51de0a526bSbluhmsend(ip/bogus_syn, iface=LOCAL_IF)
52de0a526bSbluhmsniffer.join(timeout=7)
53de0a526bSbluhmchallenge_ack = sniffer.packet
5467cf0727Sbluhm
55de0a526bSbluhmif challenge_ack is None:
56*ec1f834eSbluhm	print("ERROR: no matching ACK packet received")
5767cf0727Sbluhm	exit(1)
5867cf0727Sbluhm
599ae5678bSbluhmif challenge_ack.getlayer(TCP).seq != (synack.seq + 1):
60*ec1f834eSbluhm	print("ERROR: expecting seq %d got %d in challange ack" % \
61*ec1f834eSbluhm	    (challenge_ack.getlayer(TCP).seq, (synack.seq + 1)))
6267cf0727Sbluhm	exit(1)
6367cf0727Sbluhm
6467cf0727Sbluhmexit(0)
65