Pārlūkot izejas kodu

split pcap-comparator from testcase and enabled random id2t-parameters for the testcase

Denis Waßmann 6 gadi atpakaļ
vecāks
revīzija
a91458020a
2 mainītis faili ar 120 papildinājumiem un 34 dzēšanām
  1. 64 0
      test/TestUtil.py
  2. 56 34
      test/test_pcap_comparator.py

+ 64 - 0
test/TestUtil.py

@@ -0,0 +1,64 @@
+#!/usr/bin/python3
+
+import scapy.all
+import scapy.packet
+
+
+# You could compare pcaps by byte or by hash too, but this class tells you
+# where exactly pcaps differ
+class PcapComparator:
+    def compare_files(self, file: str, other_file: str):
+        self.compare_captures(scapy.all.rdpcap(file), scapy.all.rdpcap(other_file))
+
+    def compare_captures(self, packetsA, packetsB):
+        if len(packetsA) != len(packetsB):
+            self.fail("Both pcap's have to have the same amount of packets")
+
+        for i in range(len(packetsA)):
+            p, p2 = packetsA[i], packetsB[i]
+
+            if abs(p.time - p2.time) > (10 ** -7):
+                self.fail("Packets no %i in the pcap's don't appear at the same time" % (i + 1))
+            self.compare_packets(p, p2, i + 1)
+
+    def compare_packets(self, p: scapy.packet.BasePacket, p2: scapy.packet.BasePacket, packet_number: int):
+        if p == p2:
+            return
+
+        while type(p) != scapy.packet.NoPayload or type(p2) != scapy.packet.NoPayload:
+            if type(p) != type(p2):
+                self.fail("Packets %i are of incompatible types: %s and %s" % (packet_number, type(p).__name__, type(p2).__name__))
+
+            for field in p.fields:
+                if p.fields[field] != p2.fields[field]:
+                    packet_type = type(p).__name__
+                    v, v2 = p.fields[field], p2.fields[field]
+
+                    self.fail("Packets %i differ in field %s.%s: %s != %s" %
+                                (packet_number, packet_type, field, v, v2))
+
+            p = p.payload
+            p2 = p2.payload
+
+    def fail(self, message: str):
+        raise AssertionError(message)
+
+
+if __name__ == "__main__":
+    import sys
+
+    if len(sys.argv) < 3:
+        print("Usage: %s one.pcap other.pcap" % sys.argv[0])
+        exit(0)
+
+    try:
+        PcapComparator().compare_files(sys.argv[1], sys.argv[2])
+        print("The given pcaps are equal")
+    except AssertionError as e:
+        print("The given pcaps are not equal")
+        print("Error message:", *e.args)
+        exit(1)
+    except Exception as e:
+        print("During the comparison an unexpected error happened")
+        print(type(e).__name__ + ":", *e.args)
+        exit(1)

+ 56 - 34
test/test_pcap_comparator.py

@@ -4,13 +4,42 @@ import sys, os
 import subprocess, shlex
 import time
 import unittest
+import random
 
 import scapy.all
+from TestUtil import PcapComparator
+
+# this dictionary holds the generators (functions) for the parameters
+# that will be passed to the MembershipMgmtCommAttack
+# items need the parameter-name as key and a function that will be called
+# without parameters and returns a valid value for that parameter as value
+# WARNING: parameters will be passed via command line, make sure your values
+# get converted to string correctly
+_random_bool = lambda: random.random() < 0.5
+ID2T_PARAMETER_GENERATORS = {
+    "bots.count": lambda: random.randint(3, 6),
+#    "file.csv":,
+#    "file.xml":,
+    "hidden_mark": _random_bool,
+#    "interval.selection.end":,
+#    "interval.selection.start":,
+#    "interval.selection.strategy":,
+#    "ip.reuse.external":,
+#    "ip.reuse.local":,
+#    "ip.reuse.total":,
+    "multiport": _random_bool,
+    "nat.present": _random_bool,
+    "packet.padding": lambda: random.randint(0, 100),
+    "packets.limit": lambda: random.randint(50, 150),
+    "packets.per-second": lambda: random.randint(1000, 2000) / 100,
+    "ttl.from.caida": _random_bool,
+}
 
 class PcapComparison(unittest.TestCase):
     ID2T_PATH = ".."
     ID2T_LOCATION = ID2T_PATH + "/" + "id2t"
