Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/sendrecv.py: 13%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

734 statements  

1# SPDX-License-Identifier: GPL-2.0-only 

2# This file is part of Scapy 

3# See https://scapy.net/ for more information 

4# Copyright (C) Philippe Biondi <phil@secdev.org> 

5 

6""" 

7Functions to send and receive packets. 

8""" 

9 

10import itertools 

11from threading import Thread, Event 

12import os 

13import re 

14import socket 

15import subprocess 

16import time 

17import warnings 

18 

19from scapy.compat import plain_str 

20from scapy.data import ETH_P_ALL 

21from scapy.config import conf 

22from scapy.error import warning 

23from scapy.interfaces import ( 

24 network_name, 

25 resolve_iface, 

26 NetworkInterface, 

27) 

28from scapy.packet import Packet 

29from scapy.pton_ntop import inet_pton 

30from scapy.utils import get_temp_file, tcpdump, wrpcap, \ 

31 ContextManagerSubprocess, PcapReader, EDecimal 

32from scapy.plist import ( 

33 PacketList, 

34 QueryAnswer, 

35 SndRcvList, 

36) 

37from scapy.error import log_runtime, log_interactive, Scapy_Exception 

38from scapy.base_classes import Gen, SetGen 

39from scapy.sessions import DefaultSession 

40from scapy.supersocket import SuperSocket, IterSocket 

41 

42# Typing imports 

43from typing import ( 

44 Any, 

45 Callable, 

46 Dict, 

47 Iterator, 

48 List, 

49 Optional, 

50 Tuple, 

51 Type, 

52 Union, 

53 cast 

54) 

55from scapy.interfaces import _GlobInterfaceType 

56from scapy.plist import _PacketIterable 

57 

58if conf.route is None: 

59 # unused import, only to initialize conf.route and conf.iface* 

60 import scapy.route # noqa: F401 

61 

62################# 

63# Debug class # 

64################# 

65 

66 

67class debug: 

68 recv = PacketList([], "Received") 

69 sent = PacketList([], "Sent") 

70 match = SndRcvList([], "Matched") 

71 crashed_on = None # type: Optional[Tuple[Type[Packet], bytes]] 

72 

73 

74#################### 

75# Send / Receive # 

76#################### 

77 

78_DOC_SNDRCV_PARAMS = """ 

79 :param pks: SuperSocket instance to send/receive packets 

80 :param pkt: the packet to send 

81 :param timeout: how much time to wait after the last packet has been sent 

82 :param inter: delay between two packets during sending 

83 :param verbose: set verbosity level 

84 :param chainCC: if True, KeyboardInterrupts will be forwarded 

85 :param retry: if positive, how many times to resend unanswered packets 

86 if negative, how many times to retry when no more packets 

87 are answered 

88 :param multi: whether to accept multiple answers for the same stimulus 

89 :param first: stop after receiving the first response of any sent packet 

90 :param rcv_pks: if set, will be used instead of pks to receive packets. 

91 packets will still be sent through pks 

92 :param prebuild: pre-build the packets before starting to send them. 

93 Automatically enabled when a generator is passed as the packet 

94 :param _flood: 

95 :param threaded: if True, packets are sent in a thread and received in another. 

96 Defaults to True. 

97 :param session: a flow decoder used to handle stream of packets 

98 :param chainEX: if True, exceptions during send will be forwarded 

99 :param stop_filter: Python function applied to each packet to determine if 

100 we have to stop the capture after this packet. 

101 """ 

102 

103 

104_GlobSessionType = Union[Type[DefaultSession], DefaultSession] 

105 

106 

107class SndRcvHandler(object): 

108 """ 

109 Util to send/receive packets, used by sr*(). 

110 Do not use directly. 

111 

112 This matches the requests and answers. 

113 

114 Notes:: 

115 - threaded: if you're planning to send/receive many packets, it's likely 

116 a good idea to use threaded mode. 

117 - DEVS: store the outgoing timestamp right BEFORE sending the packet 

118 to avoid races that could result in negative latency. We aren't Stadia 

119 """ 

120 def __init__(self, 

121 pks, # type: SuperSocket 

122 pkt, # type: _PacketIterable 

123 timeout=None, # type: Optional[int] 

124 inter=0, # type: int 

125 verbose=None, # type: Optional[int] 

126 chainCC=False, # type: bool 

127 retry=0, # type: int 

128 multi=False, # type: bool 

129 first=False, # type: bool 

130 rcv_pks=None, # type: Optional[SuperSocket] 

131 prebuild=False, # type: bool 

132 _flood=None, # type: Optional[_FloodGenerator] 

133 threaded=True, # type: bool 

134 session=None, # type: Optional[_GlobSessionType] 

135 chainEX=False, # type: bool 

136 stop_filter=None # type: Optional[Callable[[Packet], bool]] 

137 ): 

138 # type: (...) -> None 

139 # Instantiate all arguments 

140 if verbose is None: 

141 verbose = conf.verb 

142 if conf.debug_match: 

143 debug.recv = PacketList([], "Received") 

144 debug.sent = PacketList([], "Sent") 

145 debug.match = SndRcvList([], "Matched") 

146 self.nbrecv = 0 

147 self.ans = [] # type: List[QueryAnswer] 

148 self.pks = pks 

149 self.rcv_pks = rcv_pks or pks 

150 self.inter = inter 

151 self.verbose = verbose 

152 self.chainCC = chainCC 

153 self.multi = multi 

154 self.timeout = timeout 

155 self.first = first 

156 self.session = session 

157 self.chainEX = chainEX 

158 self.stop_filter = stop_filter 

159 self._send_done = False 

160 self.notans = 0 

161 self.noans = 0 

162 self._flood = _flood 

163 self.threaded = threaded 

164 self.breakout = Event() 

165 # Instantiate packet holders 

166 if prebuild and not self._flood: 

167 self.tobesent = list(pkt) # type: _PacketIterable 

168 else: 

169 self.tobesent = pkt 

170 

171 if retry < 0: 

172 autostop = retry = -retry 

173 else: 

174 autostop = 0 

175 

176 if timeout is not None and timeout < 0: 

177 self.timeout = None 

178 

179 while retry >= 0: 

180 self.breakout.clear() 

181 self.hsent = {} # type: Dict[bytes, List[Packet]] 

182 

183 if threaded or self._flood: 

184 # Send packets in thread. 

185 snd_thread = Thread( 

186 target=self._sndrcv_snd 

187 ) 

188 snd_thread.daemon = True 

189 

190 # Start routine with callback 

191 interrupted = None 

192 try: 

193 self._sndrcv_rcv(snd_thread.start) 

194 except KeyboardInterrupt as ex: 

195 interrupted = ex 

196 

197 self.breakout.set() 

198 

199 # Ended. Let's close gracefully 

200 if self._flood: 

201 # Flood: stop send thread 

202 self._flood.stop() 

203 snd_thread.join() 

204 

205 if interrupted and self.chainCC: 

206 raise interrupted 

207 else: 

208 # Send packets, then receive. 

209 try: 

210 self._sndrcv_rcv(self._sndrcv_snd) 

211 except KeyboardInterrupt: 

212 if self.chainCC: 

213 raise 

214 

215 if multi: 

216 remain = [ 

217 p for p in itertools.chain(*self.hsent.values()) 

218 if not hasattr(p, '_answered') 

219 ] 

220 else: 

