From a3ec146e411ff3a0d38438f232e04fe02d1bc1fc Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Mon, 29 Apr 2019 16:33:33 +0200 Subject: [PATCH 1/2] Workaround tcpdump lack of -y support --- scapy/utils.py | 45 ++++++++++++++++++++++++++++++++++++++++++--- test/regression.uts | 9 ++++----- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/scapy/utils.py b/scapy/utils.py index 058c1f162ba..2c2ca5158a8 100644 --- a/scapy/utils.py +++ b/scapy/utils.py @@ -1468,6 +1468,23 @@ def tdecode(pktlist, args=None, **kwargs): return tcpdump(pktlist, prog=conf.prog.tshark, args=args, **kwargs) +def _guess_linktype_name(value): + """Guess the DLT name from its value.""" + import scapy.data + return next( + k[4:] for k, v in six.iteritems(scapy.data.__dict__) + if k[:3] == "DLT" and v == value + ) + + +def _guess_linktype_value(name): + """Guess the value of a DLT name.""" + import scapy.data + if name[:4] != "DLT_": + name = "DLT_" + name + return scapy.data.__dict__[name] + + @conf.commands.register def tcpdump(pktlist, dump=False, getfd=False, args=None, prog=None, getproc=False, quiet=False, use_tempfile=None, @@ -1511,9 +1528,7 @@ def tcpdump(pktlist, dump=False, getfd=False, args=None, ``tcpdump`` on OSX. read_stdin_opts: When set, a list of arguments needed to capture from stdin. Otherwise, attempts to guess. -linktype: If a Packet (or list) is passed in the ``pktlist`` argument, - set the ``linktype`` parameter on ``wrpcap``. If ``pktlist`` is a - path to a pcap file, then this option will have no effect. +linktype: A custom DLT value or name, to overwrite the default values. wait: If True (default), waits for the process to terminate before returning to Scapy. If False, the process will be detached to the background. If dump, getproc or getfd is True, these have the same effect as @@ -1562,6 +1577,30 @@ def tcpdump(pktlist, dump=False, getfd=False, args=None, else: raise ValueError("prog must be a string") + if linktype is not None: + # Tcpdump does not support integers in -y (yet) + # https://github.com/the-tcpdump-group/tcpdump/issues/758 + if isinstance(linktype, int): + # Guess name from value + try: + linktype_name = _guess_linktype_name(linktype) + except StopIteration: + linktype = -1 + else: + # Guess value from name + if linktype[:4] == "DLT_": + linktype = linktype[4:] + linktype_name = linktype + try: + linktype = _guess_linktype_value(linktype) + except KeyError: + linktype = -1 + if linktype == -1: + raise ValueError( + "Unknown linktype. Try passing its datalink name instead" + ) + prog += ["-y", linktype_name] + # Build Popen arguments if args is None: args = [] diff --git a/test/regression.uts b/test/regression.uts index 541842c08f3..2c82763381b 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -6798,10 +6798,10 @@ with mock.patch('subprocess.Popen', return_value=Bunch( stdin=f, wait=lambda: None)) as popen: # Prevent closing the BytesIO with mock.patch.object(f, 'close'): - tcpdump([pkt], linktype=scapy.data.DLT_EN3MB, use_tempfile=False) + tcpdump([pkt], linktype="DLT_EN3MB", use_tempfile=False) popen.assert_called_once_with( - [conf.prog.tcpdump, '-r', '-'], + [conf.prog.tcpdump, '-y', 'EN3MB', '-r', '-'], stdin=subprocess.PIPE, stdout=None, stderr=None) print(bytes_hex(f.getvalue())) @@ -6818,11 +6818,10 @@ with mock.patch('subprocess.Popen', return_value=Bunch( stdin=f, wait=lambda: None)) as popen: # Prevent closing the BytesIO with mock.patch.object(f, 'close'): - tcpdump([pkt], linktype=scapy.data.DLT_EN3MB, use_tempfile=False, - args=['-y', 'DLT_EN10MB']) + tcpdump([pkt], linktype=scapy.data.DLT_EN10MB, use_tempfile=False) popen.assert_called_once_with( - [conf.prog.tcpdump, '-r', '-', '-y', 'DLT_EN10MB'], + [conf.prog.tcpdump, '-y', 'EN10MB', '-r', '-'], stdin=subprocess.PIPE, stdout=None, stderr=None) print(bytes_hex(f.getvalue())) From 2b2617c9028bd708596677ce6bbd34b6b29d4082 Mon Sep 17 00:00:00 2001 From: guedou Date: Sat, 11 May 2019 21:45:06 +0200 Subject: [PATCH 2/2] Small formatting fixes --- scapy/utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scapy/utils.py b/scapy/utils.py index 2c2ca5158a8..12ac0c9d142 100644 --- a/scapy/utils.py +++ b/scapy/utils.py @@ -1473,14 +1473,14 @@ def _guess_linktype_name(value): import scapy.data return next( k[4:] for k, v in six.iteritems(scapy.data.__dict__) - if k[:3] == "DLT" and v == value + if k.startswith("DLT") and v == value ) def _guess_linktype_value(name): """Guess the value of a DLT name.""" import scapy.data - if name[:4] != "DLT_": + if not name.startswith("DLT_"): name = "DLT_" + name return scapy.data.__dict__[name] @@ -1588,7 +1588,7 @@ def tcpdump(pktlist, dump=False, getfd=False, args=None, linktype = -1 else: # Guess value from name - if linktype[:4] == "DLT_": + if linktype.startswith("DLT_"): linktype = linktype[4:] linktype_name = linktype try: