Replace fork with sniffer thread in Python. Clear the BPF list
authorbluhm <bluhm@openbsd.org>
Mon, 30 Jul 2018 18:05:56 +0000 (18:05 +0000)
committerbluhm <bluhm@openbsd.org>
Mon, 30 Jul 2018 18:05:56 +0000 (18:05 +0000)
before sniffing, Scapy 2.4.0 remembers old packets that confuse the
test.

regress/sys/netinet/pmtu/tcp_atomicfrag6.py
regress/sys/netinet/pmtu/tcp_connect.py
regress/sys/netinet/pmtu/tcp_connect6.py
regress/sys/netinet/pmtu/udp_atomicfrag6.py
regress/sys/netinet/pmtu/udp_echo6.py

index cb724a8..247068f 100755 (executable)
@@ -1,9 +1,24 @@
 #!/usr/local/bin/python2.7
 
 import os
+import threading
 from addr import *
 from scapy.all import *
 
+class Sniff(threading.Thread):
+       filter = None
+       captured = None
+       packet = None
+       def __init__(self):
+               # clear packets buffered by scapy bpf
+               sniff(iface=LOCAL_IF, timeout=1)
+               super(Sniff, self).__init__()
+       def run(self):
+               self.captured = sniff(iface=LOCAL_IF, filter=self.filter,
+                   timeout=3)
+               if self.captured:
+                       self.packet = self.captured[0]
+
 e=Ether(src=LOCAL_MAC, dst=REMOTE_MAC)
 ip6=IPv6(src=FAKE_NET_ADDR6, dst=REMOTE_ADDR6)
 tport=os.getpid() & 0xffff
@@ -28,21 +43,23 @@ if data is None:
 print "Fill our receive buffer."
 time.sleep(1)
 
+# srp1 cannot be used, fragment answer will not match outgoing ICMP6 packet
+sniffer = Sniff()
+sniffer.filter = \
+    "ip6 and src "+ip6.dst+" and dst "+ip6.src+" and proto ipv6-frag"
+sniffer.start()
+time.sleep(1)
+
 print "Send ICMP6 packet too big packet with MTU 1272."
 icmp6=ICMPv6PacketTooBig(mtu=1272)/data.payload
-# srp1 cannot be used, fragment answer will not match outgoing ICMP6 packet
-if os.fork() == 0:
-       time.sleep(1)
-       sendp(e/IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/icmp6, iface=LOCAL_IF)
-       os._exit(0)
+sendp(e/IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/icmp6, iface=LOCAL_IF)
 
 print "Path MTU discovery will not resend data, ICMP6 packet is ignored."
-ans=sniff(iface=LOCAL_IF, timeout=3, filter=
-    "ip6 and src "+ip6.dst+" and dst "+ip6.src+" and proto ipv6-frag")
+sniffer.join(timeout=5)
 
 print "IPv6 atomic fragments must not be generated."
 frag=None
-for a in ans:
+for a in sniffer.captured:
        fh=a.payload.payload
        if fh.offset != 0 or fh.nh != (ip6/syn).nh:
                continue
index 85c5044..6f27562 100755 (executable)
@@ -1,9 +1,24 @@
 #!/usr/local/bin/python2.7
 
 import os
+import threading
 from addr import *
 from scapy.all import *
 
+class Sniff1(threading.Thread):
+       filter = None
+       captured = None
+       packet = None
+       def __init__(self):
+               # clear packets buffered by scapy bpf
+               sniff(iface=LOCAL_IF, timeout=1)
+               super(Sniff1, self).__init__()
+       def run(self):
+               self.captured = sniff(iface=LOCAL_IF, filter=self.filter,
+                   count=1, timeout=3)
+               if self.captured:
+                       self.packet = self.captured[0]
+
 ip=IP(src=FAKE_NET_ADDR, dst=REMOTE_ADDR)
 tport=os.getpid() & 0xffff
 
@@ -27,19 +42,22 @@ if data is None:
 print "Fill our receive buffer."
 time.sleep(1)
 
+# sr1 cannot be used, TCP data will not match outgoing ICMP packet
+sniffer = Sniff1()
+sniffer.filter = \
+    "ip and src %s and tcp port %u and dst %s and tcp port %u" % \
+    (ip.dst, syn.dport, ip.src, syn.sport)
+sniffer.start()
+time.sleep(1)
+
 print "Send ICMP fragmentation needed packet with MTU 1300."
 icmp=ICMP(type="dest-unreach", code="fragmentation-needed",
     nexthopmtu=1300)/data
-# sr1 cannot be used, TCP data will not match outgoing ICMP packet
-if os.fork() == 0:
-       time.sleep(1)
-       send(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR)/icmp, iface=LOCAL_IF)
-       os._exit(0)
+send(IP(src=LOCAL_ADDR, dst=REMOTE_ADDR)/icmp, iface=LOCAL_IF)
 
 print "Path MTU discovery will resend first data with length 1300."
-ans=sniff(iface=LOCAL_IF, timeout=3, count=1, filter=
-    "ip and src %s and tcp port %u and dst %s and tcp port %u" %
-    (ip.dst, syn.dport, ip.src, syn.sport))
+sniffer.join(timeout=5)
+ans = sniffer.packet
 
 if len(ans) == 0:
        print "ERROR: no data retransmit from chargen server received"
index f56ec44..c78ad4c 100755 (executable)
@@ -1,9 +1,24 @@
 #!/usr/local/bin/python2.7
 
 import os
+import threading
 from addr import *
 from scapy.all import *
 
