From e41627769f6eba2dc54f102e8e7c0bc246090eec Mon Sep 17 00:00:00 2001
From: Alexander Bluhm <alexander.bluhm@gmx.net>
Date: Thu, 8 Dec 2016 00:54:14 +0100
Subject: [PATCH] Allow to set promisc mode in sndrcv().

In the pcapdnet() backend it was not possible to run the
L{2,3}{pcap,dnet}Socket in promiscuous mode.  Add a promisc option
to sr(), sr1(), srp(), srp1(), srflood(), srpflood() so that the
user can choose the behavior.

Keep the default non-promiscuous as in most cases sndrcv() sniffs
an answer that is directed to the sender.
---
 scapy/arch/pcapdnet.py | 21 +++++++++++++++------
 scapy/sendrecv.py      | 20 ++++++++++----------
 2 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/scapy/arch/pcapdnet.py b/scapy/arch/pcapdnet.py
index ae628bce..09bbe8de 100755
--- a/scapy/arch/pcapdnet.py
+++ b/scapy/arch/pcapdnet.py
@@ -229,11 +229,14 @@ if conf.use_winpcapy:
   conf.L2listen = L2pcapListenSocket
   class L2pcapSocket(SuperSocket):
       desc = "read/write packets at layer 2 using only libpcap"
-      def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
+      def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None, nofilter=0):
           if iface is None:
               iface = conf.iface
           self.iface = iface
-          self.ins = open_pcap(iface, 1600, 0, 100)
+          if promisc is None:
+              promisc = 0
+          self.promisc = promisc
+          self.ins = open_pcap(iface, 1600, self.promisc, 100)
           try:
               ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
           except:
@@ -524,13 +527,16 @@ if conf.use_dnet:
 if conf.use_pcap and conf.use_dnet:
     class L3dnetSocket(SuperSocket):
         desc = "read/write packets at layer 3 using libdnet and libpcap"
-        def __init__(self, type = ETH_P_ALL, filter=None, promisc=None, iface=None, nofilter=0):
+        def __init__(self, type = ETH_P_ALL, promisc=None, filter=None, iface=None, nofilter=0):
             self.iflist = {}
             self.intf = dnet.intf()
             if iface is None:
                 iface = conf.iface
             self.iface = iface
-            self.ins = open_pcap(iface, 1600, 0, 100)
+            if promisc is None:
+                promisc = 0
+            self.promisc = promisc
+            self.ins = open_pcap(iface, 1600, self.promisc, 100)
             try:
                 ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
             except:
@@ -614,11 +620,14 @@ if conf.use_pcap and conf.use_dnet:
     
     class L2dnetSocket(SuperSocket):
         desc = "read/write packets at layer 2 using libdnet and libpcap"
-        def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0):
+        def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None, nofilter=0):
             if iface is None:
                 iface = conf.iface
             self.iface = iface
-            self.ins = open_pcap(iface, 1600, 0, 100)
+            if promisc is None:
+                promisc = 0
+            self.promisc = promisc
+            self.ins = open_pcap(iface, 1600, self.promisc, 100)
             try:
                 ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1))
             except:
diff --git a/scapy/sendrecv.py b/scapy/sendrecv.py
index 5f6274b7..b27ee632 100644
--- a/scapy/sendrecv.py
+++ b/scapy/sendrecv.py
@@ -326,7 +326,7 @@ def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, i
         
     
 @conf.commands.register
-def sr(x,filter=None, iface=None, nofilter=0, *args,**kargs):
+def sr(x, promisc=None, filter=None, iface=None, nofilter=0, *args,**kargs):
     """Send and receive packets at layer 3
 nofilter: put 1 to avoid use of BPF filters
 retry:    if positive, how many times to resend unanswered packets
@@ -338,13 +338,13 @@ filter:   provide a BPF filter
 iface:    listen answers only on the given interface"""
     if not kargs.has_key("timeout"):
         kargs["timeout"] = -1
