summaryrefslogtreecommitdiff
path: root/regress/sys
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2021-05-22 18:38:41 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2021-05-22 18:38:41 +0000
commitf595f93b2e67707edf8622d4952f92e2189234d4 (patch)
tree2e885c410aeee96b7bab20b956a73d93e3382643 /regress/sys
parent94a0ae27acf0a09681763f6738c44a5a8a211691 (diff)
Test more corner cases of IPv4 fragment reassembly.
Diffstat (limited to 'regress/sys')
-rw-r--r--regress/sys/netinet/frag/LICENSE2
-rw-r--r--regress/sys/netinet/frag/Makefile4
-rw-r--r--regress/sys/netinet/frag/frag_overindex.py65
-rw-r--r--regress/sys/netinet/frag/frag_overlimit.py72
-rw-r--r--regress/sys/netinet/frag/frag_overreplace.py68
5 files changed, 208 insertions, 3 deletions
diff --git a/regress/sys/netinet/frag/LICENSE b/regress/sys/netinet/frag/LICENSE
index 866739d7ee3..d5bbbd0a691 100644
--- a/regress/sys/netinet/frag/LICENSE
+++ b/regress/sys/netinet/frag/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2012-2020 Alexander Bluhm <bluhm@openbsd.org>
+Copyright (c) 2012-2021 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/netinet/frag/Makefile b/regress/sys/netinet/frag/Makefile
index 29f01c0e202..a534d6201e4 100644
--- a/regress/sys/netinet/frag/Makefile
+++ b/regress/sys/netinet/frag/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.10 2020/12/30 21:40:33 kn Exp $
+# $OpenBSD: Makefile,v 1.11 2021/05/22 18:38:40 bluhm Exp $
# The following ports must be installed:
#
@@ -104,7 +104,7 @@ run-stack-frag_mf1end.py:
# the stack allows fragments with MF together with fragments without MF
@echo DISABLED
-run-stack-frag_queuelimit.py:
+run-stack-frag_queuelimit.py run-stack-frag_overlimit.py:
# the stack does not limit the amount of fragments during reassembly
@echo DISABLED
diff --git a/regress/sys/netinet/frag/frag_overindex.py b/regress/sys/netinet/frag/frag_overindex.py
new file mode 100644
index 00000000000..52f44a6263c
--- /dev/null
+++ b/regress/sys/netinet/frag/frag_overindex.py
@@ -0,0 +1,65 @@
+#!/usr/local/bin/python3
+
+print("ping fragment that overlaps the first fragment at index boundary")
+
+# index boundary 4096 |
+# |--------------|
+# ....
+# |--------------|
+# |XXXX-----|
+# |--------------|
+
+# this should trigger "frag index %d, new %d" log in kernel
+
+import os
+from addr import *
+from scapy.all import *
+
+pid=os.getpid()
+eid=pid & 0xffff
+payload=b"ABCDEFGHIJKLMNOP"
+dummy=b"01234567"
+fragsize=64
+boundary=4096
+fragnum=int(boundary/fragsize)
+packet=IP(src=LOCAL_ADDR, dst=REMOTE_ADDR)/ \
+ ICMP(type='echo-request', id=eid)/ \
+ (int((boundary+8)/len(payload)) * payload)
+frag=[]
+fid=pid & 0xffff
+for i in range(fragnum-1):
+ frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
+ frag=(i*fragsize)>>3, flags='MF')/
+ bytes(packet)[20+i*fragsize:20+(i+1)*fragsize])
+frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
+ frag=(boundary-8)>>3)/
+ (dummy+bytes(packet)[20+boundary:20+boundary+8]))
+frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
+ frag=(boundary-fragsize)>>3, flags='MF')/
+ bytes(packet)[20+boundary-fragsize:20+boundary])
+eth=[]
+for f in frag:
+ eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/f)
+
+if os.fork() == 0:
+ time.sleep(1)
+ for e in eth:
+ sendp(e, iface=LOCAL_IF)
+ time.sleep(0.001)
+ os._exit(0)
+
+ans=sniff(iface=LOCAL_IF, timeout=5, filter=
+ "ip and src "+REMOTE_ADDR+" and dst "+LOCAL_ADDR+" and icmp")
+for a in ans:
+ if a and a.type == ETH_P_IP and \
+ a.payload.proto == 1 and \
+ a.payload.frag == 0 and \
+ icmptypes[a.payload.payload.type] == 'echo-reply':
+ id=a.payload.payload.id
+ print("id=%#x" % (id))
+ if id != eid:
+ print("WRONG ECHO REPLY ID")
+ exit(2)
+ exit(0)
+print("NO ECHO REPLY")
+exit(1)
diff --git a/regress/sys/netinet/frag/frag_overlimit.py b/regress/sys/netinet/frag/frag_overlimit.py
new file mode 100644
index 00000000000..376e8edf08c
--- /dev/null
+++ b/regress/sys/netinet/frag/frag_overlimit.py
@@ -0,0 +1,72 @@
+#!/usr/local/bin/python3
+
+print("ping fragment at index boundary that cannot be requeued")
+
+# index boundary 4096 |
+# |--------------|
+# ....
+# |--------------|
+# |--------------|
+# ....----|
+# |XXXX-----|
+# |--------------|
+
+# this should trigger "fragment requeue limit exceeded" log in kernel
+
+import os
+from itertools import chain
+from addr import *
+from scapy.all import *
+
+pid=os.getpid()
+eid=pid & 0xffff
+payload=b"ABCDEFGHIJKLMNOP"
+dummy=b"01234567"
+fragsize=64
+boundary=4096
+fragnum=int(boundary/fragsize)
+packet=IP(src=LOCAL_ADDR, dst=REMOTE_ADDR)/ \
+ ICMP(type='echo-request', id=eid)/ \
+ (int((boundary+boundary)/len(payload)) * payload)
+frag=[]
+fid=pid & 0xffff
+for i in chain(range(fragnum-1), range(fragnum, fragnum+fragnum-1)):
+ frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
+ frag=(i*fragsize)>>3, flags='MF')/
+ bytes(packet)[20+i*fragsize:20+(i+1)*fragsize])
+frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
+ frag=(boundary+boundary-fragsize)>>3)/
+ bytes(packet)[20+boundary+boundary-fragsize:])
+frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
+ frag=(boundary-8)>>3, flags='MF')/
+ (dummy+bytes(packet)[20+boundary:20+boundary+8]))
+frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
+ frag=(boundary-fragsize)>>3, flags='MF')/
+ bytes(packet)[20+boundary-fragsize:20+boundary])
+eth=[]
+for f in frag:
+ eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/f)
+
+if os.fork() == 0:
+ time.sleep(1)
+ for e in eth:
+ sendp(e, iface=LOCAL_IF)
+ time.sleep(0.001)
+ os._exit(0)
+
+ans=sniff(iface=LOCAL_IF, timeout=10, filter=
+ "ip and src "+REMOTE_ADDR+" and dst "+LOCAL_ADDR+" and icmp")
+for a in ans:
+ if a and a.type == ETH_P_IP and \
+ a.payload.proto == 1 and \
+ a.payload.frag == 0 and \
+ icmptypes[a.payload.payload.type] == 'echo-reply':
+ id=a.payload.payload.id
+ print("id=%#x" % (id))
+ if id != eid:
+ print("WRONG ECHO REPLY ID")
+ exit(2)
+ print("ECHO REPLY")
+ exit(1)
+print("no echo reply")
+exit(0)
diff --git a/regress/sys/netinet/frag/frag_overreplace.py b/regress/sys/netinet/frag/frag_overreplace.py
new file mode 100644
index 00000000000..0335d946385
--- /dev/null
+++ b/regress/sys/netinet/frag/frag_overreplace.py
@@ -0,0 +1,68 @@
+#!/usr/local/bin/python3
+
+print("ping fragment that overlaps fragment at index boundary and replace it")
+
+# index boundary 4096 |
+# |--------------|
+# ....
+# |--------------|
+# |XXXX-----|
+# |--------------|
+# |--------------|
+
+# this should trigger "frag tail overlap %d" and "frag head overlap %d"
+
+import os
+from addr import *
+from scapy.all import *
+
+pid=os.getpid()
+eid=pid & 0xffff
+payload=b"ABCDEFGHIJKLMNOP"
+dummy=b"01234567"
+fragsize=1024
+boundary=4096
+fragnum=int(boundary/fragsize)
+packet=IP(src=LOCAL_ADDR, dst=REMOTE_ADDR)/ \
+ ICMP(type='echo-request', id=eid)/ \
+ (int((boundary+fragsize)/len(payload)) * payload)
+frag=[]
+fid=pid & 0xffff
+for i in range(fragnum-1):
+ frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
+ frag=(i*fragsize)>>3, flags='MF')/
+ bytes(packet)[20+i*fragsize:20+(i+1)*fragsize])
+frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
+ frag=(boundary-8)>>3, flags='MF')/
+ (dummy+bytes(packet)[20+boundary:20+boundary+8]))
+frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
+ frag=(boundary-fragsize)>>3, flags='MF')/
+ bytes(packet)[20+boundary-fragsize:20+boundary])
+frag.append(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR, proto=1, id=fid,
+ frag=(boundary)>>3)/bytes(packet)[20+boundary:])
+eth=[]
+for f in frag:
+ eth.append(Ether(src=LOCAL_MAC, dst=REMOTE_MAC)/f)
+
+if os.fork() == 0:
+ time.sleep(1)
+ for e in eth:
+ sendp(e, iface=LOCAL_IF)
+ time.sleep(0.001)
+ os._exit(0)
+
+ans=sniff(iface=LOCAL_IF, timeout=3, filter=
+ "ip and src "+REMOTE_ADDR+" and dst "+LOCAL_ADDR+" and icmp")
+for a in ans:
+ if a and a.type == ETH_P_IP and \
+ a.payload.proto == 1 and \
+ a.payload.frag == 0 and \
+ icmptypes[a.payload.payload.type] == 'echo-reply':
+ id=a.payload.payload.id
+ print("id=%#x" % (id))
+ if id != eid:
+ print("WRONG ECHO REPLY ID")
+ exit(2)
+ exit(0)
+print("NO ECHO REPLY")
+exit(1)