-    NUM_ITERATIONS = 3
+    NUM_ITERATIONS_PER_PARAMS = 3
+    NUM_ITERATIONS = 5
 
     PCAP_ENVIRONMENT_VALUE = "ID2T_SRC_PCAP"
     SEED_ENVIRONMENT_VALUE = "ID2T_SEED"
@@ -51,7 +80,7 @@ class PcapComparison(unittest.TestCase):
         self.print_warning("The command that gets executed is:", command)
 
         generated_pcap = None
-        for i in range(self.NUM_ITERATIONS):
+        for i in range(self.NUM_ITERATIONS_PER_PARAMS):
             retcode, output = subprocess.getstatusoutput(command)
 
             self.print_warning(output)
@@ -96,44 +125,37 @@ class PcapComparison(unittest.TestCase):
         return next(file for file in files if file.endswith(".pcap"))
 
     def compare_pcaps(self, one: str, other: str):
-        packetsA = list(scapy.all.rdpcap(self.ID2T_PATH + "/" + one))
-        packetsB = list(scapy.all.rdpcap(self.ID2T_PATH + "/" + other))
-
-        self.assertEqual(len(packetsA), len(packetsB), "Both pcap's have to have the same amount of packets")
-        for i in range(len(packetsA)):
-            p, p2 = packetsA[i], packetsB[i]
-
-            self.assertAlmostEqual(p.time, p2.time, "Packets no %i in the pcap's don't appear at the same time" % (i + 1))
-            self.compare_packets(p, p2, i + 1)
-
-    def compare_packets(self, p, p2, packet_number):
-        if p == p2:
-            return
-
-        while type(p) != scapy.packet.NoPayload or type(p2) != scapy.packet.NoPayload:
-            if type(p) != type(p2):
-                self.fail("Packets %i are of incompatible types: %s and %s" % (packet_number, type(p).__name__, type(p2).__name__))
-
-            for field in p.fields:
-                if p.fields[field] != p2.fields[field]:
-                    packet_type = type(p).__name__
-                    v, v2 = p.fields[field], p2.fields[field]
-
-                    self.fail("Packets %i differ in field %s.%s: %s != %s" %
-                                (packet_number, packet_type, field, v, v2))
-
-            p = p.payload
-            p2 = p2.payload
+        PcapComparator().compare_files(self.ID2T_PATH + "/" + one, self.ID2T_PATH + "/" + other)
 
     def print_warning(self, *text):
         print(*text, file=sys.stderr)
 
     def random_id2t_params(self):
-        param = lambda key, val: "-p%s=%s" % (str(key), str(val))
+        """
+        :return: A list of parameter-lists for id2t, useful if you want several
+        iterations
+        """
+        param_list = []
+        for i in range(self.NUM_ITERATIONS):
+            param_list.append(self.random_id2t_param_set())
+        return param_list
+
+    def random_id2t_param_set(self):
+        """
+        Create a list of parameters to call the membersmgmtcommattack with
+        :return: a list of command-line parameters
+        """
+        param = lambda key, val: "%s=%s" % (str(key), str(val))
+
+        number_of_keys = min(random.randint(2, 5), len(ID2T_PARAMETER_GENERATORS))
+        keys = random.sample(list(ID2T_PARAMETER_GENERATORS), number_of_keys)
+
+        params = []
+        for key in keys:
+            generator = ID2T_PARAMETER_GENERATORS[key]
+            params.append(param(key, generator()))
 
-        return [
-            []
-        ]
+        return params
 
 if __name__ == "__main__":
     import sys