Skip to content
Open
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
7 changes: 5 additions & 2 deletions scapy/contrib/isotp/isotp_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,11 +345,14 @@ def __init__(self, *args, **kwargs):
basecls=kwargs.pop("basecls", ISOTP))
super(ISOTPSession, self).__init__(*args, **kwargs)

def recv(self, sock: SuperSocket) -> Iterator[Packet]:
def recv(self, sock: SuperSocket, nonblock: bool = False) -> Iterator[Packet]:
"""
Will be called by sniff() to ask for a packet
"""
pkt = sock.recv()
if nonblock and hasattr(sock, "nonblock_recv"):
pkt = sock.nonblock_recv()
else:
pkt = sock.recv()
if not pkt:
return
self.m.feed(pkt)
Expand Down
6 changes: 5 additions & 1 deletion scapy/sendrecv.py
Original file line number Diff line number Diff line change
Expand Up @@ -1336,7 +1336,11 @@ def stop_cb():
# The session object is passed the socket to call recv() on,
# and may perform additional processing (ip defrag, etc.)
try:
packets = session.recv(s)
packets = session.recv(
s,
nonblock=timeout is not None and
hasattr(s, "nonblock_recv"),
)
# A session can return multiple objects
for p in packets:
if lfilter and not lfilter(p):
Expand Down
14 changes: 10 additions & 4 deletions scapy/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,14 @@ def process(self, pkt: Packet) -> Optional[Packet]:
return self.supersession.process(pkt)
return pkt

def recv(self, sock: 'SuperSocket') -> Iterator[Packet]:
def recv(self, sock: 'SuperSocket', nonblock: bool = False) -> Iterator[Packet]:
"""
Will be called by sniff() to ask for a packet
"""
pkt = sock.recv()
if nonblock and hasattr(sock, "nonblock_recv"):
pkt = sock.nonblock_recv()
else:
pkt = sock.recv()
if not pkt:
return
pkt = self.process(pkt)
Expand Down Expand Up @@ -407,11 +410,14 @@ def process(self,
return pkt
return None

def recv(self, sock: 'SuperSocket') -> Iterator[Packet]:
def recv(self, sock: 'SuperSocket', nonblock: bool = False) -> Iterator[Packet]:
"""
Will be called by sniff() to ask for a packet
"""
pkt = sock.recv(stop_dissection_after=self.stop_dissection_after)
if nonblock and hasattr(sock, "nonblock_recv"):
pkt = sock.nonblock_recv()
else:
pkt = sock.recv(stop_dissection_after=self.stop_dissection_after)
# Now handle TCP reassembly
if self.app:
while pkt is not None:
Expand Down
39 changes: 39 additions & 0 deletions test/regression.uts
Original file line number Diff line number Diff line change
Expand Up @@ -2061,6 +2061,45 @@ o.send(REFPACKET)
pkts = sniff(opened_socket=[o], timeout=3)
assert len(pkts) == 10

= sniff timeout with select-ready but empty pcap socket (#4590)

import time
from scapy.automaton import ObjectPipe
from scapy.supersocket import SuperSocket

class PcapLikeSocket(SuperSocket):
def __init__(self):
self.ins = ObjectPipe(name="pcap_like_socket")
self.outs = None
self.recv_called = False

def recv(self, x=65535, **kwargs):
self.recv_called = True
time.sleep(60)
return None

def nonblock_recv(self, x=65535):
return None

@staticmethod
def select(sockets, remain=None):
return list(sockets)

def close(self):
if self.closed:
return
self.closed = True
self.ins.close()

sock = PcapLikeSocket()
t0 = time.monotonic()
pkts = sniff(opened_socket=sock, timeout=1, count=1)
elapsed = time.monotonic() - t0
assert not sock.recv_called, "blocking recv must not be used with timeout"
assert elapsed < 3, "sniff should stop on timeout, got %.1fs" % elapsed
assert len(pkts) == 0
sock.close()

= GH issue 3306
~ netaccess needs_root

Expand Down
Loading