Skip to content

Commit 94d5521

Browse files
authored
Merge pull request #1282 from karpierz/issue_1199_fix
Fix for issue #1199 (regression against scapy<=2.3.2). [PR is ready for merge to the master]
2 parents a13a05c + 8725782 commit 94d5521

File tree

2 files changed

+67
-16
lines changed

2 files changed

+67
-16
lines changed

scapy/sendrecv.py

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False,
173173
timeout: how much time to wait after the last packet has been sent
174174
verbose: set verbosity level
175175
multi: whether to accept multiple answers for the same stimulus"""
176-
if not isinstance(pkt, Gen):
177-
pkt = SetGen(pkt)
176+
is_single = isinstance(pkt, Gen)
177+
pkts = [pkt] if is_single else pkt
178178
if verbose is None:
179179
verbose = conf.verb
180180
debug.recv = plist.PacketList([],"Unanswered")
@@ -183,15 +183,16 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False,
183183
nbrecv = 0
184184
ans = []
185185
# do it here to fix random fields, so that parent and child have the same
186-
tobesent = [p for p in pkt]
186+
tobesent = [p for p in (pkt if is_single else SetGen(pkt))]
187187
notans = len(tobesent)
188188

189189
if retry < 0:
190-
retry = -retry
191-
autostop = retry
190+
autostop = retry = -retry
192191
else:
193192
autostop = 0
194193

194+
for pkt in pkts:
195+
pkt.sent_time = None
195196
while retry >= 0:
196197
if timeout is not None and timeout < 0:
197198
timeout = None
@@ -207,18 +208,28 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False,
207208
(rcv_pks or pks), tobesent, stopevent, nbrecv, notans, verbose, chainCC, multi,
208209
)
209210
thread.join()
211+
210212
ans.extend(newans)
213+
to_set_time = [pkt for pkt in pkts if pkt.sent_time is None]
214+
if to_set_time:
215+
try:
216+
sent_time = min(p.sent_time for p in tobesent if getattr(p, "sent_time", None))
217+
except ValueError:
218+
pass
219+
else:
220+
for pkt in to_set_time:
221+
pkt.sent_time = sent_time
211222

212-
remain = list(itertools.chain(*six.itervalues(hsent)))
213-
if multi:
214-
remain = [p for p in remain if not hasattr(p, '_answered')]
223+
remain = itertools.chain(*six.itervalues(hsent))
224+
remain = [p for p in remain if not hasattr(p, '_answered')] if multi else list(remain)
215225

216-
if autostop and len(remain) > 0 and len(remain) != len(tobesent):
226+
if not remain:
227+
break
228+
229+
if autostop and len(remain) != len(tobesent):
217230
retry = autostop
218231

219232
tobesent = remain
220-
if len(tobesent) == 0:
221-
break
222233
retry -= 1
223234

224235
if conf.debug_match:
@@ -497,9 +508,9 @@ def srploop(pkts, *args, **kargs):
497508
def sndrcvflood(pks, pkt, inter=0, verbose=None, chainCC=False, prn=lambda x: x):
498509
if not verbose:
499510
verbose = conf.verb
500-
if not isinstance(pkt, Gen):
501-
pkt = SetGen(pkt)
502-
tobesent = [p for p in pkt]
511+
is_single = isinstance(pkt, Gen)
512+
pkts = [pkt] if is_single else pkt
513+
tobesent = [p for p in (pkt if is_single else SetGen(pkt))]
503514

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

516527
infinite_gen = send_in_loop(tobesent, stopevent)
517528

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

525538
hsent, ans, nbrecv, notans = _sndrcv_rcv(pks, tobesent, stopevent, 0, len(tobesent), verbose, chainCC, False)
526539
thread.join()
540+
541+
ans = [(x, prn(y)) for (x, y) in ans] # Apply prn
542+
to_set_time = [pkt for pkt in pkts if pkt.sent_time is None]
543+
if to_set_time:
544+
try:
545+
sent_time = min(p.sent_time for p in tobesent if getattr(p, "sent_time", None))
546+
except ValueError:
547+
pass
548+
else:
549+
for pkt in to_set_time:
550+
pkt.sent_time = sent_time
551+
527552
remain = list(itertools.chain(*six.itervalues(hsent)))
528-
# Apply prn
529-
ans = [(x, prn(y)) for (x, y) in ans]
530553

531554
if verbose:
532555
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()))

test/regression.uts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,34 @@ for i in range(10):
12231223
response = res[0][1]
12241224
assert response[ICMP].type == 0
12251225

1226+
= Test set of sent_time by sr
1227+
~ netaccess IP ICMP
1228+
packet = IP(dst="8.8.8.8")/ICMP()
1229+
r = sr(packet)
1230+
assert packet.sent_time is not None
1231+
1232+
= Test set of sent_time by sr (multiple packets)
1233+
~ netaccess IP ICMP
1234+
packet1 = IP(dst="8.8.8.8")/ICMP()
1235+
packet2 = IP(dst="8.8.4.4")/ICMP()
1236+
r = sr([packet1, packet2])
1237+
assert packet1.sent_time is not None
1238+
assert packet2.sent_time is not None
1239+
1240+
= Test set of sent_time by srflood
1241+
~ netaccess IP ICMP
1242+
packet = IP(dst="8.8.8.8")/ICMP()
1243+
r = srflood(packet)
1244+
assert packet.sent_time is not None
1245+
1246+
= Test set of sent_time by srflood (multiple packets)
1247+
~ netaccess IP ICMP
1248+
packet1 = IP(dst="8.8.8.8")/ICMP()
1249+
packet2 = IP(dst="8.8.4.4")/ICMP()
1250+
r = srflood([packet1, packet2])
1251+
assert packet1.sent_time is not None
1252+
assert packet2.sent_time is not None
1253+
12261254
############
12271255
############
12281256
+ ManuFDB tests

0 commit comments

Comments
 (0)