221 remain = list(itertools.chain(*self.hsent.values())) 

222 

223 if autostop and len(remain) > 0 and \ 

224 len(remain) != len(self.tobesent): 

225 retry = autostop 

226 

227 self.tobesent = remain 

228 if len(self.tobesent) == 0: 

229 break 

230 retry -= 1 

231 

232 if conf.debug_match: 

233 debug.sent = PacketList(remain[:], "Sent") 

234 debug.match = SndRcvList(self.ans[:]) 

235 

236 # Clean the ans list to delete the field _answered 

237 if multi: 

238 for snd, _ in self.ans: 

239 if hasattr(snd, '_answered'): 

240 del snd._answered 

241 

242 if verbose: 

243 print( 

244 "\nReceived %i packets, got %i answers, " 

245 "remaining %i packets" % ( 

246 self.nbrecv + len(self.ans), len(self.ans), 

247 max(0, self.notans - self.noans) 

248 ) 

249 ) 

250 

251 self.ans_result = SndRcvList(self.ans) 

252 self.unans_result = PacketList(remain, "Unanswered") 

253 

254 def results(self): 

255 # type: () -> Tuple[SndRcvList, PacketList] 

256 return self.ans_result, self.unans_result 

257 

258 def _stop_sniffer_if_done(self) -> None: 

259 """Close the sniffer if all expected answers have been received""" 

260 if ( 

261 self._send_done and self.noans >= self.notans and not self.multi or 

262 self.first and self.noans 

263 ): 

264 if self.sniffer and self.sniffer.running: 

265 self.sniffer.stop(join=False) 

266 

267 def _sndrcv_snd(self): 

268 # type: () -> None 

269 """Function used in the sending thread of sndrcv()""" 

270 i = 0 

271 p = None 

272 try: 

273 if self.verbose: 

274 os.write(1, b"Begin emission\n") 

275 for p in self.tobesent: 

276 # Populate the dictionary of _sndrcv_rcv 

277 # _sndrcv_rcv won't miss the answer of a packet that 

278 # has not been sent 

279 self.hsent.setdefault(p.hashret(), []).append(p) 

280 # Send packet 

281 self.pks.send(p) 

282 time.sleep(self.inter) 

283 if self.breakout.is_set(): 

284 break 

285 i += 1 

286 if self.verbose: 

287 os.write(1, b"\nFinished sending %i packets\n" % i) 

288 except SystemExit: 

289 pass 

290 except Exception: 

291 if self.chainEX: 

292 raise 

293 else: 

294 log_runtime.exception("--- Error sending packets") 

295 finally: 

296 try: 

297 cast(Packet, self.tobesent).sent_time = \ 

298 cast(Packet, p).sent_time 

299 except AttributeError: 

300 pass 

301 if self._flood: 

302 self.notans = self._flood.iterlen 

303 elif not self._send_done: 

304 self.notans = i 

305 self._send_done = True 

306 self._stop_sniffer_if_done() 

307 # In threaded mode, timeout 

308 if self.threaded and self.timeout is not None and not self.breakout.is_set(): 

309 self.breakout.wait(timeout=self.timeout) 

310 if self.sniffer and self.sniffer.running: 

311 self.sniffer.stop() 

312 

313 def _process_packet(self, r): 

314 # type: (Packet) -> None 

315 """Internal function used to process each packet.""" 

316 if r is None: 

317 return 

318 ok = False 

319 h = r.hashret() 

320 if h in self.hsent: 

321 hlst = self.hsent[h] 

322 for i, sentpkt in enumerate(hlst): 

323 if r.answers(sentpkt): 

324 self.ans.append(QueryAnswer(sentpkt, r)) 

325 if self.verbose > 1: 

326 os.write(1, b"*") 

327 ok = True 

328 if not self.multi: 

329 del hlst[i] 

330 self.noans += 1 

331 else: 

332 if not hasattr(sentpkt, '_answered'): 

333 self.noans += 1 

334 sentpkt._answered = 1 

335 break 

336 self._stop_sniffer_if_done() 

337 if not ok: 

338 if self.verbose > 1: 

339 os.write(1, b".") 

340 self.nbrecv += 1 

341 if conf.debug_match: 

342 debug.recv.append(r) 

343 

344 def _sndrcv_rcv(self, callback): 

345 # type: (Callable[[], None]) -> None 

346 """Function used to receive packets and check their hashret""" 

347 # This is blocking. 

348 self.sniffer = None # type: Optional[AsyncSniffer] 

349 self.sniffer = AsyncSniffer() 

350 self.sniffer._run( 

351 prn=self._process_packet, 

352 timeout=None if self.threaded and not self._flood else self.timeout, 

353 store=False, 

354 opened_socket=self.rcv_pks, 

355 session=self.session, 

356 stop_filter=self.stop_filter, 

357 started_callback=callback, 

358 chainCC=True, 

359 ) 

360 

361 

362def sndrcv(*args, **kwargs): 

363 # type: (*Any, **Any) -> Tuple[SndRcvList, PacketList] 

364 """Scapy raw function to send a packet and receive its answer. 

365 WARNING: This is an internal function. Using sr/srp/sr1/srp is 

366 more appropriate in many cases. 

367 """ 

368 sndrcver = SndRcvHandler(*args, **kwargs) 

369 return sndrcver.results() 

370 

371 

372def __gen_send(s, # type: SuperSocket 

373 x, # type: _PacketIterable 

374 inter=0, # type: int 

375 loop=0, # type: int 

376 count=None, # type: Optional[int] 

377 verbose=None, # type: Optional[int] 

378 realtime=False, # type: bool 

379 return_packets=False, # type: bool 

380 *args, # type: Any 

381 **kargs # type: Any 

382 ): 

383 # type: (...) -> Optional[PacketList] 

384 """ 

385 An internal function used by send/sendp to actually send the packets, 

386 implement the send logic... 

387 

388 It will take care of iterating through the different packets 

389 """ 

390 if isinstance(x, str): 

391 x = conf.raw_layer(load=x) 

392 if not isinstance(x, Gen): 

393 x = SetGen(x) 

394 if verbose is None: 

395 verbose = conf.verb 

396 n = 0 

397 if count is not None: 

398 loop = -count 

399 elif not loop: 

400 loop = -1 

401 sent_packets = PacketList() if return_packets else None 

402 p = None 

403 try: 

404 while loop: 

405 dt0 = None 

406 for p in x: 

407 if realtime: 

408 ct = time.time() 

409 if dt0: 

410 st = dt0 + float(p.time) - ct 

411 if st > 0: 

412 time.sleep(st) 

413 else: 

414 dt0 = ct - float(p.time) 

415 s.send(p) 

416 if sent_packets is not None: 

417 sent_packets.append(p) 

418 n += 1 

419 if verbose: 

420 os.write(1, b".") 

421 time.sleep(inter) 

422 if loop < 0: 

423 loop += 1 

424 except KeyboardInterrupt: 

425 pass 

426 finally: 

427 try: 

428 cast(Packet, x).sent_time = cast(Packet, p).sent_time 

429 except AttributeError: 

430 pass 

431 if verbose: 

432 print("\nSent %i packets." % n) 

433 return sent_packets 

434 

435 

