From 339dfb39b159ef8f96f29c2344866004d972c9a0 Mon Sep 17 00:00:00 2001
From: Pierre LALET <pierre.lalet@cea.fr>
Date: Fri, 6 Jan 2017 13:43:28 +0100
Subject: [PATCH] Add a tcpdump-based L2listen socket

This also includes some fixes for tcpdump()
---
 scapy/supersocket.py | 26 ++++++++++++++++++++++++++
 scapy/utils.py       | 27 ++++++++++++++++++---------
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/scapy/supersocket.py b/scapy/supersocket.py
index fe80d507..2a2c1107 100644
--- a/scapy/supersocket.py
+++ b/scapy/supersocket.py
@@ -13,6 +13,7 @@ from scapy.config import conf
 from scapy.data import *
 from scapy.error import warning, log_runtime
 import scapy.packet
+from scapy.utils import PcapReader, tcpdump
 
 class _SuperSocket_metaclass(type):
     def __repr__(self):
@@ -174,5 +175,30 @@ class SSLStreamSocket(StreamSocket):
         self._buf = self._buf[x:]
         return pkt
 
+
+class L2ListenTcpdump(SuperSocket):
+    desc = "read packets at layer 2 using tcpdump"
+
+    def __init__(self, iface=None, promisc=None, filter=None, nofilter=False,
+                 prog=None, *arg, **karg):
+        self.outs = None
+        args = ['-w', '-', '-s', '65535']
+        if iface is not None:
+            args.extend(['-i', iface])
+        if not promisc:
+            args.append('-p')
+        if not nofilter:
+            if conf.except_filter:
+                if filter:
+                    filter = "(%s) and not (%s)" % (filter, conf.except_filter)
+                else:
+                    filter = "not (%s)" % conf.except_filter
+        if filter is not None:
+            args.append(filter)
+        self.ins = PcapReader(tcpdump(None, prog=prog, args=args, getfd=True))
+    def recv(self, x=MTU):
+        return self.ins.recv(x)
+
+
 if conf.L3socket is None:
     conf.L3socket = L3RawSocket
diff --git a/scapy/utils.py b/scapy/utils.py
index 1215c69b..74fc4c10 100644
--- a/scapy/utils.py
+++ b/scapy/utils.py
@@ -804,7 +804,10 @@ class RawPcapNgReader(RawPcapReader):
             self.endian = "<"
         else:
             raise Scapy_Exception("Not a pcapng capture file (bad magic)")
-        self.f.seek(0)
+        try:
+            self.f.seek(0)
+        except:
+            pass
 
     def read_packet(self, size=MTU):
         """Read blocks until it reaches either EOF or a packet, and
@@ -1139,11 +1142,19 @@ To get a JSON representation of a tshark-parsed PacketList(), one can:
 u'64'
 
     """
-    if isinstance(pktlist, basestring):
+    if prog is None:
+        prog = [conf.prog.tcpdump]
+    elif isinstance(prog, basestring):
+        prog = [prog]
+    if pktlist is None:
         proc = subprocess.Popen(
-            [conf.prog.tcpdump if prog is None else prog, "-r", pktlist]
-            + (["-n"] if args is None else args),
-            stdin=subprocess.PIPE,
+            prog + (args if args is not None else []),
+            stdout=subprocess.PIPE if dump or getfd else None,
+            stderr=open(os.devnull),
+        )
+    elif isinstance(pktlist, basestring):
+        proc = subprocess.Popen(
+            prog + ["-r", pktlist] + (args if args is not None else []),
             stdout=subprocess.PIPE if dump or getfd else None,
             stderr=open(os.devnull),
         )
@@ -1158,16 +1169,14 @@ u'64'
         else:
             tmpfile.close()
         proc = subprocess.Popen(
-            [conf.prog.tcpdump if prog is None else prog, "-r",
-             tmpfile.name] + (["-n"] if args is None else args),
+            prog + ["-r", tmpfile.name] + (args if args is not None else []),
             stdout=subprocess.PIPE if dump or getfd else None,
             stderr=open(os.devnull),
         )
         conf.temp_files.append(tmpfile.name)
     else:
         proc = subprocess.Popen(
-            [conf.prog.tcpdump if prog is None else prog, "-r", "-"]
-            + (["-n"] if args is None else args),
+            prog + ["-r", "-"] + (args if args is not None else []),
             stdin=subprocess.PIPE,
             stdout=subprocess.PIPE if dump or getfd else None,
             stderr=open(os.devnull),
-- 
GitLab