From d5e3fc20994f338358a18b33bd8818c75bf1484b Mon Sep 17 00:00:00 2001
From: Pierre LALET <pierre.lalet@cea.fr>
Date: Fri, 25 Aug 2017 13:49:52 +0200
Subject: [PATCH] Implement bridge_and_sniff() using sniff()

This removes duplicated code and should make bridge_and_sniff()
function work under Windows.
---
 scapy/sendrecv.py | 100 +++++++++++++++++-----------------------------
 1 file changed, 36 insertions(+), 64 deletions(-)

diff --git a/scapy/sendrecv.py b/scapy/sendrecv.py
index dee5a746..4503abca 100644
--- a/scapy/sendrecv.py
+++ b/scapy/sendrecv.py
@@ -734,76 +734,48 @@ Examples:
 
 
 @conf.commands.register
-def bridge_and_sniff(if1, if2, count=0, store=1, prn=None, lfilter=None,
-                     L2socket=None, timeout=None, stop_filter=None, *args,
-                     **kargs):
-    """Forward traffic between two interfaces and sniff packets exchanged
-bridge_and_sniff([count=0,] [prn=None,] [store=1,] [offline=None,] 
-[lfilter=None,] + L2Socket args) -> list of packets
-
-  count: number of packets to capture. 0 means infinity
-  store: whether to store sniffed packets or discard them
-    prn: function to apply to each packet. If something is returned,
-         it is displayed. Ex:
-         ex: prn = lambda x: x.summary()
-lfilter: python function applied to each packet to determine
-         if further action may be done
-         ex: lfilter = lambda x: x.haslayer(Padding)
-timeout: stop sniffing after a given time (default: None)
-L2socket: use the provided L2socket
-stop_filter: python function applied to each packet to determine
-             if we have to stop the capture after this packet
-             ex: stop_filter = lambda x: x.haslayer(TCP)
+def bridge_and_sniff(if1, if2, prn=None, L2socket=None, *args, **kargs):
+    """Forward traffic between interfaces if1 and if2, sniff and return the
+exchanged packets.
+
+Arguments:
+
+  if1, if2: the interfaces to use
+
+  The other arguments are the same than for the function sniff(),
+      except for opened_socket, offline and iface that are ignored.
+      See help(sniff) for more.
+
     """
-    c = 0
+    for arg in ['opened_socket', 'offline', 'iface']:
+        if arg in kargs:
+            log_runtime.warning("Argument %s cannot be used in "
+                                "bridge_and_sniff() -- ignoring it.", arg)
+            del kargs[arg]
     if L2socket is None:
         L2socket = conf.L2socket
     s1 = L2socket(iface=if1)
     s2 = L2socket(iface=if2)
-    peerof={s1:s2,s2:s1}
-    label={s1:if1, s2:if2}
-    
-    lst = []
-    if timeout is not None:
-        stoptime = time.time()+timeout
-    remain = None
-    try:
-        stop_event = False
-        while not stop_event:
-            if timeout is not None:
-                remain = stoptime-time.time()
-                if remain <= 0:
-                    break
-            if conf.use_bpf:
-                from scapy.arch.bpf.supersocket import bpf_select
-                ins = bpf_select([s1, s2], remain)
-            else:
-                ins, _, _ = select([s1, s2], [], [], remain)
+    peers = {if1: s2, if2: s1}
+    def prn_send(pkt):
+        try:
+            sendsock = peers[pkt.sniffed_on]
+        except KeyError:
+            return
+        try:
+            sendsock.send(pkt.original)
+        except:
+            log_runtime.warning('Cannot forward packet [%s] received from %s',
+                                pkt.summary(), pkt.sniffed_on, exc_info=True)
+    if prn is None:
+        prn = prn_send
+    else:
+        prn_orig = prn
+        def prn(pkt):
+            prn_send(pkt)
+            return prn_orig(pkt)
 
-            for s in ins:
-                p = s.recv()
-                if p is not None:
-                    peerof[s].send(p.original)
-                    if lfilter and not lfilter(p):
-                        continue
-                    if store:
-                        p.sniffed_on = label[s]
-                        lst.append(p)
-                    c += 1
-                    if prn:
-                        r = prn(p)
-                        if r is not None:
-                            print(r)
-                    if stop_filter and stop_filter(p):
-                        stop_event = True
-                        break
-                    if 0 < count <= c:
-                        stop_event = True
-                        break
-    except KeyboardInterrupt:
-        pass
-    finally:
-        return plist.PacketList(lst,"Sniffed")
+    return sniff(opened_socket={s1: if1, s2: if2}, prn=prn, *args, **kargs)
 
 
 @conf.commands.register
-- 
GitLab