436def _send(x, # type: _PacketIterable 

437 _func, # type: Callable[[NetworkInterface], Type[SuperSocket]] 

438 inter=0, # type: int 

439 loop=0, # type: int 

440 iface=None, # type: Optional[_GlobInterfaceType] 

441 count=None, # type: Optional[int] 

442 verbose=None, # type: Optional[int] 

443 realtime=False, # type: bool 

444 return_packets=False, # type: bool 

445 socket=None, # type: Optional[SuperSocket] 

446 **kargs # type: Any 

447 ): 

448 # type: (...) -> Optional[PacketList] 

449 """Internal function used by send and sendp""" 

450 need_closing = socket is None 

451 iface = resolve_iface(iface or conf.iface) 

452 socket = socket or _func(iface)(iface=iface, **kargs) 

453 results = __gen_send(socket, x, inter=inter, loop=loop, 

454 count=count, verbose=verbose, 

455 realtime=realtime, return_packets=return_packets) 

456 if need_closing: 

457 socket.close() 

458 return results 

459 

460 

461@conf.commands.register 

462def send(x, # type: _PacketIterable 

463 **kargs # type: Any 

464 ): 

465 # type: (...) -> Optional[PacketList] 

466 """ 

467 Send packets at layer 3 

468 

469 This determines the interface (or L2 source to use) based on the routing 

470 table: conf.route / conf.route6 

471 

472 :param x: the packets 

473 :param inter: time (in s) between two packets (default 0) 

474 :param loop: send packet indefinitely (default 0) 

475 :param count: number of packets to send (default None=1) 

476 :param verbose: verbose mode (default None=conf.verb) 

477 :param realtime: check that a packet was sent before sending the next one 

478 :param return_packets: return the sent packets 

479 :param socket: the socket to use (default is conf.L3socket(kargs)) 

480 :param monitor: (not on linux) send in monitor mode 

481 :returns: None 

482 """ 

483 if "iface" in kargs: 

484 # Warn that it isn't used. 

485 warnings.warn( 

486 "'iface' has no effect on L3 I/O send(). For multicast/link-local " 

487 "see https://scapy.readthedocs.io/en/latest/usage.html#multicast", 

488 SyntaxWarning, 

489 ) 

490 del kargs["iface"] 

491 iface, ipv6 = _interface_selection(x) 

492 return _send( 

493 x, 

494 lambda iface: iface.l3socket(ipv6), 

495 iface=iface, 

496 **kargs 

497 ) 

498 

499 

500@conf.commands.register 

501def sendp(x, # type: _PacketIterable 

502 iface=None, # type: Optional[_GlobInterfaceType] 

503 iface_hint=None, # type: Optional[str] 

504 socket=None, # type: Optional[SuperSocket] 

505 **kargs # type: Any 

506 ): 

507 # type: (...) -> Optional[PacketList] 

508 """ 

509 Send packets at layer 2 

510 

511 :param x: the packets 

512 :param inter: time (in s) between two packets (default 0) 

513 :param loop: send packet indefinitely (default 0) 

514 :param count: number of packets to send (default None=1) 

515 :param verbose: verbose mode (default None=conf.verb) 

516 :param realtime: check that a packet was sent before sending the next one 

517 :param return_packets: return the sent packets 

518 :param socket: the socket to use (default is conf.L3socket(kargs)) 

519 :param iface: the interface to send the packets on 

520 :param monitor: (not on linux) send in monitor mode 

521 :returns: None 

522 """ 

523 if iface is None and iface_hint is not None and socket is None: 

524 iface = conf.route.route(iface_hint)[0] 

525 return _send( 

526 x, 

527 lambda iface: iface.l2socket(), 

528 iface=iface, 

529 socket=socket, 

530 **kargs 

531 ) 

532 

533 

534@conf.commands.register 

535def sendpfast(x: _PacketIterable, 

536 pps: Optional[float] = None, 

537 mbps: Optional[float] = None, 

538 realtime: bool = False, 

539 count: Optional[int] = None, 

540 loop: int = 0, 

541 file_cache: bool = False, 

542 iface: Optional[_GlobInterfaceType] = None, 

543 replay_args: Optional[List[str]] = None, 

544 parse_results: bool = False, 

545 ): 

546 # type: (...) -> Optional[Dict[str, Any]] 

547 """Send packets at layer 2 using tcpreplay for performance 

548 

549 :param pps: packets per second 

550 :param mbps: MBits per second 

551 :param realtime: use packet's timestamp, bending time with real-time value 

552 :param loop: send the packet indefinitely (default 0) 

553 :param count: number of packets to send (default None=1) 

554 :param file_cache: cache packets in RAM instead of reading from 

555 disk at each iteration 

556 :param iface: output interface 

557 :param replay_args: List of additional tcpreplay args (List[str]) 

558 :param parse_results: Return a dictionary of information 

559 outputted by tcpreplay (default=False) 

560 :returns: stdout, stderr, command used 

561 """ 

562 if iface is None: 

563 iface = conf.iface 

564 argv = [conf.prog.tcpreplay, "--intf1=%s" % network_name(iface)] 

565 if pps is not None: 

566 argv.append("--pps=%f" % pps) 

567 elif mbps is not None: 

568 argv.append("--mbps=%f" % mbps) 

569 elif realtime is not None: 

570 argv.append("--multiplier=%f" % realtime) 

571 else: 

572 argv.append("--topspeed") 

573 

574 if count: 

575 assert not loop, "Can't use loop and count at the same time in sendpfast" 

576 argv.append("--loop=%i" % count) 

577 elif loop: 

578 argv.append("--loop=0") 

579 if file_cache: 

580 argv.append("--preload-pcap") 

581 

582 # Check for any additional args we didn't cover. 

583 if replay_args is not None: 

584 argv.extend(replay_args) 

585 

586 f = get_temp_file() 

587 argv.append(f) 

588 wrpcap(f, x) 

589 results = None 

590 with ContextManagerSubprocess(conf.prog.tcpreplay): 

591 try: 

592 cmd = subprocess.Popen(argv, stdout=subprocess.PIPE, 

593 stderr=subprocess.PIPE) 

594 cmd.wait() 

595 except KeyboardInterrupt: 

596 if cmd: 

597 cmd.terminate() 

598 log_interactive.info("Interrupted by user") 

599 except Exception: 

600 os.unlink(f) 

601 raise 

602 finally: 

603 stdout, stderr = cmd.communicate() 

604 if stderr: 

605 log_runtime.warning(stderr.decode()) 

606 if parse_results: 

607 results = _parse_tcpreplay_result(stdout, stderr, argv) 

608 elif conf.verb > 2: 

609 log_runtime.info(stdout.decode()) 

610 if os.path.exists(f): 

611 os.unlink(f) 

612 return results 

613 

614 

615def _parse_tcpreplay_result(stdout_b, stderr_b, argv): 

616 # type: (bytes, bytes, List[str]) -> Dict[str, Any] 

617 """ 

618 Parse the output of tcpreplay and modify the results_dict to populate output information. # noqa: E501 

619 Tested with tcpreplay v3.4.4 

620 Tested with tcpreplay v4.1.2 

621 :param stdout: stdout of tcpreplay subprocess call 

622 :param stderr: stderr of tcpreplay subprocess call 

623 :param argv: the command used in the subprocess call 

624 :return: dictionary containing the results 

625 """ 

626 try: 

627 results = {} 

628 stdout = plain_str(stdout_b).lower() 

629 stderr = plain_str(stderr_b).strip().split("\n") 

