summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2012-01-06 21:52:16 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2012-01-06 21:52:16 +0000
commita279f2f3d85c99cdfafe036c75959e20e475e29d (patch)
tree422a17f85b302903a9eeb5948955a66cbcd4e194
parent50e3db76c468b28e1179276043d44c3399329ae8 (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/Makefile109
-rw-r--r--regress/sys/netinet6/frag6/frag6.py46
-rw-r--r--regress/sys/netinet6/frag6/frag6_ext.py43
-rw-r--r--regress/sys/netinet6/frag6/frag6_overhead.py51
-rw-r--r--regress/sys/netinet6/frag6/frag6_overhead0.py49
-rw-r--r--regress/sys/netinet6/frag6/frag6_overtail.py49
-rw-r--r--regress/sys/netinet6/frag6/frag6_permute.py64
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)