Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 42 additions & 3 deletions scapy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.startswith("DLT") and v == value
)


def _guess_linktype_value(name):
"""Guess the value of a DLT name."""
import scapy.data
if not name.startswith("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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.startswith("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 = []
Expand Down
9 changes: 4 additions & 5 deletions test/regression.uts
Original file line number Diff line number Diff line change
Expand Up @@ -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()))
Expand All @@ -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()))
Expand Down