630 elements = { 

631 "actual": (int, int, float), 

632 "rated": (float, float, float), 

633 "flows": (int, float, int, int), 

634 "attempted": (int,), 

635 "successful": (int,), 

636 "failed": (int,), 

637 "truncated": (int,), 

638 "retried packets (eno": (int,), 

639 "retried packets (eag": (int,), 

640 } 

641 multi = { 

642 "actual": ("packets", "bytes", "time"), 

643 "rated": ("bps", "mbps", "pps"), 

644 "flows": ("flows", "fps", "flow_packets", "non_flow"), 

645 "retried packets (eno": ("retried_enobufs",), 

646 "retried packets (eag": ("retried_eagain",), 

647 } 

648 float_reg = r"([0-9]*\.[0-9]+|[0-9]+)" 

649 int_reg = r"([0-9]+)" 

650 any_reg = r"[^0-9]*" 

651 r_types = {int: int_reg, float: float_reg} 

652 for line in stdout.split("\n"): 

653 line = line.strip() 

654 for elt, _types in elements.items(): 

655 if line.startswith(elt): 

656 regex = any_reg.join([r_types[x] for x in _types]) 

657 matches = re.search(regex, line) 

658 for i, typ in enumerate(_types): 

659 name = multi.get(elt, [elt])[i] 

660 if matches: 

661 results[name] = typ(matches.group(i + 1)) 

662 results["command"] = " ".join(argv) 

663 results["warnings"] = stderr[:-1] 

664 return results 

665 except Exception as parse_exception: 

666 if not conf.interactive: 

667 raise 

668 log_runtime.error("Error parsing output: %s", parse_exception) 

669 return {} 

670 

671 

672def _interface_selection(packet: _PacketIterable) -> Tuple[NetworkInterface, bool]: 

673 """ 

674 Select the network interface according to the layer 3 destination 

675 """ 

676 _iff, src, _ = next(packet.__iter__()).route() 

677 ipv6 = False 

678 if src: 

679 try: 

680 inet_pton(socket.AF_INET6, src) 

681 ipv6 = True 

682 except (ValueError, OSError): 

683 pass 

684 try: 

685 iff = resolve_iface(_iff or conf.iface) 

686 except AttributeError: 

687 iff = None 

688 return iff or conf.iface, ipv6 

689 

690 

691@conf.commands.register 

692def sr(x, # type: _PacketIterable 

693 promisc=None, # type: Optional[bool] 

694 filter=None, # type: Optional[str] 

695 nofilter=0, # type: int 

696 *args, # type: Any 

697 **kargs # type: Any 

698 ): 

699 # type: (...) -> Tuple[SndRcvList, PacketList] 

700 """ 

701 Send and receive packets at layer 3 

702 

703 This determines the interface (or L2 source to use) based on the routing 

704 table: conf.route / conf.route6 

705 """ 

706 if "iface" in kargs: 

707 # Warn that it isn't used. 

708 warnings.warn( 

709 "'iface' has no effect on L3 I/O sr(). For multicast/link-local " 

710 "see https://scapy.readthedocs.io/en/latest/usage.html#multicast", 

711 SyntaxWarning, 

712 ) 

713 del kargs["iface"] 

714 iface, ipv6 = _interface_selection(x) 

715 s = iface.l3socket(ipv6)( 

716 promisc=promisc, filter=filter, 

717 iface=iface, nofilter=nofilter, 

718 ) 

719 result = sndrcv(s, x, *args, **kargs) 

720 s.close() 

721 return result 

722 

723 

724@conf.commands.register 

725def sr1(*args, **kargs): 

726 # type: (*Any, **Any) -> Optional[Packet] 

727 """ 

728 Send packets at layer 3 and return only the first answer 

729 

730 This determines the interface (or L2 source to use) based on the routing 

731 table: conf.route / conf.route6 

732 """ 

733 if "iface" in kargs: 

734 # Warn that it isn't used. 

735 warnings.warn( 

736 "'iface' has no effect on L3 I/O sr1(). For multicast/link-local " 

737 "see https://scapy.readthedocs.io/en/latest/usage.html#multicast", 

738 SyntaxWarning, 

739 ) 

740 del kargs["iface"] 

741 ans, _ = sr(*args, **kargs) 

742 if ans: 

743 return cast(Packet, ans[0][1]) 

744 return None 

745 

746 

747@conf.commands.register 

748def srp(x, # type: _PacketIterable 

749 promisc=None, # type: Optional[bool] 

750 iface=None, # type: Optional[_GlobInterfaceType] 

751 iface_hint=None, # type: Optional[str] 

752 filter=None, # type: Optional[str] 

753 nofilter=0, # type: int 

754 type=ETH_P_ALL, # type: int 

755 *args, # type: Any 

756 **kargs # type: Any 

757 ): 

758 # type: (...) -> Tuple[SndRcvList, PacketList] 

759 """ 

760 Send and receive packets at layer 2 

761 """ 

762 if iface is None and iface_hint is not None: 

763 iface = conf.route.route(iface_hint)[0] 

764 iface = resolve_iface(iface or conf.iface) 

765 s = iface.l2socket()(promisc=promisc, iface=iface, 

766 filter=filter, nofilter=nofilter, type=type) 

767 result = sndrcv(s, x, *args, **kargs) 

768 s.close() 

769 return result 

770 

771 

772@conf.commands.register 

773def srp1(*args, **kargs): 

774 # type: (*Any, **Any) -> Optional[Packet] 

775 """ 

776 Send and receive packets at layer 2 and return only the first answer 

777 """ 

778 ans, _ = srp(*args, **kargs) 

779 if len(ans) > 0: 

780 return cast(Packet, ans[0][1]) 

781 return None 

782 

783 

784# Append doc 

785for sr_func in [srp, srp1, sr, sr1]: 

786 if sr_func.__doc__ is not None: 

787 sr_func.__doc__ += _DOC_SNDRCV_PARAMS 

788 

789 

790# SEND/RECV LOOP METHODS 

791 

792 

793def __sr_loop(srfunc, # type: Callable[..., Tuple[SndRcvList, PacketList]] 

794 pkts, # type: _PacketIterable 

795 prn=lambda x: x[1].summary(), # type: Optional[Callable[[QueryAnswer], Any]] # noqa: E501 

796 prnfail=lambda x: x.summary(), # type: Optional[Callable[[Packet], Any]] 

797 inter=1, # type: int 

798 timeout=None, # type: Optional[int] 

799 count=None, # type: Optional[int] 

800 verbose=None, # type: Optional[int] 

801 store=1, # type: int 

802 *args, # type: Any 

803 **kargs # type: Any 

804 ): 

805 # type: (...) -> Tuple[SndRcvList, PacketList] 

806 n = 0 

807 r = 0 

808 ct = conf.color_theme 

809 if verbose is None: 

810 verbose = conf.verb 

811 parity = 0 

812 ans = [] # type: List[QueryAnswer] 

813 unans = [] # type: List[Packet] 

814 if timeout is None: 

815 timeout = min(2 * inter, 5) 

816 try: 

817 while True: 

818 parity ^= 1 

819 col = [ct.even, ct.odd][parity] 

820 if count is not None: 

821 if count == 0: 

822 break 

823 count -= 1 

824 start = time.monotonic() 

825 if verbose > 1: 

826 print("\rsend...\r", end=' ') 

827 res = srfunc(pkts, timeout=timeout, verbose=0, chainCC=True, *args, **kargs) # noqa: E501 

