traffic-taffy 0.8__py3-none-any.whl → 0.8.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
traffic_taffy/__init__.py CHANGED
@@ -1 +1 @@
1
- __VERSION__ = "0.8"
1
+ __VERSION__ = "0.8.5"
traffic_taffy/compare.py CHANGED
@@ -3,8 +3,9 @@
3
3
  from __future__ import annotations
4
4
  from logging import debug, error
5
5
  from typing import List, TYPE_CHECKING
6
- import datetime as dt
7
6
  from datetime import datetime
7
+ import datetime as dt
8
+ import itertools
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from argparse import ArgumentParser, Namespace
@@ -102,9 +103,22 @@ class PcapCompare:
102
103
  def compare_all(self, dissections: List[Dissection]) -> List[Comparison]:
103
104
  """Compare all loaded pcaps."""
104
105
  reports = []
105
- if isinstance(dissections, list) and len(dissections) > 1:
106
+
107
+ # hack to figure out if there is at least two instances of a generator
108
+ # without actually extracting them all
109
+ # (since it could be memory expensive)
110
+ reference = next(dissections)
111
+ other = None
112
+ multiple = True
113
+ try:
114
+ other = next(dissections)
115
+ dissections = itertools.chain([other], dissections)
116
+ except Exception as e:
117
+ print(e)
118
+ multiple = False
119
+
120
+ if multiple:
106
121
  # multiple file comparison
107
- reference = next(dissections)
108
122
  for other in dissections:
109
123
  # compare the two global summaries
110
124
 
@@ -116,7 +130,7 @@ class PcapCompare:
116
130
  reports.append(report)
117
131
  else:
118
132
  # deal with timestamps within a single file
119
- reference = list(dissections)[0].data
133
+ reference = reference.data
120
134
  timestamps = list(reference.keys())
121
135
  if len(timestamps) <= 2: # just 0-summary plus a single stamp
