diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2017-11-07 22:06:18 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2017-11-07 22:06:18 +0000 |
commit | 3dc4a242a13bc6a1b41ae3cde031d13716cb045e (patch) | |
tree | 3bbbfcb277f43d3b35ff555e9cb20884a16b7f26 | |
parent | fda0f93db2eb45780e55b241dd9c93b086955434 (diff) |
Test more variations of TCP packets in the scapy splicing tests.
Delay connect and SYN+ACK to splice data into a connecting socket.
-rw-r--r-- | regress/sys/kern/sosplice/LICENSE | 2 | ||||
-rw-r--r-- | regress/sys/kern/sosplice/Relay.pm | 14 | ||||
-rw-r--r-- | regress/sys/kern/sosplice/scapy/scapy-oobinline-delay-connect.py | 106 | ||||
-rw-r--r-- | regress/sys/kern/sosplice/scapy/scapy-payload-delay-connect.py | 106 | ||||
-rw-r--r-- | regress/sys/kern/sosplice/scapy/scapy.pl | 4 |
5 files changed, 228 insertions, 4 deletions
diff --git a/regress/sys/kern/sosplice/LICENSE b/regress/sys/kern/sosplice/LICENSE index a6e1dd38fcf..52b251631b7 100644 --- a/regress/sys/kern/sosplice/LICENSE +++ b/regress/sys/kern/sosplice/LICENSE @@ -1,4 +1,4 @@ -# Copyright (c) 2010-2014 Alexander Bluhm <bluhm@openbsd.org> +# Copyright (c) 2010-2017 Alexander Bluhm <bluhm@openbsd.org> # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above diff --git a/regress/sys/kern/sosplice/Relay.pm b/regress/sys/kern/sosplice/Relay.pm index a4f79733c7c..41c8575ed45 100644 --- a/regress/sys/kern/sosplice/Relay.pm +++ b/regress/sys/kern/sosplice/Relay.pm @@ -1,6 +1,6 @@ -# $OpenBSD: Relay.pm,v 1.1 2013/01/03 17:36:37 bluhm Exp $ +# $OpenBSD: Relay.pm,v 1.2 2017/11/07 22:06:17 bluhm Exp $ -# Copyright (c) 2010 Alexander Bluhm <bluhm@openbsd.org> +# Copyright (c) 2010-2017 Alexander Bluhm <bluhm@openbsd.org> # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -96,6 +96,16 @@ sub child { or die ref($self), " dup STDIN failed: $!"; print STDERR "Accepted\n"; + if ($self->{clientreadable}) { + my $idle = 15; # timeout + my $rin = ''; + vec($rin, fileno($as), 1) = 1; + defined(my $n = select($rin, undef, undef, $idle)) + or die ref($self), " select failed: $!"; + $idle && $n == 0 + and die ref($self), " select timeout"; + } + my $cs = IO::Socket::INET6->new( Proto => $self->{protocol}, Domain => $self->{connectdomain}, diff --git a/regress/sys/kern/sosplice/scapy/scapy-oobinline-delay-connect.py b/regress/sys/kern/sosplice/scapy/scapy-oobinline-delay-connect.py new file mode 100644 index 00000000000..10dafa78c65 --- /dev/null +++ b/regress/sys/kern/sosplice/scapy/scapy-oobinline-delay-connect.py @@ -0,0 +1,106 @@ +#!/usr/local/bin/python2.7 +# send urgent data from client to relay before connecting to server + +import os +import sys +import threading +from addr import * +from scapy.all import * + +client=os.getpid() & 0xffff +relay=int(sys.argv[2]) +server=int(sys.argv[1]) + +class Sniff1(threading.Thread): + filter = None + captured = None + packet = None + def run(self): + self.captured = sniff(iface=LOCAL_IF, filter=self.filter, + count=1, timeout=5) + if self.captured: + self.packet = self.captured[0] + +ip=IP(src=FAKE_NET_ADDR, dst=REMOTE_ADDR) + +print "Send SYN packet, receive SYN+ACK" +syn=TCP(sport=client, dport=relay, seq=0, flags='S', window=(2**16)-1) +synack=sr1(ip/syn, iface=LOCAL_IF, timeout=5) + +if synack is None: + print "ERROR: No matching SYN+ACK packet received" + exit(1) + +print "Send ACK packet to finish handshake" +ack=TCP(sport=synack.dport, dport=synack.sport, + seq=1, ack=synack.seq+1, flags='A') +send(ip/ack, iface=LOCAL_IF) + +print "Expect spliced SYN" +sniffer = Sniff1(); +sniffer.filter = "src %s and dst %s and tcp port %u " \ + "and tcp[tcpflags] = tcp-syn" % (ip.dst, ip.src, server) +sniffer.start() +time.sleep(1) + +print "Send 20 bytes payload and one urgent byte" +data="0123456789Xabcdefghij" +payload=TCP(sport=synack.dport, dport=synack.sport, urgptr=11, + seq=1, ack=synack.seq+1, flags='APU')/data +payload_ack=sr1(ip/payload, iface=LOCAL_IF) + +if payload_ack is None: + print "ERROR: No payload ACK packet received" + exit(1) +if payload_ack.ack != len(data)+1: + print "ERROR: Expected ack %d, got %d in payload ACK" % \ + (len(data)+1, payload_ack.ack) + exit(1) + +sniffer.join(timeout=7) +spliced_syn = sniffer.packet + +if spliced_syn is None: + print "ERROR: No spliced SYN packet received" + exit(1) + +print "Expect spliced urgent payload" +sniffer = Sniff1(); +sniffer.filter = "src %s and dst %s and tcp port %u " \ + "and tcp[tcpflags] = tcp-ack|tcp-urg" % (ip.dst, ip.src, server) +sniffer.start() +time.sleep(1) + +print "Send spliced SYN+ACK packet to finish handshake" +spliced_synack=TCP(sport=spliced_syn.dport, dport=spliced_syn.sport, + seq=0, ack=spliced_syn.seq+1, flags='SA') +spliced_ack=sr1(ip/spliced_synack, iface=LOCAL_IF) + +if spliced_ack is None: + print "ERROR: No spliced ACK packet received" + exit(1) + +sniffer.join(timeout=7) +spliced_payload = sniffer.packet + +if spliced_payload is None: + print "ERROR: No spliced urgent payload packet received" + exit(1) +if spliced_payload.seq != spliced_ack.seq: + print "ERROR: Expected seq %d, got %d in spliced payload" % \ + (spliced_ack.seq, spliced_payload.seq) + exit(1) +if spliced_payload.urgptr != 11: + print "ERROR: Expected urgptr %d, got %d in spliced payload" % \ + (11, spliced_payload.urgptr) + exit(1) + +print "Kill connections with RST" +spliced_rst=TCP(sport=spliced_ack.dport, dport=spliced_ack.sport, + seq=1, ack=spliced_ack.seq, flags='RA') +send(ip/spliced_rst, iface=LOCAL_IF) +rst=TCP(sport=synack.dport, dport=synack.sport, + seq=payload_ack.ack, ack=synack.seq+1, flags='RA') +send(ip/rst, iface=LOCAL_IF) + +exit(0) diff --git a/regress/sys/kern/sosplice/scapy/scapy-payload-delay-connect.py b/regress/sys/kern/sosplice/scapy/scapy-payload-delay-connect.py new file mode 100644 index 00000000000..28d2423ef44 --- /dev/null +++ b/regress/sys/kern/sosplice/scapy/scapy-payload-delay-connect.py @@ -0,0 +1,106 @@ +#!/usr/local/bin/python2.7 +# send payload from client to relay before connecting to server + +import os +import sys +import threading +from addr import * +from scapy.all import * + +client=os.getpid() & 0xffff +relay=int(sys.argv[2]) +server=int(sys.argv[1]) + +class Sniff1(threading.Thread): + filter = None + captured = None + packet = None + def run(self): + self.captured = sniff(iface=LOCAL_IF, filter=self.filter, + count=1, timeout=5) + if self.captured: + self.packet = self.captured[0] + +ip=IP(src=FAKE_NET_ADDR, dst=REMOTE_ADDR) + +print "Send SYN packet, receive SYN+ACK" +syn=TCP(sport=client, dport=relay, seq=0, flags='S', window=(2**16)-1) +synack=sr1(ip/syn, iface=LOCAL_IF, timeout=5) + +if synack is None: + print "ERROR: No matching SYN+ACK packet received" + exit(1) + +print "Send ACK packet to finish handshake" +ack=TCP(sport=synack.dport, dport=synack.sport, + seq=1, ack=synack.seq+1, flags='A') +send(ip/ack, iface=LOCAL_IF) + +print "Expect spliced SYN" +sniffer = Sniff1(); +sniffer.filter = "src %s and dst %s and tcp port %u " \ + "and tcp[tcpflags] = tcp-syn" % (ip.dst, ip.src, server) +sniffer.start() +time.sleep(1) + +print "Send 10 bytes payload" +data="0123456789" +payload=TCP(sport=synack.dport, dport=synack.sport, + seq=1, ack=synack.seq+1, flags='APU')/data +payload_ack=sr1(ip/payload, iface=LOCAL_IF) + +if payload_ack is None: + print "ERROR: No payload ACK packet received" + exit(1) +if payload_ack.ack != len(data)+1: + print "ERROR: Expected ack %d, got %d in payload ACK" % \ + (len(data)+1, payload_ack.ack) + exit(1) + +sniffer.join(timeout=7) +spliced_syn = sniffer.packet + +if spliced_syn is None: + print "ERROR: No spliced SYN packet received" + exit(1) + +print "Expect spliced payload" +sniffer = Sniff1(); +sniffer.filter = "src %s and dst %s and tcp port %u " \ + "and tcp[tcpflags] = tcp-ack|tcp-push" % (ip.dst, ip.src, server) +sniffer.start() +time.sleep(1) + +print "Send spliced SYN+ACK packet to finish handshake" +spliced_synack=TCP(sport=spliced_syn.dport, dport=spliced_syn.sport, + seq=0, ack=spliced_syn.seq+1, flags='SA') +spliced_ack=sr1(ip/spliced_synack, iface=LOCAL_IF) + +if spliced_ack is None: + print "ERROR: No spliced ACK packet received" + exit(1) + +sniffer.join(timeout=7) +spliced_payload = sniffer.packet + +if spliced_payload is None: + print "ERROR: No spliced payload packet received" + exit(1) +if spliced_payload.seq != spliced_ack.seq: + print "ERROR: Expected seq %d, got %d in spliced payload" % \ + (spliced_ack.seq, spliced_payload.seq) + exit(1) +if spliced_payload.len-20-20 != len(data): + print "ERROR: Expected len %d, got %d in spliced payload" % \ + (len(data), spliced_payload.len-20-20) + exit(1) + +print "Kill connections with RST" +spliced_rst=TCP(sport=spliced_ack.dport, dport=spliced_ack.sport, + seq=1, ack=spliced_ack.seq, flags='RA') +send(ip/spliced_rst, iface=LOCAL_IF) +rst=TCP(sport=synack.dport, dport=synack.sport, + seq=payload_ack.ack, ack=synack.seq+1, flags='RA') +send(ip/rst, iface=LOCAL_IF) + +exit(0) diff --git a/regress/sys/kern/sosplice/scapy/scapy.pl b/regress/sys/kern/sosplice/scapy/scapy.pl index facb4da5b51..3af41f960c5 100644 --- a/regress/sys/kern/sosplice/scapy/scapy.pl +++ b/regress/sys/kern/sosplice/scapy/scapy.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -# $OpenBSD: scapy.pl,v 1.1 2017/10/27 16:59:14 bluhm Exp $ +# $OpenBSD: scapy.pl,v 1.2 2017/11/07 22:06:17 bluhm Exp $ # Copyright (c) 2010-2017 Alexander Bluhm <bluhm@openbsd.org> # @@ -71,6 +71,8 @@ if ($mode eq "relay") { rcvbuf => 2**12, sndbuf => 2**12, down => "Broken pipe|Connection reset by peer", + clientreadable => $testfile =~ /delay-connect/ ? 1 : 0, + nonblocking => 1, ); open(my $log, '<', $r->{logfile}) or die "Remote log file open failed: $!"; |