828 n += len(res[0]) + len(res[1]) 

829 r += len(res[0]) 

830 if verbose > 1 and prn and len(res[0]) > 0: 

831 msg = "RECV %i:" % len(res[0]) 

832 print("\r" + ct.success(msg), end=' ') 

833 for rcv in res[0]: 

834 print(col(prn(rcv))) 

835 print(" " * len(msg), end=' ') 

836 if verbose > 1 and prnfail and len(res[1]) > 0: 

837 msg = "fail %i:" % len(res[1]) 

838 print("\r" + ct.fail(msg), end=' ') 

839 for fail in res[1]: 

840 print(col(prnfail(fail))) 

841 print(" " * len(msg), end=' ') 

842 if verbose > 1 and not (prn or prnfail): 

843 print("recv:%i fail:%i" % tuple( 

844 map(len, res[:2]) # type: ignore 

845 )) 

846 if verbose == 1: 

847 if res[0]: 

848 os.write(1, b"*") 

849 if res[1]: 

850 os.write(1, b".") 

851 if store: 

852 ans += res[0] 

853 unans += res[1] 

854 end = time.monotonic() 

855 if end - start < inter: 

856 time.sleep(inter + start - end) 

857 except KeyboardInterrupt: 

858 pass 

859 

860 if verbose and n > 0: 

861 print(ct.normal("\nSent %i packets, received %i packets. %3.1f%% hits." % (n, r, 100.0 * r / n))) # noqa: E501 

862 return SndRcvList(ans), PacketList(unans) 

863 

864 

865@conf.commands.register 

866def srloop(pkts, # type: _PacketIterable 

867 *args, # type: Any 

868 **kargs # type: Any 

869 ): 

870 # type: (...) -> Tuple[SndRcvList, PacketList] 

871 """ 

872 Send a packet at layer 3 in loop and print the answer each time 

873 srloop(pkts, [prn], [inter], [count], ...) --> None 

874 """ 

875 return __sr_loop(sr, pkts, *args, **kargs) 

876 

877 

878@conf.commands.register 

879def srploop(pkts, # type: _PacketIterable 

880 *args, # type: Any 

881 **kargs # type: Any 

882 ): 

883 # type: (...) -> Tuple[SndRcvList, PacketList] 

884 """ 

885 Send a packet at layer 2 in loop and print the answer each time 

886 srloop(pkts, [prn], [inter], [count], ...) --> None 

887 """ 

888 return __sr_loop(srp, pkts, *args, **kargs) 

889 

890# SEND/RECV FLOOD METHODS 

891 

892 

893class _FloodGenerator(object): 

894 def __init__(self, tobesent, maxretries): 

895 # type: (_PacketIterable, Optional[int]) -> None 

896 self.tobesent = tobesent 

897 self.maxretries = maxretries 

898 self.stopevent = Event() 

899 self.iterlen = 0 

900 

901 def __iter__(self): 

902 # type: () -> Iterator[Packet] 

903 i = 0 

904 while True: 

905 i += 1 

906 j = 0 

907 if self.maxretries and i >= self.maxretries: 

908 return 

909 for p in self.tobesent: 

910 if self.stopevent.is_set(): 

911 return 

912 j += 1 

913 yield p 

914 if self.iterlen == 0: 

915 self.iterlen = j 

916 

917 @property 

918 def sent_time(self): 

919 # type: () -> Union[EDecimal, float, None] 

920 return cast(Packet, self.tobesent).sent_time 

921 

922 @sent_time.setter 

923 def sent_time(self, val): 

924 # type: (Union[EDecimal, float, None]) -> None 

925 cast(Packet, self.tobesent).sent_time = val 

926 

927 def stop(self): 

928 # type: () -> None 

929 self.stopevent.set() 

930 

931 

932def sndrcvflood(pks, # type: SuperSocket 

933 pkt, # type: _PacketIterable 

934 inter=0, # type: int 

935 maxretries=None, # type: Optional[int] 

936 verbose=None, # type: Optional[int] 

937 chainCC=False, # type: bool 

938 timeout=None # type: Optional[int] 

939 ): 

940 # type: (...) -> Tuple[SndRcvList, PacketList] 

941 """sndrcv equivalent for flooding.""" 

942 

943 flood_gen = _FloodGenerator(pkt, maxretries) 

944 return sndrcv( 

945 pks, flood_gen, 

946 inter=inter, verbose=verbose, 

947 chainCC=chainCC, timeout=timeout, 

948 _flood=flood_gen 

949 ) 

950 

951 

952@conf.commands.register 

953def srflood(x, # type: _PacketIterable 

954 promisc=None, # type: Optional[bool] 

955 filter=None, # type: Optional[str] 

956 iface=None, # type: Optional[_GlobInterfaceType] 

957 nofilter=None, # type: Optional[bool] 

958 *args, # type: Any 

959 **kargs # type: Any 

960 ): 

961 # type: (...) -> Tuple[SndRcvList, PacketList] 

962 """Flood and receive packets at layer 3 

963 

964 This determines the interface (or L2 source to use) based on the routing 

965 table: conf.route / conf.route6 

966 

967 :param prn: function applied to packets received 

968 :param unique: only consider packets whose print 

969 :param nofilter: put 1 to avoid use of BPF filters 

970 :param filter: provide a BPF filter 

971 """ 

972 if "iface" in kargs: 

973 # Warn that it isn't used. 

974 warnings.warn( 

975 "'iface' has no effect on L3 I/O srflood(). For multicast/link-local " 

976 "see https://scapy.readthedocs.io/en/latest/usage.html#multicast", 

977 SyntaxWarning, 

978 ) 

979 del kargs["iface"] 

980 iface, ipv6 = _interface_selection(x) 

981 s = iface.l3socket(ipv6)( 

982 promisc=promisc, filter=filter, 

983 iface=iface, nofilter=nofilter, 

984 ) 

985 r = sndrcvflood(s, x, *args, **kargs) 

986 s.close() 

987 return r 

988 

989 

990@conf.commands.register 

991def sr1flood(x, # type: _PacketIterable 

992 promisc=None, # type: Optional[bool] 

993 filter=None, # type: Optional[str] 

994 nofilter=0, # type: int 

995 *args, # type: Any 

996 **kargs # type: Any 

997 ): 

998 # type: (...) -> Optional[Packet] 

999 """Flood and receive packets at layer 3 and return only the first answer 

1000 

1001 This determines the interface (or L2 source to use) based on the routing 

1002 table: conf.route / conf.route6 

1003 

1004 :param prn: function applied to packets received 

1005 :param verbose: set verbosity level 

1006 :param nofilter: put 1 to avoid use of BPF filters 

1007 :param filter: provide a BPF filter 

1008 :param iface: listen answers only on the given interface 

1009 """ 

1010 if "iface" in kargs: 

1011 # Warn that it isn't used. 

1012 warnings.warn( 

1013 "'iface' has no effect on L3 I/O sr1flood(). For multicast/link-local " 

1014 "see https://scapy.readthedocs.io/en/latest/usage.html#multicast", 

1015 SyntaxWarning, 

1016 ) 

1017 del kargs["iface"] 

1018 iface, ipv6 = _interface_selection(x) 

1019 s = iface.l3socket(ipv6)( 

1020 promisc=promisc, filter=filter, 

1021 nofilter=nofilter, iface=iface, 

1022 ) 