122
136
  error(
@@ -11,6 +11,23 @@ from typing import List
11
11
  from copy import deepcopy
12
12
  from pathlib import Path
13
13
  from traffic_taffy import __VERSION__ as VERSION
14
+ from io import BytesIO
15
+ import pkgutil
16
+
17
+ # TODO(hardaker): fix to not use a global
18
+ # note that this is designed to load only once before forking
19
+ iana_data = None
20
+ if not iana_data:
21
+ # try a local copy first
22
+ if Path("traffic_taffy/iana/tables.msgpakx").exists():
23
+ iana_data = msgpack.load(Path.open("traffic_taffy/iana/tables.msgpak", "rb"))
24
+ else:
25
+ content = pkgutil.get_data("traffic_taffy", "iana/tables.msgpak")
26
+ if content:
27
+ content = BytesIO(content)
28
+ iana_data = msgpack.load(content)
29
+ else:
30
+ warning("failed to load IANA data tables -- no enum expansion available")
14
31
 
15
32
 
16
33
  class PCAPDissectorLevel(Enum):
@@ -57,6 +74,7 @@ class Dissection:
57
74
  self.maximum_count = maximum_count
58
75
  self.pcap_filter = pcap_filter
59
76
  self.ignore_list = ignore_list or []
77
+ self.iana_data = defaultdict(dict)
60
78
 
61
79
  self.parameters = [
62
80
  "pcap_file",
@@ -421,6 +439,8 @@ class Dissection:
421
439
  )
422
440
  else:
423
441
  value = "0x" + value.hex()
442
+ elif value_type in Dissection.ENUM_TRANSLATORS:
443
+ value = str(Dissection.ENUM_TRANSLATORS[value_type](value_type, value))
424
444
  else:
425
445
  value = str(value)
426
446
  except Exception:
@@ -448,6 +468,79 @@ class Dissection:
448
468
  """Convert binary bytes to IP addresses (v4 and v6)."""
449
469
  return ipaddress.ip_address(value)
450
470
 
471
+ UDP_PORTS: ClassVar[Dict[str, str]] = {
472
+ "53": "DNS",
473
+ }
474
+
475
+ IANA_TRANSLATORS: ClassVar[Dict[str, str]] = {
476
+ "Ethernet_IP_proto": "protocols",
477
+ "Ethernet_IPv6_proto": "protocols",
478
+ "Ethernet_IP_UDP_sport": "udp_ports",
479
+ "Ethernet_IP_UDP_dport": "udp_ports",
480
+ "Ethernet_IP_TCP_sport": "tcp_ports",
481
+ "Ethernet_IP_TCP_dport": "tcp_ports",
482
+ "Ethernet_IPv6_UDP_sport": "udp_ports",
483
+ "Ethernet_IPv6_UDP_dport": "udp_ports",
484
+ "Ethernet_IPv6_TCP_sport": "tcp_ports",
485
+ "Ethernet_IPv6_TCP_dport": "tcp_ports",
486
+ "Ethernet_IP_ICMP_code": "icmp_codes",
487
+ "Ethernet_IP_ICMP_type": "icmp_types",
488
+ "Ethernet_IP_ICMP_IP in ICMP_UDP in ICMP_dport": "udp_ports",
489
+ "Ethernet_IP_ICMP_IP in ICMP_UDP in ICMP_sport": "udp_ports",
490
+ "Ethernet_IP_ICMP_IP in ICMP_TCP in ICMP_dport": "tcp_ports",
491
+ "Ethernet_IP_ICMP_IP in ICMP_TCP in ICMP_sport": "tcp_ports",
492
+ "Ethernet_IP_ICMP_IP in ICMP_protoc": "protocols",
493
+ "Ethernet_IP_UDP_DNS_qd_qclass": "dns_classes",
494
+ "Ethernet_IP_UDP_DNS_ns_rclass": "dns_classes",
495
+ "Ethernet_IP_UDP_DNS_an_rclass": "dns_classes",
496
+ "Ethernet_IP_UDP_DNS_qd_qtype": "dns_rrtypes",
497
+ "Ethernet_IP_UDP_DNS_ns_type": "dns_rrtypes",
498
+ "Ethernet_IP_UDP_DNS_an_type": "dns_rrtypes",
499
+ "Ethernet_IP_UDP_DNS_opcode": "dns_opcodes",
500
+ }
501
+
502
+ @staticmethod
503
+ def print_iana_values(value_type: str, value: bytes) -> str:
504
+ """Use IANA lookup tables for converting protocol enumerations to human readable types."""
505
+ table_name = Dissection.IANA_TRANSLATORS.get(value_type)
506
+
507
+ if not table_name:
508
+ return value
509
+
510
+ table = iana_data[table_name]
511
+ value = str(value)
512
+ if value not in table:
513
+ return value
514
+
515
+ return f"{value} ({table[value]})"
516
+
517
+ ENUM_TRANSLATORS: ClassVar[Dict[str, callable]] = {
518
+ "Ethernet_IP_proto": print_iana_values,
519
+ "Ethernet_IPv6_proto": print_iana_values,
520
+ "Ethernet_IP_UDP_sport": print_iana_values,
521
+ "Ethernet_IP_UDP_dport": print_iana_values,
522
+ "Ethernet_IP_TCP_sport": print_iana_values,
523
+ "Ethernet_IP_TCP_dport": print_iana_values,
524
+ "Ethernet_IP_ICMP_IP in ICMP_UDP in ICMP_dport": print_iana_values,
525
+ "Ethernet_IP_ICMP_IP in ICMP_UDP in ICMP_sport": print_iana_values,
526
+ "Ethernet_IP_ICMP_IP in ICMP_TCP in ICMP_dport": print_iana_values,
527
+ "Ethernet_IP_ICMP_IP in ICMP_TCP in ICMP_sport": print_iana_values,
528
+ "Ethernet_IP_ICMP_IP in ICMP_proto": print_iana_values,
529
+ "Ethernet_IPv6_UDP_sport": print_iana_values,
530
+ "Ethernet_IPv6_UDP_dport": print_iana_values,
531
+ "Ethernet_IPv6_TCP_sport": print_iana_values,
532
+ "Ethernet_IPv6_TCP_dport": print_iana_values,
533
+ "Ethernet_IP_ICMP_code": print_iana_values,
534
+ "Ethernet_IP_ICMP_type": print_iana_values,
535
+ "Ethernet_IP_UDP_DNS_qd_qclass": print_iana_values,
536
+ "Ethernet_IP_UDP_DNS_ns_rclass": print_iana_values,
537
+ "Ethernet_IP_UDP_DNS_an_rclass": print_iana_values,
538
+ "Ethernet_IP_UDP_DNS_qd_qtype": print_iana_values,
539
+ "Ethernet_IP_UDP_DNS_ns_type": print_iana_values,
540
+ "Ethernet_IP_UDP_DNS_an_type": print_iana_values,
541
+ "Ethernet_IP_UDP_DNS_opcode": print_iana_values,
542
+ }
543
+
451
544
  # has to go at the end to pick up the above function names
452
545
  DISPLAY_TRANSFORMERS: ClassVar[Dict[str, callable]] = {
453
546
  "Ethernet_IP_src": print_ip_address,
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: traffic-taffy
3
- Version: 0.8
3
+ Version: 0.8.5
4
4
  Summary: A tool for doing differential analysis of pcap files
5
5
  Project-URL: Homepage, https://traffic-taffy.github.io/
6
6
  Author-email: Wes Hardaker <opensource@hardakers.net>
@@ -1,7 +1,7 @@
1
- traffic_taffy/__init__.py,sha256=rSli_H1CNuvL_e1rmtF9vux7IpylSjpepysxJbNv5gg,20
2
- traffic_taffy/compare.py,sha256=MBmNLRdALgPiabwRg1NGnf6Gfb0vKpJc3jhMe2wsgZs,8269
1
+ traffic_taffy/__init__.py,sha256=n9FymgbxpXu3w9gvFFmFbdtHDu-QOLvIWAMihAIPlcs,22
2
+ traffic_taffy/compare.py,sha256=4T25Ygp6rQw7J3syn4Tam6tEw3ieSzl-lELPARvNnVw,8641
3
3
  traffic_taffy/comparison.py,sha256=MmCxK7E3RbVLS8gJ_JJOdqa2MHQ7np1Pq_VB0Scir8U,933
4
- traffic_taffy/dissection.py,sha256=-jXt4PYCi_lvPh86KC_84VywRZqhZ1cGgLdV2glCQC8,17390
4
+ traffic_taffy/dissection.py,sha256=6Ex0zkUCvl-nMNg44CYkSL7JFqi6O7_T690bFzTj0A8,21567
5
5
  traffic_taffy/dissectmany.py,sha256=kJO2XF8QzOmLDsKDjZIkQBmxC97wFpi-IisCURLOmfU,4700
6
6
  traffic_taffy/dissector.py,sha256=JHewf3vhvYjE6CGuRzO6_SnR5QuHZjzx-hZjpkAPHl4,11685
7
7
  traffic_taffy/graph.py,sha256=lH20RjnY3rMU8g2zyOkpS5pfvgCcYa4GCtO22uArzs8,4510
@@ -16,13 +16,13 @@ traffic_taffy/dissector_engine/scapy.py,sha256=5lE6y4wzULfULTFcTAo6qINazqoBVwzbR
16
16
  traffic_taffy/hooks/__init__.py,sha256=Bvhl6RnyBqQkWuCU6TS0O_ZHe4qCQsC4HE8FELigWPw,661
17
17
  traffic_taffy/hooks/ip2asn.py,sha256=8KyqwKTY3YK9GZEDW_3PM_6zuvrzkDAzIceIodNAepY,1765
18
18
  traffic_taffy/hooks/psl.py,sha256=6Xmbl2OigDIe17ChumU35iuE0B6Q7ttBp2iBruxWFg4,1529
19
+ traffic_taffy/iana/tables.msgpak,sha256=d-R5Xw9yG9t4RqGJRrpE6cjH4YfaxQBwQiBhNjKZbwI,172825
19
20
  traffic_taffy/output/__init__.py,sha256=dSpW9xDno3nKaYOwThS2fVkcIHJVAJE9DlEiLfdHXfg,4555
20
21
  traffic_taffy/output/console.py,sha256=Ziq4MKtzSdP9oVaZrWHiw0Bpsm2Dj9QFLJtDK38mxaY,2911
21
22
  traffic_taffy/output/fsdb.py,sha256=po--ldHeRPTXVTkP68qtI_BYV2cEOab-kFVWv0ymj5M,1704
22
23
  traffic_taffy/output/memory.py,sha256=86tgJ-jMt3UVX31eP6U02YbbYRoqbYhhR4kXJQmYzO4,1870
23
24
  traffic_taffy/tests/test_compare_results.py,sha256=LRAAsel2vwSLZmSGxzdGurga77dhBsLkTCMRjybb10A,1921
24
25
  traffic_taffy/tests/test_dict_merge.py,sha256=t3rZSQQ0AlBxRKfLborx9SxYN53cCAQQzZ2w-__WT2Y,1429
25
- traffic_taffy/tests/test_dpkt_engine.py,sha256=512Wfq7D1qVkfhGwf1u2QSgZooWqZQWV9L4OhpAr4AE,489
26
26
  traffic_taffy/tests/test_hooks.py,sha256=amjEbtMwOZZCg_RCJ0wQR7aOqNfwz3IG3WY-9CwjSF4,1260
27
27
  traffic_taffy/tests/test_normalize.py,sha256=k5y3XmYitnF1aTkB-9dZ7WZPQB__l_iEzC6atKKywfw,2601
28
28
  traffic_taffy/tests/test_pcap_dissector.py,sha256=sxJJ3seO9pjzilM0b6iu_ggQbUI4E7WbMFdwm4m9Gz0,2027
@@ -36,8 +36,8 @@ traffic_taffy/tools/dissect.py,sha256=Z_5JJ92E4168_GZM_9Iu-m6lDfETBt8Gv-vD_Mu3Cf
36
36
  traffic_taffy/tools/explore.py,sha256=Hb4x9HZkFoYnR8BJKF5OLwZWKGR3RX3MdZhX4Oo-NDU,24180
37
37
  traffic_taffy/tools/export.py,sha256=BuAnZcOszj9ZpMxHmRjDqptR15dMRigOhp2-BFJHgWA,2707
38
38
  traffic_taffy/tools/graph.py,sha256=gARv5-7N5MUBSJJ8Uj5XLx4xEonXgIMADKwN573jxyk,2555
39
- traffic_taffy-0.8.dist-info/METADATA,sha256=Ipy4XE9_pCJwre7SPOvA8Q1yCJtMTT0PAsDeKuLmlhU,1931
40
- traffic_taffy-0.8.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
41
- traffic_taffy-0.8.dist-info/entry_points.txt,sha256=ySz30b1Cu03CtCGMRqqg0NZJpzrVI91T5HjbEaTNnpQ,314
42
- traffic_taffy-0.8.dist-info/licenses/LICENSE.txt,sha256=hiV1DJgDQeSM1r7P-ez5oxily11S5nsCedU0jKzKKzo,11338
43
- traffic_taffy-0.8.dist-info/RECORD,,
39
+ traffic_taffy-0.8.5.dist-info/METADATA,sha256=h_i-wO4muRSfeswpfjQddlpyinLnYJfYc2wLGnr_SN4,1933
40
+ traffic_taffy-0.8.5.dist-info/WHEEL,sha256=TJPnKdtrSue7xZ_AVGkp9YXcvDrobsjBds1du3Nx6dc,87
41
+ traffic_taffy-0.8.5.dist-info/entry_points.txt,sha256=ySz30b1Cu03CtCGMRqqg0NZJpzrVI91T5HjbEaTNnpQ,314
42
+ traffic_taffy-0.8.5.dist-info/licenses/LICENSE.txt,sha256=hiV1DJgDQeSM1r7P-ez5oxily11S5nsCedU0jKzKKzo,11338
43
+ traffic_taffy-0.8.5.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- import os
2
- from traffic_taffy.dissection import PCAPDissectorLevel
3
- from traffic_taffy.dissector_engine.dpkt import DissectionEngineDpkt
4
-
5
- def test_dpkt_engine():
6
- test_pcap = "dns.pcap"
7
- test_pcap = "port53-2023-30-31_20.pcap"
8
- test_pcap = "airplane-wireless.pcap"
9
- if not os.path.exists(test_pcap):
10
- return
11
-
12
- engine = DissectionEngineDpkt(test_pcap,
13
- dissector_level = PCAPDissectorLevel.COMMON_LAYERS)
14
- dissection = engine.load()
15
-