diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2012-01-06 21:52:16 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2012-01-06 21:52:16 +0000 |
commit | a279f2f3d85c99cdfafe036c75959e20e475e29d (patch) | |
tree | 422a17f85b302903a9eeb5948955a66cbcd4e194 | |
parent | 50e3db76c468b28e1179276043d44c3399329ae8 (diff) |
Add tests for IPv6 fragment reassembly. Hand-crafted ping6
echo-request fragments are sent by scapy to the target machine.
There they get reassembled and a echo-reply comes back. The ping6
payload is checked.
-rw-r--r-- | regress/sys/netinet6/frag6/Makefile | 109 | ||||
-rw-r--r-- | regress/sys/netinet6/frag6/frag6.py | 46 | ||||
-rw-r--r-- | regress/sys/netinet6/frag6/frag6_ext.py | 43 | ||||
-rw-r--r-- | regress/sys/netinet6/frag6/frag6_overhead.py | 51 | ||||
-rw-r--r-- | regress/sys/netinet6/frag6/frag6_overhead0.py | 49 | ||||
-rw-r--r-- | regress/sys/netinet6/frag6/frag6_overtail.py | 49 | ||||
-rw-r--r-- | regress/sys/netinet6/frag6/frag6_permute.py | 64 |
7 files changed, 411 insertions, 0 deletions
diff --git a/regress/sys/netinet6/frag6/Makefile b/regress/sys/netinet6/frag6/Makefile new file mode 100644 index 00000000000..a9857862394 --- /dev/null +++ b/regress/sys/netinet6/frag6/Makefile @@ -0,0 +1,109 @@ +# $OpenBSD: Makefile,v 1.1 2012/01/06 21:52:15 bluhm Exp $ + +# The following ports must be installed: +# +# python-2.7 interpreted object-oriented programming language +# py-libdnet python interface to libdnet +# scapy powerful interactive packet manipulation in python + +# This test needs a manual setup of two machines +# Set up machines: SRC DST +# SRC is the machine where this makefile is running. +# DST is running OpenBSD with pf disabled to test the IPv6 stack. +# +# +---+ 1 +---+ +# |SRC| ----> |DST| +# +---+ +---+ +# out in + +# Configure Addresses on the machines. +# Adapt interface and addresse variables to your local setup. +# +SRC_IF = tun0 +SRC_MAC = fe:e1:ba:d1:56:1f +DST_MAC = 52:54:00:12:34:50 + +SRC_OUT6 = fdd7:e83e:66bc:211:fce1:baff:fed1:561f +DST_IN6 = fdd7:e83e:66bc:211:5054:ff:fe12:3450 + +depend: addr.py + +# Create python include file containing the addresses. +addr.py: Makefile + rm -f $@ $@.tmp + echo 'SRC_IF = "${SRC_IF}"' >>$@.tmp + echo 'SRC_MAC = "${SRC_MAC}"' >>$@.tmp + echo 'DST_MAC = "${DST_MAC}"' >>$@.tmp +.for var in SRC_OUT DST_IN + echo '${var} = "${${var}}"' >>$@.tmp + echo '${var}6 = "${${var}6}"' >>$@.tmp +.endfor + mv $@.tmp $@ + +# Ping all addresses. This ensures that the ip addresses are configured +# and all routing table are set up to allow bidirectional packet flow. +TARGETS += ping6 +run-regress-ping6: + @echo '\n======== $@ ========' +.for ip in SRC_OUT DST_IN + @echo Check ping6 ${ip}6: + ping6 -n -c 1 ${${ip}6} +.endfor + +# Ping all addresses again but with 5000 bytes payload. These large +# packets get fragmented by SRC and must be handled by DST. +TARGETS += fragping6 +run-regress-fragping6: + @echo '\n======== $@ ========' +.for ip in SRC_OUT DST_IN + @echo Check ping6 ${ip}6: + ping6 -n -c 1 -s 5000 -m ${${ip}6} +.endfor + +# Send hand-crafted fragmented packet +TARGETS += frag6 +run-regress-frag6: addr.py + @echo '\n======== $@ ========' + @echo Check ping6 reassembly + ${SUDO} python2.7 frag6.py ${DST_IN6} + +# An hop by hop options extension header before the fragment header +TARGETS += frag6-ext +run-regress-frag6-ext: addr.py + @echo '\n======== $@ ========' + @echo Check ping6 extension header reassembly + ${SUDO} python2.7 frag6_ext.py ${DST_IN6} + +# fragmented packet with head overlapping first fragment +TARGETS += frag6-overhead0 +run-regress-frag6-overhead0: addr.py + @echo '\n======== $@ ========' + @echo Check ping6 head overlapping first fragment + ${SUDO} python2.7 frag6_overhead0.py ${DST_IN6} + +# fragmented packet with head overlapping second fragment +TARGETS += frag6-overhead +run-regress-frag6-overhead: addr.py + @echo '\n======== $@ ========' + @echo Check ping6 head overlapping second fragment + ${SUDO} python2.7 frag6_overhead.py ${DST_IN6} + +# fragmented packet with tail overlapping last fragment +TARGETS += frag6-overtail +run-regress-frag6-overtail: addr.py + @echo '\n======== $@ ========' + @echo Check ping6 tail overlapping last fragment + ${SUDO} python2.7 frag6_overtail.py ${DST_IN6} + +# fragmented packet permuted fragments +TARGETS += frag6-permute +run-regress-frag6-permute: addr.py + @echo '\n======== $@ ========' + @echo Check ping6 permuted fragments + ${SUDO} python2.7 frag6_permute.py ${DST_IN6} + +REGRESS_TARGETS = ${TARGETS:S/^/run-regress-/} + +CLEANFILES += *.pyc *.log + +.include <bsd.regress.mk> diff --git a/regress/sys/netinet6/frag6/frag6.py b/regress/sys/netinet6/frag6/frag6.py new file mode 100644 index 00000000000..2d8b2ec7bae --- /dev/null +++ b/regress/sys/netinet6/frag6/frag6.py @@ -0,0 +1,46 @@ +#!/usr/local/bin/python2.7 +# send 2 non-overlapping ping6 fragments + +# |--------| +# |----| + +import os +from addr import * +from scapy.all import * + +dstaddr=sys.argv[1] +pid=os.getpid() +payload="ABCDEFGHIJKLOMNO" +packet=IPv6(src=SRC_OUT6, dst=dstaddr)/ICMPv6EchoRequest(id=pid, data=payload) +frag=[] +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, m=1)/str(packet)[40:56]) +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, offset=2)/str(packet)[56:64]) +eth=[] +for f in frag: + pkt=IPv6(src=SRC_OUT6, dst=dstaddr)/f + eth.append(Ether(src=SRC_MAC, dst=DST_MAC)/pkt) + +if os.fork() == 0: + time.sleep(1) + sendp(eth, iface=SRC_IF) + os._exit(0) + +ans=sniff(iface=SRC_IF, timeout=3, filter= + "ip6 and src "+dstaddr+" and dst "+SRC_OUT6+" and icmp6") +for a in ans: + if a and a.type == scapy.layers.dot11.ETHER_TYPES.IPv6 and \ + ipv6nh[a.payload.nh] == 'ICMPv6' and \ + icmp6types[a.payload.payload.type] == 'Echo Reply': + id=a.payload.payload.id + print "id=%#x" % (id) + if id != pid: + print "WRONG ECHO REPLY ID" + exit(2) + data=a.payload.payload.data + print "payload=%s" % (data) + if data == payload: + exit(0) + print "PAYLOAD!=%s" % (payload) + exit(1) +print "NO ECHO REPLY" +exit(2) diff --git a/regress/sys/netinet6/frag6/frag6_ext.py b/regress/sys/netinet6/frag6/frag6_ext.py new file mode 100644 index 00000000000..3eb51627fd6 --- /dev/null +++ b/regress/sys/netinet6/frag6/frag6_ext.py @@ -0,0 +1,43 @@ +#!/usr/local/bin/python2.7 +# send 2 ping6 fragments with hop-by-hop extension header + +import os +from addr import * +from scapy.all import * + +dstaddr=sys.argv[1] +pid=os.getpid() +payload="ABCDEFGHIJKLOMNO" +packet=IPv6(src=SRC_OUT6, dst=dstaddr)/ICMPv6EchoRequest(id=pid, data=payload) +frag=[] +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, m=1)/str(packet)[40:56]) +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, offset=2)/str(packet)[56:64]) +eth=[] +for f in frag: + pkt=IPv6(src=SRC_OUT6, dst=dstaddr)/IPv6ExtHdrHopByHop()/f + eth.append(Ether(src=SRC_MAC, dst=DST_MAC)/pkt) + +if os.fork() == 0: + time.sleep(1) + sendp(eth, iface=SRC_IF) + os._exit(0) + +ans=sniff(iface=SRC_IF, timeout=3, filter= + "ip6 and src "+dstaddr+" and dst "+SRC_OUT6+" and icmp6") +for a in ans: + if a and a.type == scapy.layers.dot11.ETHER_TYPES.IPv6 and \ + ipv6nh[a.payload.nh] == 'ICMPv6' and \ + icmp6types[a.payload.payload.type] == 'Echo Reply': + id=a.payload.payload.id + print "id=%#x" % (id) + if id != pid: + print "WRONG ECHO REPLY ID" + exit(2) + data=a.payload.payload.data + print "payload=%s" % (data) + if data == payload: + exit(0) + print "PAYLOAD!=%s" % (payload) + exit(1) +print "NO ECHO REPLY" +exit(2) diff --git a/regress/sys/netinet6/frag6/frag6_overhead.py b/regress/sys/netinet6/frag6/frag6_overhead.py new file mode 100644 index 00000000000..388258358bc --- /dev/null +++ b/regress/sys/netinet6/frag6/frag6_overhead.py @@ -0,0 +1,51 @@ +#!/usr/local/bin/python2.7 +# send ping6 fragment that overlaps the second fragment with the head + +# |----| +# |----| +# |XXXXXXXXX| +# |----| + +import os +from addr import * +from scapy.all import * + +dstaddr=sys.argv[1] +pid=os.getpid() +payload="ABCDEFGHIJKLOMNO" +dummy="0123456701234567" +packet=IPv6(src=SRC_OUT6, dst=dstaddr)/ICMPv6EchoRequest(id=pid, data=payload) +frag=[] +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, m=1)/str(packet)[40:48]) +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, offset=1, m=1)/str(packet)[48:56]) +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, offset=1)/dummy) +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, offset=2)/str(packet)[56:64]) +eth=[] +for f in frag: + pkt=IPv6(src=SRC_OUT6, dst=dstaddr)/f + eth.append(Ether(src=SRC_MAC, dst=DST_MAC)/pkt) + +if os.fork() == 0: + time.sleep(1) + sendp(eth, iface=SRC_IF) + os._exit(0) + +ans=sniff(iface=SRC_IF, timeout=3, filter= + "ip6 and src "+dstaddr+" and dst "+SRC_OUT6+" and icmp6") +for a in ans: + if a and a.type == scapy.layers.dot11.ETHER_TYPES.IPv6 and \ + ipv6nh[a.payload.nh] == 'ICMPv6' and \ + icmp6types[a.payload.payload.type] == 'Echo Reply': + id=a.payload.payload.id + print "id=%#x" % (id) + if id != pid: + print "WRONG ECHO REPLY ID" + exit(2) + data=a.payload.payload.data + print "payload=%s" % (data) + if data == payload: + exit(0) + print "PAYLOAD!=%s" % (payload) + exit(1) +print "NO ECHO REPLY" +exit(2) diff --git a/regress/sys/netinet6/frag6/frag6_overhead0.py b/regress/sys/netinet6/frag6/frag6_overhead0.py new file mode 100644 index 00000000000..c272a8042d1 --- /dev/null +++ b/regress/sys/netinet6/frag6/frag6_overhead0.py @@ -0,0 +1,49 @@ +#!/usr/local/bin/python2.7 +# send ping6 fragment that overlaps the first fragment with the head + +# |--------| +# |XXXXXXXX| +# |----| + +import os +from addr import * +from scapy.all import * + +dstaddr=sys.argv[1] +pid=os.getpid() +payload="ABCDEFGHIJKLOMNO" +dummy="0123456701234567" +packet=IPv6(src=SRC_OUT6, dst=dstaddr)/ICMPv6EchoRequest(id=pid, data=payload) +frag=[] +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, m=1)/str(packet)[40:56]) +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, offset=1)/dummy) +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, offset=2)/str(packet)[56:64]) +eth=[] +for f in frag: + pkt=IPv6(src=SRC_OUT6, dst=dstaddr)/f + eth.append(Ether(src=SRC_MAC, dst=DST_MAC)/pkt) + +if os.fork() == 0: + time.sleep(1) + sendp(eth, iface=SRC_IF) + os._exit(0) + +ans=sniff(iface=SRC_IF, timeout=3, filter= + "ip6 and src "+dstaddr+" and dst "+SRC_OUT6+" and icmp6") +for a in ans: + if a and a.type == scapy.layers.dot11.ETHER_TYPES.IPv6 and \ + ipv6nh[a.payload.nh] == 'ICMPv6' and \ + icmp6types[a.payload.payload.type] == 'Echo Reply': + id=a.payload.payload.id + print "id=%#x" % (id) + if id != pid: + print "WRONG ECHO REPLY ID" + exit(2) + data=a.payload.payload.data + print "payload=%s" % (data) + if data == payload: + exit(0) + print "PAYLOAD!=%s" % (payload) + exit(1) +print "NO ECHO REPLY" +exit(2) diff --git a/regress/sys/netinet6/frag6/frag6_overtail.py b/regress/sys/netinet6/frag6/frag6_overtail.py new file mode 100644 index 00000000000..dc4d40b215b --- /dev/null +++ b/regress/sys/netinet6/frag6/frag6_overtail.py @@ -0,0 +1,49 @@ +#!/usr/local/bin/python2.7 +# send ping6 fragment that overlaps the last fragment with the tail + +# |----| +# |XXXXXXXX| +# |--------| + +import os +from addr import * +from scapy.all import * + +dstaddr=sys.argv[1] +pid=os.getpid() +payload="ABCDEFGHIJKLOMNO" +dummy="0123456701234567" +packet=IPv6(src=SRC_OUT6, dst=dstaddr)/ICMPv6EchoRequest(id=pid, data=payload) +frag=[] +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, offset=2)/str(packet)[56:64]) +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, offset=1)/dummy) +frag.append(IPv6ExtHdrFragment(nh=58, id=pid, m=1)/str(packet)[40:56]) +eth=[] +for f in frag: + pkt=IPv6(src=SRC_OUT6, dst=dstaddr)/f + eth.append(Ether(src=SRC_MAC, dst=DST_MAC)/pkt) + +if os.fork() == 0: + time.sleep(1) + sendp(eth, iface=SRC_IF) + os._exit(0) + +ans=sniff(iface=SRC_IF, timeout=3, filter= + "ip6 and src "+dstaddr+" and dst "+SRC_OUT6+" and icmp6") +for a in ans: + if a and a.type == scapy.layers.dot11.ETHER_TYPES.IPv6 and \ + ipv6nh[a.payload.nh] == 'ICMPv6' and \ + icmp6types[a.payload.payload.type] == 'Echo Reply': + id=a.payload.payload.id + print "id=%#x" % (id) + if id != pid: + print "WRONG ECHO REPLY ID" + exit(2) + data=a.payload.payload.data + print "payload=%s" % (data) + if data == payload: + exit(0) + print "PAYLOAD!=%s" % (payload) + exit(1) +print "NO ECHO REPLY" +exit(2) diff --git a/regress/sys/netinet6/frag6/frag6_permute.py b/regress/sys/netinet6/frag6/frag6_permute.py new file mode 100644 index 00000000000..0df0682e675 --- /dev/null +++ b/regress/sys/netinet6/frag6/frag6_permute.py @@ -0,0 +1,64 @@ +#!/usr/local/bin/python2.7 +# send 3 non-overlapping ping6 fragments in all possible orders + +# |----| +# |----| +# |----| + +import os +from addr import * +from scapy.all import * + +permute=[] +permute.append([0,1,2]) +permute.append([0,2,1]) +permute.append([1,0,2]) +permute.append([2,0,1]) +permute.append([1,2,0]) +permute.append([2,1,0]) + +dstaddr=sys.argv[1] +pid=os.getpid() +payload="ABCDEFGHIJKLOMNO" + +for p in permute: + pid += 1 + packet=IPv6(src=SRC_OUT6, dst=dstaddr)/ \ + ICMPv6EchoRequest(id=pid, data=payload) + frag=[] + frag.append(IPv6ExtHdrFragment(nh=58, id=pid, m=1)/ \ + str(packet)[40:48]) + frag.append(IPv6ExtHdrFragment(nh=58, id=pid, offset=1, m=1)/ \ + str(packet)[48:56]) + frag.append(IPv6ExtHdrFragment(nh=58, id=pid, offset=2)/ \ + str(packet)[56:64]) + eth=[] + for i in range(3): + pkt=IPv6(src=SRC_OUT6, dst=dstaddr)/frag[p[i]] + eth.append(Ether(src=SRC_MAC, dst=DST_MAC)/pkt) + + if os.fork() == 0: + time.sleep(1) + sendp(eth, iface=SRC_IF) + os._exit(0) + + ans=sniff(iface=SRC_IF, timeout=3, filter= + "ip6 and src "+dstaddr+" and dst "+SRC_OUT6+" and icmp6") + for a in ans: + if a and a.type == scapy.layers.dot11.ETHER_TYPES.IPv6 and \ + ipv6nh[a.payload.nh] == 'ICMPv6' and \ + icmp6types[a.payload.payload.type] == 'Echo Reply': + id=a.payload.payload.id + print "id=%#x" % (id) + if id != pid: + print "WRONG ECHO REPLY ID" + exit(2) + data=a.payload.payload.data + print "payload=%s" % (data) + if data == payload: + break + print "PAYLOAD!=%s" % (payload) + exit(1) + else: + print "NO ECHO REPLY" + exit(2) |