1023 ans, _ = sndrcvflood(s, x, *args, **kargs) 

1024 s.close() 

1025 if len(ans) > 0: 

1026 return cast(Packet, ans[0][1]) 

1027 return None 

1028 

1029 

1030@conf.commands.register 

1031def srpflood(x, # type: _PacketIterable 

1032 promisc=None, # type: Optional[bool] 

1033 filter=None, # type: Optional[str] 

1034 iface=None, # type: Optional[_GlobInterfaceType] 

1035 iface_hint=None, # type: Optional[str] 

1036 nofilter=None, # type: Optional[bool] 

1037 *args, # type: Any 

1038 **kargs # type: Any 

1039 ): 

1040 # type: (...) -> Tuple[SndRcvList, PacketList] 

1041 """Flood and receive packets at layer 2 

1042 

1043 :param prn: function applied to packets received 

1044 :param unique: only consider packets whose print 

1045 :param nofilter: put 1 to avoid use of BPF filters 

1046 :param filter: provide a BPF filter 

1047 :param iface: listen answers only on the given interface 

1048 """ 

1049 if iface is None and iface_hint is not None: 

1050 iface = conf.route.route(iface_hint)[0] 

1051 iface = resolve_iface(iface or conf.iface) 

1052 s = iface.l2socket()(promisc=promisc, filter=filter, iface=iface, nofilter=nofilter) # noqa: E501 

1053 r = sndrcvflood(s, x, *args, **kargs) 

1054 s.close() 

1055 return r 

1056 

1057 

1058@conf.commands.register 

1059def srp1flood(x, # type: _PacketIterable 

1060 promisc=None, # type: Optional[bool] 

1061 filter=None, # type: Optional[str] 

1062 iface=None, # type: Optional[_GlobInterfaceType] 

1063 nofilter=0, # type: int 

1064 *args, # type: Any 

1065 **kargs # type: Any 

1066 ): 

1067 # type: (...) -> Optional[Packet] 

1068 """Flood and receive packets at layer 2 and return only the first answer 

1069 

1070 :param prn: function applied to packets received 

1071 :param verbose: set verbosity level 

1072 :param nofilter: put 1 to avoid use of BPF filters 

1073 :param filter: provide a BPF filter 

1074 :param iface: listen answers only on the given interface 

1075 """ 

1076 iface = resolve_iface(iface or conf.iface) 

1077 s = iface.l2socket()(promisc=promisc, filter=filter, nofilter=nofilter, iface=iface) # noqa: E501 

1078 ans, _ = sndrcvflood(s, x, *args, **kargs) 

1079 s.close() 

1080 if len(ans) > 0: 

1081 return cast(Packet, ans[0][1]) 

1082 return None 

1083 

1084# SNIFF METHODS 

1085 

1086 

1087class AsyncSniffer(object): 

1088 """ 

1089 Sniff packets and return a list of packets. 

1090 

1091 Args: 

1092 count: number of packets to capture. 0 means infinity. 

1093 store: whether to store sniffed packets or discard them 

1094 prn: function to apply to each packet. If something is returned, it 

1095 is displayed. 

1096 --Ex: prn = lambda x: x.summary() 

1097 session: a session = a flow decoder used to handle stream of packets. 

1098 --Ex: session=TCPSession 

1099 See below for more details. 

1100 filter: BPF filter to apply. 

1101 lfilter: Python function applied to each packet to determine if 

1102 further action may be done. 

1103 --Ex: lfilter = lambda x: x.haslayer(Padding) 

1104 offline: PCAP file (or list of PCAP files) to read packets from, 

1105 instead of sniffing them 

1106 quiet: when set to True, the process stderr is discarded 

1107 (default: False). 

1108 timeout: stop sniffing after a given time (default: None). 

1109 L2socket: use the provided L2socket (default: use conf.L2listen). 

1110 opened_socket: provide an object (or a list of objects) ready to use 

1111 .recv() on. 

1112 stop_filter: Python function applied to each packet to determine if 

1113 we have to stop the capture after this packet. 

1114 --Ex: stop_filter = lambda x: x.haslayer(TCP) 

1115 iface: interface or list of interfaces (default: None for sniffing 

1116 on the default interface). 

1117 monitor: use monitor mode. May not be available on all OS 

1118 started_callback: called as soon as the sniffer starts sniffing 

1119 (default: None). 

1120 

1121 The iface, offline and opened_socket parameters can be either an 

1122 element, a list of elements, or a dict object mapping an element to a 

1123 label (see examples below). 

1124 

1125 For more information about the session argument, see 

1126 https://scapy.rtfd.io/en/latest/usage.html#advanced-sniffing-sniffing-sessions 

1127 

1128 Examples: synchronous 

1129 >>> sniff(filter="arp") 

1130 >>> sniff(filter="tcp", 

1131 ... session=IPSession, # defragment on-the-flow 

1132 ... prn=lambda x: x.summary()) 

1133 >>> sniff(lfilter=lambda pkt: ARP in pkt) 

1134 >>> sniff(iface="eth0", prn=Packet.summary) 

1135 >>> sniff(iface=["eth0", "mon0"], 

1136 ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, 

1137 ... pkt.summary())) 

1138 >>> sniff(iface={"eth0": "Ethernet", "mon0": "Wifi"}, 

1139 ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, 

1140 ... pkt.summary())) 

1141 

1142 Examples: asynchronous 

1143 >>> t = AsyncSniffer(iface="enp0s3") 

1144 >>> t.start() 

1145 >>> time.sleep(1) 

1146 >>> print("nice weather today") 

1147 >>> t.stop() 

1148 """ 

1149 

1150 def __init__(self, *args, **kwargs): 

1151 # type: (*Any, **Any) -> None 

1152 # Store keyword arguments 

1153 self.args = args 

1154 self.kwargs = kwargs 

1155 self.running = False 

1156 self.thread = None # type: Optional[Thread] 

1157 self.results = None # type: Optional[PacketList] 

1158 self.exception = None # type: Optional[Exception] 

1159 self.stop_cb = lambda: None # type: Callable[[], None] 

1160 

1161 def _setup_thread(self): 

1162 # type: () -> None 

1163 def _run_catch(self=self, *args, **kwargs): 

1164 # type: (Any, *Any, **Any) -> None 

1165 try: 

1166 self._run(*args, **kwargs) 

1167 except Exception as ex: 

1168 self.exception = ex 

1169 # Prepare sniffing thread 

1170 self.thread = Thread( 

1171 target=_run_catch, 

1172 args=self.args, 

1173 kwargs=self.kwargs, 

1174 name="AsyncSniffer" 

1175 ) 

1176 self.thread.daemon = True 

1177 

1178 def _run(self, 

1179 count=0, # type: int 

1180 store=True, # type: bool 

1181 offline=None, # type: Any 

1182 quiet=False, # type: bool 

1183 prn=None, # type: Optional[Callable[[Packet], Any]] 

1184 lfilter=None, # type: Optional[Callable[[Packet], bool]] 

1185 L2socket=None, # type: Optional[Type[SuperSocket]] 

1186 timeout=None, # type: Optional[int] 

1187 opened_socket=None, # type: Optional[SuperSocket] 

1188 stop_filter=None, # type: Optional[Callable[[Packet], bool]] 

1189 iface=None, # type: Optional[_GlobInterfaceType] 

1190 started_callback=None, # type: Optional[Callable[[], Any]] 

1191 session=None, # type: Optional[_GlobSessionType] 

1192 chainCC=False, # type: bool 

1193 **karg # type: Any 

1194 ): 