-    s = conf.L3socket(filter=filter, iface=iface, nofilter=nofilter)
+    s = conf.L3socket(promisc=promisc, filter=filter, iface=iface, nofilter=nofilter)
     a,b=sndrcv(s,x,*args,**kargs)
     s.close()
     return a,b
 
 @conf.commands.register
-def sr1(x,filter=None,iface=None, nofilter=0, *args,**kargs):
+def sr1(x, promisc=None, filter=None, iface=None, nofilter=0, *args,**kargs):
     """Send packets at layer 3 and return only the first answer
 nofilter: put 1 to avoid use of BPF filters
 retry:    if positive, how many times to resend unanswered packets
@@ -356,7 +356,7 @@ filter:   provide a BPF filter
 iface:    listen answers only on the given interface"""
     if not kargs.has_key("timeout"):
         kargs["timeout"] = -1
-    s=conf.L3socket(filter=filter, nofilter=nofilter, iface=iface)
+    s=conf.L3socket(promisc=promisc, filter=filter, nofilter=nofilter, iface=iface)
     a,b=sndrcv(s,x,*args,**kargs)
     s.close()
     if len(a) > 0:
@@ -365,7 +365,7 @@ iface:    listen answers only on the given interface"""
         return None
 
 @conf.commands.register
-def srp(x,iface=None, iface_hint=None, filter=None, nofilter=0, type=ETH_P_ALL, *args,**kargs):
+def srp(x, promisc=None, iface=None, iface_hint=None, filter=None, nofilter=0, type=ETH_P_ALL, *args,**kargs):
     """Send and receive packets at layer 2
 nofilter: put 1 to avoid use of BPF filters
 retry:    if positive, how many times to resend unanswered packets
@@ -379,7 +379,7 @@ iface:    work only on the given interface"""
         kargs["timeout"] = -1
     if iface is None and iface_hint is not None:
         iface = conf.route.route(iface_hint)[0]
-    s = conf.L2socket(iface=iface, filter=filter, nofilter=nofilter, type=type)
+    s = conf.L2socket(promisc=promisc, iface=iface, filter=filter, nofilter=nofilter, type=type)
     a,b=sndrcv(s ,x,*args,**kargs)
     s.close()
     return a,b
@@ -527,7 +527,7 @@ def sndrcvflood(pks, pkt, prn=lambda (s,r):r.summary(), chainCC=0, store=1, uniq
     return received
 
 @conf.commands.register
-def srflood(x,filter=None, iface=None, nofilter=None, *args,**kargs):
+def srflood(x, promisc=None, filter=None, iface=None, nofilter=None, *args,**kargs):
     """Flood and receive packets at layer 3
 prn:      function applied to packets received. Ret val is printed if not None
 store:    if 1 (default), store answers and return them
@@ -535,13 +535,13 @@ unique:   only consider packets whose print
 nofilter: put 1 to avoid use of BPF filters
 filter:   provide a BPF filter
 iface:    listen answers only on the given interface"""
-    s = conf.L3socket(filter=filter, iface=iface, nofilter=nofilter)
+    s = conf.L3socket(promisc=promisc, filter=filter, iface=iface, nofilter=nofilter)
     r=sndrcvflood(s,x,*args,**kargs)
     s.close()
     return r
 
 @conf.commands.register
-def srpflood(x,filter=None, iface=None, iface_hint=None, nofilter=None, *args,**kargs):
+def srpflood(x, promisc=None, filter=None, iface=None, iface_hint=None, nofilter=None, *args,**kargs):
     """Flood and receive packets at layer 2
 prn:      function applied to packets received. Ret val is printed if not None
 store:    if 1 (default), store answers and return them
@@ -551,7 +551,7 @@ filter:   provide a BPF filter
 iface:    listen answers only on the given interface"""
     if iface is None and iface_hint is not None:
         iface = conf.route.route(iface_hint)[0]    
-    s = conf.L2socket(filter=filter, iface=iface, nofilter=nofilter)
+    s = conf.L2socket(promisc=promisc, filter=filter, iface=iface, nofilter=nofilter)
     r=sndrcvflood(s,x,*args,**kargs)
     s.close()
     return r
-- 
GitLab