Skip to content
Merged
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
55 changes: 39 additions & 16 deletions scapy/sendrecv.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False,
timeout: how much time to wait after the last packet has been sent
verbose: set verbosity level
multi: whether to accept multiple answers for the same stimulus"""
if not isinstance(pkt, Gen):
pkt = SetGen(pkt)
is_single = isinstance(pkt, Gen)
pkts = [pkt] if is_single else pkt
if verbose is None:
verbose = conf.verb
debug.recv = plist.PacketList([],"Unanswered")
Expand All @@ -183,15 +183,16 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False,
nbrecv = 0
ans = []
# do it here to fix random fields, so that parent and child have the same
tobesent = [p for p in pkt]
tobesent = [p for p in (pkt if is_single else SetGen(pkt))]
notans = len(tobesent)

if retry < 0:
retry = -retry
autostop = retry
autostop = retry = -retry
else:
autostop = 0

for pkt in pkts:
pkt.sent_time = None
while retry >= 0:
if timeout is not None and timeout < 0:
timeout = None
Expand All @@ -207,18 +208,28 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False,
(rcv_pks or pks), tobesent, stopevent, nbrecv, notans, verbose, chainCC, multi,
)
thread.join()

ans.extend(newans)
to_set_time = [pkt for pkt in pkts if pkt.sent_time is None]
if to_set_time:
try:
sent_time = min(p.sent_time for p in tobesent if getattr(p, "sent_time", None))
except ValueError:
pass
else:
for pkt in to_set_time:
pkt.sent_time = sent_time

remain = list(itertools.chain(*six.itervalues(hsent)))
if multi:
remain = [p for p in remain if not hasattr(p, '_answered')]
remain = itertools.chain(*six.itervalues(hsent))
remain = [p for p in remain if not hasattr(p, '_answered')] if multi else list(remain)

if autostop and len(remain) > 0 and len(remain) != len(tobesent):
if not remain:
break

if autostop and len(remain) != len(tobesent):
retry = autostop

tobesent = remain
if len(tobesent) == 0:
break
retry -= 1

if conf.debug_match:
Expand Down Expand Up @@ -497,9 +508,9 @@ def srploop(pkts, *args, **kargs):
def sndrcvflood(pks, pkt, inter=0, verbose=None, chainCC=False, prn=lambda x: x):
if not verbose:
verbose = conf.verb
if not isinstance(pkt, Gen):
pkt = SetGen(pkt)
tobesent = [p for p in pkt]
is_single = isinstance(pkt, Gen)
pkts = [pkt] if is_single else pkt
tobesent = [p for p in (pkt if is_single else SetGen(pkt))]

stopevent = threading.Event()
count_packets = six.moves.queue.Queue()
Expand All @@ -515,6 +526,8 @@ def send_in_loop(tobesent, stopevent, count_packets=count_packets):

infinite_gen = send_in_loop(tobesent, stopevent)

for pkt in pkts:
pkt.sent_time = None
# We don't use _sndrcv_snd verbose (it messes the logs up as in a thread that ends after recieving)
thread = threading.Thread(
target=_sndrcv_snd,
Expand All @@ -524,9 +537,19 @@ def send_in_loop(tobesent, stopevent, count_packets=count_packets):

hsent, ans, nbrecv, notans = _sndrcv_rcv(pks, tobesent, stopevent, 0, len(tobesent), verbose, chainCC, False)
thread.join()

ans = [(x, prn(y)) for (x, y) in ans] # Apply prn
to_set_time = [pkt for pkt in pkts if pkt.sent_time is None]
if to_set_time:
try:
sent_time = min(p.sent_time for p in tobesent if getattr(p, "sent_time", None))
except ValueError:
pass
else:
for pkt in to_set_time:
pkt.sent_time = sent_time

remain = list(itertools.chain(*six.itervalues(hsent)))
# Apply prn
ans = [(x, prn(y)) for (x, y) in ans]

if verbose:
print("\nReceived %i packets, got %i answers, remaining %i packets. Sent a total of %i packets." % (nbrecv+len(ans), len(ans), notans, count_packets.qsize()))
Expand Down
28 changes: 28 additions & 0 deletions test/regression.uts
Original file line number Diff line number Diff line change
Expand Up @@ -1223,6 +1223,34 @@ for i in range(10):
response = res[0][1]
assert response[ICMP].type == 0

= Test set of sent_time by sr
~ netaccess IP ICMP
packet = IP(dst="8.8.8.8")/ICMP()
r = sr(packet)
assert packet.sent_time is not None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic between ˋsrandsr1` is the same. Because networking tests tend to fail more often, it would be good not to have too many doing the same thing :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


= Test set of sent_time by sr (multiple packets)
~ netaccess IP ICMP
packet1 = IP(dst="8.8.8.8")/ICMP()
packet2 = IP(dst="8.8.4.4")/ICMP()
r = sr([packet1, packet2])
assert packet1.sent_time is not None
assert packet2.sent_time is not None

= Test set of sent_time by srflood
~ netaccess IP ICMP
packet = IP(dst="8.8.8.8")/ICMP()
r = srflood(packet)
assert packet.sent_time is not None

= Test set of sent_time by srflood (multiple packets)
~ netaccess IP ICMP
packet1 = IP(dst="8.8.8.8")/ICMP()
packet2 = IP(dst="8.8.4.4")/ICMP()
r = srflood([packet1, packet2])
assert packet1.sent_time is not None
assert packet2.sent_time is not None

############
############
+ ManuFDB tests
Expand Down