1195 # type: (...) -> None 

1196 self.running = True 

1197 self.count = 0 

1198 lst = [] 

1199 # Start main thread 

1200 # instantiate session 

1201 if not isinstance(session, DefaultSession): 

1202 session = session or DefaultSession 

1203 session = session() 

1204 # sniff_sockets follows: {socket: label} 

1205 sniff_sockets = {} # type: Dict[SuperSocket, _GlobInterfaceType] 

1206 if opened_socket is not None: 

1207 if isinstance(opened_socket, list): 

1208 sniff_sockets.update( 

1209 (s, "socket%d" % i) 

1210 for i, s in enumerate(opened_socket) 

1211 ) 

1212 elif isinstance(opened_socket, dict): 

1213 sniff_sockets.update( 

1214 (s, label) 

1215 for s, label in opened_socket.items() 

1216 ) 

1217 else: 

1218 sniff_sockets[opened_socket] = "socket0" 

1219 if offline is not None: 

1220 flt = karg.get('filter') 

1221 

1222 if isinstance(offline, str): 

1223 # Single file 

1224 offline = [offline] 

1225 if isinstance(offline, list) and \ 

1226 all(isinstance(elt, str) for elt in offline): 

1227 # List of files 

1228 sniff_sockets.update((PcapReader( # type: ignore 

1229 fname if flt is None else 

1230 tcpdump(fname, 

1231 args=["-w", "-"], 

1232 flt=flt, 

1233 getfd=True, 

1234 quiet=quiet) 

1235 ), fname) for fname in offline) 

1236 elif isinstance(offline, dict): 

1237 # Dict of files 

1238 sniff_sockets.update((PcapReader( # type: ignore 

1239 fname if flt is None else 

1240 tcpdump(fname, 

1241 args=["-w", "-"], 

1242 flt=flt, 

1243 getfd=True, 

1244 quiet=quiet) 

1245 ), label) for fname, label in offline.items()) 

1246 elif isinstance(offline, (Packet, PacketList, list)): 

1247 # Iterables (list of packets, PacketList..) 

1248 offline = IterSocket(offline) 

1249 sniff_sockets[offline if flt is None else PcapReader( 

1250 tcpdump(offline, 

1251 args=["-w", "-"], 

1252 flt=flt, 

1253 getfd=True, 

1254 quiet=quiet) 

1255 )] = offline 

1256 else: 

1257 # Other (file descriptors...) 

1258 sniff_sockets[PcapReader( # type: ignore 

1259 offline if flt is None else 

1260 tcpdump(offline, 

1261 args=["-w", "-"], 

1262 flt=flt, 

1263 getfd=True, 

1264 quiet=quiet) 

1265 )] = offline 

1266 if not sniff_sockets or iface is not None: 

1267 # The _RL2 function resolves the L2socket of an iface 

1268 _RL2 = lambda i: L2socket or resolve_iface(i).l2listen() # type: Callable[[_GlobInterfaceType], Callable[..., SuperSocket]] # noqa: E501 

1269 if isinstance(iface, list): 

1270 sniff_sockets.update( 

1271 (_RL2(ifname)(type=ETH_P_ALL, iface=ifname, **karg), 

1272 ifname) 

1273 for ifname in iface 

1274 ) 

1275 elif isinstance(iface, dict): 

1276 sniff_sockets.update( 

1277 (_RL2(ifname)(type=ETH_P_ALL, iface=ifname, **karg), 

1278 iflabel) 

1279 for ifname, iflabel in iface.items() 

1280 ) 

1281 else: 

1282 iface = iface or conf.iface 

1283 sniff_sockets[_RL2(iface)(type=ETH_P_ALL, iface=iface, 

1284 **karg)] = iface 

1285 

1286 # Get select information from the sockets 

1287 _main_socket = next(iter(sniff_sockets)) 

1288 select_func = _main_socket.select 

1289 nonblocking_socket = getattr(_main_socket, "nonblocking_socket", False) 

1290 # We check that all sockets use the same select(), or raise a warning 

1291 if not all(select_func == sock.select for sock in sniff_sockets): 

1292 warning("Warning: inconsistent socket types ! " 

1293 "The used select function " 

1294 "will be the one of the first socket") 

1295 

1296 close_pipe = None # type: Optional[ObjectPipe[None]] 

1297 if not nonblocking_socket: 

1298 # select is blocking: Add special control socket 

1299 from scapy.automaton import ObjectPipe 

1300 close_pipe = ObjectPipe[None]("control_socket") 

1301 sniff_sockets[close_pipe] = "control_socket" # type: ignore 

1302 

1303 def stop_cb(): 

1304 # type: () -> None 

1305 if self.running and close_pipe: 

1306 close_pipe.send(None) 

1307 self.continue_sniff = False 

1308 self.stop_cb = stop_cb 

1309 else: 

1310 # select is non blocking 

1311 def stop_cb(): 

1312 # type: () -> None 

1313 self.continue_sniff = False 

1314 self.stop_cb = stop_cb 

1315 

1316 try: 

1317 if started_callback: 

1318 started_callback() 

1319 self.continue_sniff = True 

1320 

1321 # Start timeout 

1322 if timeout is not None: 

1323 stoptime = time.monotonic() + timeout 

1324 remain = None 

1325 

1326 while sniff_sockets and self.continue_sniff: 

1327 if timeout is not None: 

1328 remain = stoptime - time.monotonic() 

1329 if remain <= 0: 

1330 break 

1331 sockets = select_func(list(sniff_sockets.keys()), remain) 

1332 dead_sockets = [] 

1333 for s in sockets: 

1334 if s is close_pipe: # type: ignore 

1335 break 

1336 # The session object is passed the socket to call recv() on, 

1337 # and may perform additional processing (ip defrag, etc.) 

1338 try: 

1339 packets = session.recv(s) 

1340 # A session can return multiple objects 

1341 for p in packets: 

1342 if lfilter and not lfilter(p): 

1343 continue 

1344 p.sniffed_on = sniff_sockets.get(s, None) 

1345 # post-processing 

1346 self.count += 1 

1347 if store: 

1348 lst.append(p) 

1349 if prn: 

1350 result = prn(p) 

1351 if result is not None: 

1352 print(result) 

1353 # check 

1354 if (stop_filter and stop_filter(p)) or \ 

1355 (0 < count <= self.count): 

1356 self.continue_sniff = False 

1357 break 

1358 except EOFError: 

1359 # End of stream 

1360 try: 

1361 s.close() 

1362 except Exception: 

1363 pass 

1364 dead_sockets.append(s) 

1365 continue 

1366 except Exception as ex: 

1367 msg = " It was closed." 

1368 try: 

1369 # Make sure it's closed 

1370 s.close() 

1371 except Exception as ex2: 

1372 msg = " close() failed with '%s'" % ex2 

1373 warning( 

1374 "Socket %s failed with '%s'." % (s, ex) + msg 

1375 ) 

1376 dead_sockets.append(s) 

1377 if conf.debug_dissector >= 2: 

1378 raise 

1379 continue 

1380 # Removed dead sockets 

1381 for s in dead_sockets: 

1382 del sniff_sockets[s] 

1383 if len(sniff_sockets) == 1 and \ 

