diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2017-01-18 19:27:00 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2017-01-18 19:27:00 +0000 |
commit | a011092ef38ac3ac057181567c0037a295149930 (patch) | |
tree | 3b4d604547133ead5a4976f4e5ad9a72272010e1 /regress/sys/netinet | |
parent | bde2df117499cb77cc0553de690dcdabdcc3c0b3 (diff) |
Add tests that generate IPv6 atomic fragments for UDP and TCP by
sending an ICMP6 too big packet with MTU 1272.
Diffstat (limited to 'regress/sys/netinet')
-rw-r--r-- | regress/sys/netinet/pmtu/Makefile | 13 | ||||
-rwxr-xr-x | regress/sys/netinet/pmtu/tcp_atomicfrag6.py | 78 | ||||
-rwxr-xr-x | regress/sys/netinet/pmtu/tcp_connect.py | 2 | ||||
-rwxr-xr-x | regress/sys/netinet/pmtu/tcp_connect6.py | 2 | ||||
-rwxr-xr-x | regress/sys/netinet/pmtu/udp_atomicfrag6.py | 78 | ||||
-rwxr-xr-x | regress/sys/netinet/pmtu/udp_echo6.py | 5 |
6 files changed, 174 insertions, 4 deletions
diff --git a/regress/sys/netinet/pmtu/Makefile b/regress/sys/netinet/pmtu/Makefile index ddd6c470492..6c0193d580e 100644 --- a/regress/sys/netinet/pmtu/Makefile +++ b/regress/sys/netinet/pmtu/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.7 2016/11/09 12:43:36 bluhm Exp $ +# $OpenBSD: Makefile,v 1.8 2017/01/18 19:26:59 bluhm Exp $ # The following ports must be installed: # @@ -146,6 +146,17 @@ run-regress-gateway6: run-regress-udp6 grep -q 'flags: <UP,GATEWAY,HOST,DYNAMIC,DONE>' pmtu.route ${SUDO} ${PYTHON}udp_echo6.py +TARGETS += tcpfrag6 udpfrag6 +run-regress-tcpfrag6: addr.py reset-route6 + @echo '\n======== $@ ========' + @echo Send ICMP6 and try to trigger a short TCP segment + ${SUDO} ${PYTHON}tcp_atomicfrag6.py +run-regress-udpfrag6: addr.py reset-route6 + @echo '\n======== $@ ========' + @echo Send ICMP6 and try to trigger an atomic UDP IPv6 fragment + ${SUDO} ${PYTHON}udp_atomicfrag6.py + + REGRESS_TARGETS = ${TARGETS:S/^/run-regress-/} CLEANFILES += addr.py *.pyc *.log *.route diff --git a/regress/sys/netinet/pmtu/tcp_atomicfrag6.py b/regress/sys/netinet/pmtu/tcp_atomicfrag6.py new file mode 100755 index 00000000000..d0646b544d5 --- /dev/null +++ b/regress/sys/netinet/pmtu/tcp_atomicfrag6.py @@ -0,0 +1,78 @@ +#!/usr/local/bin/python2.7 + +import os +from addr import * +from scapy.all import * + +e=Ether(src=LOCAL_MAC, dst=REMOTE_MAC) +ip6=IPv6(src=FAKE_NET_ADDR6, dst=REMOTE_ADDR6) +port=os.getpid() & 0xffff + +print "Send SYN packet, receive SYN+ACK." +syn=TCP(sport=port, dport='chargen', seq=1, flags='S', window=(2**16)-1) +synack=srp1(e/ip6/syn, iface=LOCAL_IF, timeout=5) + +if synack is None: + print "ERROR: no SYN+ACK from chargen server received" + exit(1) + +print "Send ACK packet, receive chargen data." +ack=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='A', + ack=synack.seq+1, window=(2**16)-1) +data=srp1(e/ip6/ack, iface=LOCAL_IF, timeout=5) + +if data is None: + print "ERROR: no data from chargen server received" + exit(1) + +print "Fill our receive buffer." +time.sleep(1) + +print "Send ICMP6 packet too big packet with MTU 1272." +icmp6=ICMPv6PacketTooBig(mtu=1272)/data.payload +sendp(e/IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/icmp6, iface=LOCAL_IF) + +print "Path MTU discovery will resend first data with length 1272." +# srp1 cannot be used, fragment answer will not match on outgoing udp packet +if os.fork() == 0: + time.sleep(1) + sendp(e/ip6/ack, iface=LOCAL_IF) + os._exit(0) + +ans=sniff(iface=LOCAL_IF, timeout=3, filter= + "ip6 and src "+ip6.dst+" and dst "+ip6.src+" and proto ipv6-frag") + +for a in ans: + fh=a.payload.payload + if fh.offset != 0 or fh.nh != (ip6/syn).nh: + continue + th=fh.payload + if th.sport != syn.dport or th.dport != syn.sport: + continue + frag=a + break +else: + print "ERROR: no fragement retransmit from chargen server received" + exit(1) + +print "Cleanup the other's socket with a reset packet." +rst=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='AR', + ack=synack.seq+1) +sendp(e/ip6/rst, iface=LOCAL_IF) + +if frag.offset != 0: + print "ERROR: TCP fragment is not atomic, offset is %d." % frag.offset + exit(1) + +if frag.m != 0: + print "ERROR: TCP fragment is not atomic, more fragment bit is set." + exit(1) + +print "Atomic fragment contains 8 octet header, so expected len is 1280" +flen = frag.plen + len(IPv6()) +print "flen=%d" % flen +if flen != 1280: + print "ERROR: TCP atomic fragment len is %d, expected 1280." % flen + exit(1) + +exit(0) diff --git a/regress/sys/netinet/pmtu/tcp_connect.py b/regress/sys/netinet/pmtu/tcp_connect.py index 2e3ea22e02e..0ba209800a1 100755 --- a/regress/sys/netinet/pmtu/tcp_connect.py +++ b/regress/sys/netinet/pmtu/tcp_connect.py @@ -15,7 +15,7 @@ if synack is None: print "ERROR: no SYN+ACK from chargen server received" exit(1) -print "Send ack packet, receive chargen data." +print "Send ACK packet, receive chargen data." ack=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='A', ack=synack.seq+1, window=(2**16)-1) data=sr1(ip/ack, iface=LOCAL_IF, timeout=5) diff --git a/regress/sys/netinet/pmtu/tcp_connect6.py b/regress/sys/netinet/pmtu/tcp_connect6.py index dec42858368..dc0c4ef0690 100755 --- a/regress/sys/netinet/pmtu/tcp_connect6.py +++ b/regress/sys/netinet/pmtu/tcp_connect6.py @@ -16,7 +16,7 @@ if synack is None: print "ERROR: no SYN+ACK from chargen server received" exit(1) -print "Send ack packet, receive chargen data." +print "Send ACK packet, receive chargen data." ack=TCP(sport=synack.dport, dport=synack.sport, seq=2, flags='A', ack=synack.seq+1, window=(2**16)-1) data=srp1(e/ip6/ack, iface=LOCAL_IF, timeout=5) diff --git a/regress/sys/netinet/pmtu/udp_atomicfrag6.py b/regress/sys/netinet/pmtu/udp_atomicfrag6.py new file mode 100755 index 00000000000..ef25af79af5 --- /dev/null +++ b/regress/sys/netinet/pmtu/udp_atomicfrag6.py @@ -0,0 +1,78 @@ +#!/usr/local/bin/python2.7 + +import os +import string +import random +from addr import * +from scapy.all import * + +e=Ether(src=LOCAL_MAC, dst=REMOTE_MAC) +ip6=IPv6(src=FAKE_NET_ADDR6, dst=REMOTE_ADDR6) +port=os.getpid() & 0xffff +# inetd ignores packets from privileged port or nfs +if port < 1024 or port == 2049: + port+=1024 + +print "Send UDP packet with 1200 octets payload, receive echo." +data=''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + + string.digits) for _ in range(1200)) +udp=UDP(sport=port, dport='echo')/data +echo=srp1(e/ip6/udp, iface=LOCAL_IF, timeout=5) + +if echo is None: + print "ERROR: no UDP answer from echo server received" + exit(1) + +print "Send ICMP6 packet too big packet with MTU 1272." +icmp6=ICMPv6PacketTooBig(mtu=1272)/echo.payload +sendp(e/IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/icmp6, iface=LOCAL_IF) + +print "Clear route cache at echo socket by sending from different address." +sendp(e/IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/udp, iface=LOCAL_IF) + +print "Path MTU discovery will send UDP atomic fragment with length 1256." +# srp1 cannot be used, fragment answer will not match on outgoing udp packet +if os.fork() == 0: + time.sleep(1) + sendp(e/ip6/udp, iface=LOCAL_IF) + os._exit(0) + +ans=sniff(iface=LOCAL_IF, timeout=3, filter= + "ip6 and src "+ip6.dst+" and dst "+ip6.src+" and proto ipv6-frag") + +for a in ans: + fh=a.payload.payload + if fh.offset != 0 or fh.nh != (ip6/udp).nh: + continue + uh=fh.payload + if uh.sport != udp.dport or uh.dport != udp.sport: + continue + frag=a + break +else: + print "ERROR: no matching IPv6 fragment UDP answer found" + exit(1) + +if frag.offset != 0: + print "ERROR: TCP fragment is not atomic, offset is %d." % frag.offset + exit(1) + +if frag.m != 0: + print "ERROR: TCP fragment is not atomic, more fragment bit is set." + exit(1) + +print "UDP echo has IPv6 and UDP header, so expected payload len is 1248" +elen = echo.plen + len(IPv6()) +print "elen=%d" % elen +if elen != 1248: + print "ERROR: UDP echo payload len is %d, expected 1248." % elen + exit(1) + +print "Atomic fragment contains 8 octet header, so expected len is 1256" +flen = frag.plen + len(IPv6()) +print "flen=%d" % flen +if flen != 1256: + print "ERROR: UDP atomic fragment len is %d, expected 1256." % flen + exit(1) + +exit(0) diff --git a/regress/sys/netinet/pmtu/udp_echo6.py b/regress/sys/netinet/pmtu/udp_echo6.py index 55f86c37072..72b815baa94 100755 --- a/regress/sys/netinet/pmtu/udp_echo6.py +++ b/regress/sys/netinet/pmtu/udp_echo6.py @@ -9,6 +9,9 @@ from scapy.all import * e=Ether(src=LOCAL_MAC, dst=REMOTE_MAC) ip6=IPv6(src=FAKE_NET_ADDR6, dst=REMOTE_ADDR6) port=os.getpid() & 0xffff +# inetd ignores packets from privileged port or nfs +if port < 1024 or port == 2049: + port+=1024 print "Send UDP packet with 1400 octets payload, receive echo." data=''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + @@ -54,7 +57,7 @@ print "UDP echo has IPv6 and UDP header, so expected payload len is 1448" elen = echo.plen + len(IPv6()) print "elen=%d" % elen if elen != 1448: - print "ERROR: UDP echo paylod len is %d, expected 1448." % elen + print "ERROR: UDP echo payload len is %d, expected 1448." % elen exit(1) print "Fragments contain multiple of 8 octets, so expected len is 1296" |