+class Sniff1(threading.Thread):
+       filter = None
+       captured = None
+       packet = None
+       def __init__(self):
+               # clear packets buffered by scapy bpf
+               sniff(iface=LOCAL_IF, timeout=1)
+               super(Sniff1, self).__init__()
+       def run(self):
+               self.captured = sniff(iface=LOCAL_IF, filter=self.filter,
+                   count=1, timeout=3)
+               if self.captured:
+                       self.packet = self.captured[0]
+
 e=Ether(src=LOCAL_MAC, dst=REMOTE_MAC)
 ip6=IPv6(src=FAKE_NET_ADDR6, dst=REMOTE_ADDR6)
 tport=os.getpid() & 0xffff
@@ -28,18 +43,21 @@ if data is None:
 print "Fill our receive buffer."
 time.sleep(1)
 
+# srp1 cannot be used, TCP data will not match outgoing ICMP6 packet
+sniffer = Sniff1()
+sniffer.filter = \
+    "ip6 and src %s and tcp port %u and dst %s and tcp port %u" % \
+    (ip6.dst, syn.dport, ip6.src, syn.sport)
+sniffer.start()
+time.sleep(1)
+
 print "Send ICMP6 packet too big packet with MTU 1300."
 icmp6=ICMPv6PacketTooBig(mtu=1300)/data.payload
-# srp1 cannot be used, TCP data will not match outgoing ICMP6 packet
-if os.fork() == 0:
-       time.sleep(1)
-       sendp(e/IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/icmp6, iface=LOCAL_IF)
-       os._exit(0)
+sendp(e/IPv6(src=LOCAL_ADDR6, dst=REMOTE_ADDR6)/icmp6, iface=LOCAL_IF)
 
 print "Path MTU discovery will resend first data with length 1300."
-ans=sniff(iface=LOCAL_IF, timeout=3, count=1, filter=
-    "ip6 and src %s and tcp port %u and dst %s and tcp port %u" %
-    (ip6.dst, syn.dport, ip6.src, syn.sport))
+sniffer.join(timeout=5)
+ans = sniffer.packet
 
 if len(ans) == 0:
        print "ERROR: no data retransmit from chargen server received"
index 09525f0..d74cfbb 100755 (executable)
@@ -1,11 +1,26 @@
 #!/usr/local/bin/python2.7
 
 import os
+import threading
 import string
 import random
 from addr import *
 from scapy.all import *
 
+class Sniff(threading.Thread):
+        filter = None
+        captured = None
+        packet = None
+        def __init__(self):
+                # clear packets buffered by scapy bpf
+                sniff(iface=LOCAL_IF, timeout=1)
+                super(Sniff, self).__init__()
+        def run(self):
+                self.captured = sniff(iface=LOCAL_IF, filter=self.filter,
+                    timeout=3)
+                if self.captured:
+                        self.packet = self.captured[0]
+
 e=Ether(src=LOCAL_MAC, dst=REMOTE_MAC)
 ip6=IPv6(src=FAKE_NET_ADDR6, dst=REMOTE_ADDR6)
 uport=os.getpid() & 0xffff
@@ -30,19 +45,22 @@ 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 not send UDP atomic fragment."
 # 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)
+sniffer = Sniff()
+sniffer.filter = \
+    "ip6 and src "+ip6.dst+" and dst "+ip6.src+" and proto ipv6-frag"
+sniffer.start()
+time.sleep(1)
 
-ans=sniff(iface=LOCAL_IF, timeout=3, filter=
-    "ip6 and src "+ip6.dst+" and dst "+ip6.src+" and proto ipv6-frag")
+print "Send UDP packet with 1200 octets payload."
+sendp(e/ip6/udp, iface=LOCAL_IF)
+
+print "Path MTU discovery will not send UDP atomic fragment."
+sniffer.join(timeout=5)
 
 print "IPv6 atomic fragments must not be generated."
 frag=None
-for a in ans:
+for a in sniffer.captured:
        fh=a.payload.payload
        if fh.offset != 0 or fh.nh != (ip6/udp).nh:
                continue
index 77a7463..f1a4e11 100755 (executable)
@@ -1,11 +1,26 @@
 #!/usr/local/bin/python2.7
 
 import os
+import threading
 import string
 import random
 from addr import *
 from scapy.all import *
 
+class Sniff(threading.Thread):
+       filter = None
+       captured = None
+       packet = None
+       def __init__(self):
+               # clear packets buffered by scapy bpf
+               sniff(iface=LOCAL_IF, timeout=1)
+               super(Sniff, self).__init__()
+       def run(self):
+               self.captured = sniff(iface=LOCAL_IF, filter=self.filter,
+                   timeout=3)
+               if self.captured:
+                       self.packet = self.captured[0]
+
 e=Ether(src=LOCAL_MAC, dst=REMOTE_MAC)
 ip6=IPv6(src=FAKE_NET_ADDR6, dst=REMOTE_ADDR6)
 uport=os.getpid() & 0xffff
@@ -30,17 +45,20 @@ 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 fragment with maximum length 1300."
 # 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)
+sniffer = Sniff()
+sniffer.filter = \
+    "ip6 and src "+ip6.dst+" and dst "+ip6.src+" and proto ipv6-frag"
+sniffer.start()
+time.sleep(1)
 
-ans=sniff(iface=LOCAL_IF, timeout=3, filter=
-    "ip6 and src "+ip6.dst+" and dst "+ip6.src+" and proto ipv6-frag")
+print "Send UDP packet with 1400 octets payload."
+sendp(e/ip6/udp, iface=LOCAL_IF)
+
+print "Path MTU discovery will send UDP fragment with maximum length 1300."
+sniffer.join(timeout=5)
 
-for a in ans:
+for a in sniffer.captured:
        fh=a.payload.payload
        if fh.offset != 0 or fh.nh != (ip6/udp).nh:
                continue