1384 close_pipe in sniff_sockets: # type: ignore 

1385 # Only the close_pipe left 

1386 del sniff_sockets[close_pipe] # type: ignore 

1387 except KeyboardInterrupt: 

1388 if chainCC: 

1389 raise 

1390 self.running = False 

1391 if opened_socket is None: 

1392 for s in sniff_sockets: 

1393 s.close() 

1394 elif close_pipe: 

1395 close_pipe.close() 

1396 self.results = PacketList(lst, "Sniffed") 

1397 

1398 def start(self): 

1399 # type: () -> None 

1400 """Starts AsyncSniffer in async mode""" 

1401 self._setup_thread() 

1402 if self.thread: 

1403 self.thread.start() 

1404 

1405 def stop(self, join=True): 

1406 # type: (bool) -> Optional[PacketList] 

1407 """Stops AsyncSniffer if not in async mode""" 

1408 if self.running: 

1409 self.stop_cb() 

1410 if not hasattr(self, "continue_sniff"): 

1411 # Never started -> is there an exception? 

1412 if self.exception is not None: 

1413 raise self.exception 

1414 return None 

1415 if self.continue_sniff: 

1416 raise Scapy_Exception( 

1417 "Unsupported (offline or unsupported socket)" 

1418 ) 

1419 if join: 

1420 self.join() 

1421 return self.results 

1422 return None 

1423 else: 

1424 raise Scapy_Exception("Not running ! (check .running attr)") 

1425 

1426 def join(self, *args, **kwargs): 

1427 # type: (*Any, **Any) -> None 

1428 if self.thread: 

1429 self.thread.join(*args, **kwargs) 

1430 if self.exception is not None: 

1431 raise self.exception 

1432 

1433 

1434@conf.commands.register 

1435def sniff(*args, **kwargs): 

1436 # type: (*Any, **Any) -> PacketList 

1437 sniffer = AsyncSniffer() 

1438 sniffer._run(*args, **kwargs) 

1439 return cast(PacketList, sniffer.results) 

1440 

1441 

1442sniff.__doc__ = AsyncSniffer.__doc__ 

1443 

1444 

1445@conf.commands.register 

1446def bridge_and_sniff(if1, # type: _GlobInterfaceType 

1447 if2, # type: _GlobInterfaceType 

1448 xfrm12=None, # type: Optional[Callable[[Packet], Union[Packet, bool]]] # noqa: E501 

1449 xfrm21=None, # type: Optional[Callable[[Packet], Union[Packet, bool]]] # noqa: E501 

1450 prn=None, # type: Optional[Callable[[Packet], Any]] 

1451 L2socket=None, # type: Optional[Type[SuperSocket]] 

1452 *args, # type: Any 

1453 **kargs # type: Any 

1454 ): 

1455 # type: (...) -> PacketList 

1456 """Forward traffic between interfaces if1 and if2, sniff and return 

1457 the exchanged packets. 

1458 

1459 :param if1: the interfaces to use (interface names or opened sockets). 

1460 :param if2: 

1461 :param xfrm12: a function to call when forwarding a packet from if1 to 

1462 if2. If it returns True, the packet is forwarded as it. If it 

1463 returns False or None, the packet is discarded. If it returns a 

1464 packet, this packet is forwarded instead of the original packet 

1465 one. 

1466 :param xfrm21: same as xfrm12 for packets forwarded from if2 to if1. 

1467 

1468 The other arguments are the same than for the function sniff(), 

1469 except for offline, opened_socket and iface that are ignored. 

1470 See help(sniff) for more. 

1471 """ 

1472 for arg in ['opened_socket', 'offline', 'iface']: 

1473 if arg in kargs: 

1474 log_runtime.warning("Argument %s cannot be used in " 

1475 "bridge_and_sniff() -- ignoring it.", arg) 

1476 del kargs[arg] 

1477 

1478 def _init_socket(iface, # type: _GlobInterfaceType 

1479 count, # type: int 

1480 L2socket=L2socket # type: Optional[Type[SuperSocket]] 

1481 ): 

1482 # type: (...) -> Tuple[SuperSocket, _GlobInterfaceType] 

1483 if isinstance(iface, SuperSocket): 

1484 return iface, "iface%d" % count 

1485 else: 

1486 if not L2socket: 

1487 iface = resolve_iface(iface or conf.iface) 

1488 L2socket = iface.l2socket() 

1489 return L2socket(iface=iface), iface 

1490 sckt1, if1 = _init_socket(if1, 1) 

1491 sckt2, if2 = _init_socket(if2, 2) 

1492 peers = {if1: sckt2, if2: sckt1} 

1493 xfrms = {} 

1494 if xfrm12 is not None: 

1495 xfrms[if1] = xfrm12 

1496 if xfrm21 is not None: 

1497 xfrms[if2] = xfrm21 

1498 

1499 def prn_send(pkt): 

1500 # type: (Packet) -> None 

1501 try: 

1502 sendsock = peers[pkt.sniffed_on or ""] 

1503 except KeyError: 

1504 return 

1505 if pkt.sniffed_on in xfrms: 

1506 try: 

1507 _newpkt = xfrms[pkt.sniffed_on](pkt) 

1508 except Exception: 

1509 log_runtime.warning( 

1510 'Exception in transformation function for packet [%s] ' 

1511 'received on %s -- dropping', 

1512 pkt.summary(), pkt.sniffed_on, exc_info=True 

1513 ) 

1514 return 

1515 else: 

1516 if isinstance(_newpkt, bool): 

1517 if not _newpkt: 

1518 return 

1519 newpkt = pkt 

1520 else: 

1521 newpkt = _newpkt 

1522 else: 

1523 newpkt = pkt 

1524 try: 

1525 sendsock.send(newpkt) 

1526 except Exception: 

1527 log_runtime.warning('Cannot forward packet [%s] received on %s', 

1528 pkt.summary(), pkt.sniffed_on, exc_info=True) 

1529 if prn is None: 

1530 prn = prn_send 

1531 else: 

1532 prn_orig = prn 

1533 

1534 def prn(pkt): 

1535 # type: (Packet) -> Any 

1536 prn_send(pkt) 

1537 return prn_orig(pkt) 

1538 

1539 return sniff(opened_socket={sckt1: if1, sckt2: if2}, prn=prn, 

1540 *args, **kargs) 

1541 

1542 

1543@conf.commands.register 

1544def tshark(*args, **kargs): 

1545 # type: (Any, Any) -> None 

1546 """Sniff packets and print them calling pkt.summary(). 

1547 This tries to replicate what text-wireshark (tshark) would look like""" 

1548 

1549 if 'iface' in kargs: 

1550 iface = kargs.get('iface') 

1551 elif 'opened_socket' in kargs: 

1552 iface = cast(SuperSocket, kargs.get('opened_socket')).iface 

1553 else: 

1554 iface = conf.iface 

1555 print("Capturing on '%s'" % iface) 

1556 

1557 # This should be a nonlocal variable, using a mutable object 

1558 # for Python 2 compatibility 

1559 i = [0] 

1560 

1561 def _cb(pkt): 

1562 # type: (Packet) -> None 

1563 print("%5d\t%s" % (i[0], pkt.summary())) 

1564 i[0] += 1 

1565 

1566 sniff(prn=_cb, store=False, *args, **kargs) 

1567 print("\n%d packet%s captured" % (i[0], 's' if i[0] > 1 else ''))