@@ -42,19 +42,57 @@ class PcapTimeoutElapsed(Scapy_Exception):
4242
4343
4444class _L2pcapdnetSocket (SuperSocket , SelectableObject ):
45- def check_recv (self ):
46- return True
47-
48- def recv_raw (self , x = MTU ):
49- """Receives a packet, then returns a tuple containing (cls, pkt_data, time)""" # noqa: E501
45+ def __init__ (self , promisc = None , iface = None ):
46+ self .type = type
47+ self .outs = None
48+ if iface is None :
49+ iface = conf .iface
50+ self .iface = iface
51+ if promisc is None :
52+ promisc = conf .sniff_promisc
53+ self .promisc = promisc
54+
55+ def _process_loaded_streams (self , type , filter , nofilter ):
56+ """This is an internal function, used while initializing pcap
57+ sockets"""
58+ # Guess cls
5059 ll = self .ins .datalink ()
5160 if ll in conf .l2types :
52- cls = conf .l2types [ll ]
61+ self . cls = conf .l2types [ll ]
5362 else :
54- cls = conf .default_l2
63+ self . cls = conf .default_l2
5564 warning ("Unable to guess datalink type (interface=%s linktype=%i). Using %s" , # noqa: E501
5665 self .iface , ll , cls .name )
66+ # Enable immediate mode: reads return immediately upon packet reception
67+ try :
68+ ioctl (self .ins .fileno (), BIOCIMMEDIATE , struct .pack ("I" , 1 ))
69+ except :
70+ pass
71+ # Apply init filter & rules
72+ if nofilter :
73+ if type != ETH_P_ALL : # PF_PACKET stuff. Need to emulate this for pcap # noqa: E501
74+ filter = "ether proto %i" % type
75+ else :
76+ filter = None
77+ else :
78+ if conf .except_filter :
79+ if filter :
80+ filter = "(%s) and not (%s)" % (filter , conf .except_filter ) # noqa: E501
81+ else :
82+ filter = "not (%s)" % conf .except_filter
83+ if type != ETH_P_ALL : # PF_PACKET stuff. Need to emulate this for pcap # noqa: E501
84+ if filter :
85+ filter = "(ether proto %i) and (%s)" % (type , filter )
86+ else :
87+ filter = "ether proto %i" % type
88+ if filter :
89+ self .ins .setfilter (filter )
90+
91+ def check_recv (self ):
92+ return True
5793
94+ def recv_raw (self , x = MTU ):
95+ """Receives a packet, then returns a tuple containing (cls, pkt_data, time)""" # noqa: E501
5896 pkt = None
5997 while pkt is None :
6098 pkt = self .ins .next ()
@@ -64,7 +102,7 @@ def recv_raw(self, x=MTU):
64102 raise PcapTimeoutElapsed # To understand this behavior, have a look at L2pcapListenSocket's note # noqa: E501
65103 if pkt is None :
66104 return None , None , None
67- return cls , pkt , ts
105+ return self . cls , pkt , ts
68106
69107 def nonblock_recv (self ):
70108 """Receives and dissect a packet in non-blocking mode.
@@ -397,37 +435,22 @@ def __del__(self):
397435 class L2pcapListenSocket (_L2pcapdnetSocket ):
398436 desc = "read packets at layer 2 using libpcap"
399437
400- def __init__ (self , iface = None , type = ETH_P_ALL , promisc = None , filter = None , monitor = None ): # noqa: E501
401- self .type = type
402- self .outs = None
403- self .iface = iface
404- if iface is None :
405- iface = conf .iface
406- if promisc is None :
407- promisc = conf .sniff_promisc
408- self .promisc = promisc
438+ def __init__ (self , iface = None , type = ETH_P_ALL , promisc = None , filter = None , nofilter = 0 , # noqa: E501
439+ monitor = None ): # noqa: E501
440+ _L2pcapdnetSocket .__init__ (self , promisc = promisc , iface = iface )
409441 # Note: Timeout with Winpcap/Npcap
410442 # The 4th argument of open_pcap corresponds to timeout. In an ideal world, we would # noqa: E501
411443 # set it to 0 ==> blocking pcap_next_ex.
412444 # However, the way it is handled is very poor, and result in a jerky packet stream. # noqa: E501
413445 # To fix this, we set 100 and the implementation under windows is slightly different, as # noqa: E501
414446 # everything is always received as non-blocking
415- self .ins = open_pcap (iface , MTU , self .promisc , 100 , monitor = monitor ) # noqa: E501
416- try :
417- ioctl (self .ins .fileno (), BIOCIMMEDIATE , struct .pack ("I" , 1 ))
418- except :
419- pass
420- if type == ETH_P_ALL : # Do not apply any filter if Ethernet type is given # noqa: E501
421- if conf .except_filter :
422- if filter :
423- filter = "(%s) and not (%s)" % (filter , conf .except_filter ) # noqa: E501
424- else :
425- filter = "not (%s)" % conf .except_filter
426- if filter :
427- self .ins .setfilter (filter )
447+ self .ins = open_pcap (self .iface , MTU , self .promisc , 100 , monitor = monitor ) # noqa: E501
448+ # Post init routine
449+ self ._process_loaded_streams (type , filter , nofilter )
428450
429451 def close (self ):
430452 self .ins .close ()
453+ self .closed = True
431454
432455 def send (self , x ):
433456 raise Scapy_Exception ("Can't send anything with L2pcapListenSocket" ) # noqa: E501
@@ -439,40 +462,16 @@ class L2pcapSocket(_L2pcapdnetSocket):
439462
440463 def __init__ (self , iface = None , type = ETH_P_ALL , promisc = None , filter = None , nofilter = 0 , # noqa: E501
441464 monitor = None ):
442- if iface is None :
443- iface = conf .iface
444- self .iface = iface
445- if promisc is None :
446- promisc = 0
447- self .promisc = promisc
465+ _L2pcapdnetSocket .__init__ (self , promisc = promisc , iface = iface )
448466 # See L2pcapListenSocket for infos about this line
449- self .ins = open_pcap (iface , MTU , self .promisc , 100 , monitor = monitor ) # noqa: E501
467+ self .ins = open_pcap (self . iface , MTU , self .promisc , 100 , monitor = monitor ) # noqa: E501
450468 # We need to have a different interface open because of an
451469 # access violation in Npcap that occurs in multi-threading
452470 # (see https://github.com/nmap/nmap/issues/982)
453- self .outs = open_pcap (iface , MTU , self .promisc , 100 )
454- try :
455- ioctl (self .ins .fileno (), BIOCIMMEDIATE , struct .pack ("I" , 1 ))
456- except :
457- pass
458- if nofilter :
459- if type != ETH_P_ALL : # PF_PACKET stuff. Need to emulate this for pcap # noqa: E501
460- filter = "ether proto %i" % type
461- else :
462- filter = None
463- else :
464- if conf .except_filter :
465- if filter :
466- filter = "(%s) and not (%s)" % (filter , conf .except_filter ) # noqa: E501
467- else :
468- filter = "not (%s)" % conf .except_filter
469- if type != ETH_P_ALL : # PF_PACKET stuff. Need to emulate this for pcap # noqa: E501
470- if filter :
471- filter = "(ether proto %i) and (%s)" % (type , filter )
472- else :
473- filter = "ether proto %i" % type
474- if filter :
475- self .ins .setfilter (filter )
471+ self .outs = open_pcap (self .iface , MTU , self .promisc , 100 , monitor = monitor )
472+ # Post init routine
473+ self ._process_loaded_streams (type , filter , nofilter )
474+
476475
477476 def send (self , x ):
478477 sx = raw (x )
@@ -493,8 +492,8 @@ class L3pcapSocket(L2pcapSocket):
493492 # def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0): # noqa: E501
494493 # L2pcapSocket.__init__(self, iface, type, filter, nofilter)
495494
496- def recv (self , x = MTU ):
497- r = L2pcapSocket .recv (self , x )
495+ def recv (self , ** kwargs ):
496+ r = L2pcapSocket .recv (self , ** kwargs )
498497 if r :
499498 return r .payload
500499 else :
0 commit comments