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

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

724 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 

17 

18from scapy.compat import plain_str 

19from scapy.data import ETH_P_ALL 

20from scapy.config import conf 

21from scapy.error import warning 

22from scapy.interfaces import ( 

23 network_name, 

24 resolve_iface, 

25 NetworkInterface, 

26) 

27from scapy.packet import Packet 

28from scapy.pton_ntop import inet_pton 

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

30 ContextManagerSubprocess, PcapReader, EDecimal 

31from scapy.plist import ( 

32 PacketList, 

33 QueryAnswer, 

34 SndRcvList, 

35) 

36from scapy.error import log_runtime, log_interactive, Scapy_Exception 

37from scapy.base_classes import Gen, SetGen, ScopedIP 

38from scapy.sessions import DefaultSession 

39from scapy.supersocket import SuperSocket, IterSocket 

40 

41# Typing imports 

42from typing import ( 

43 Any, 

44 Callable, 

45 Dict, 

46 Iterator, 

47 List, 

48 Optional, 

49 Tuple, 

50 Type, 

51 Union, 

52 cast 

53) 

54from scapy.interfaces import _GlobInterfaceType 

55from scapy.plist import _PacketIterable 

56 

57if conf.route is None: 

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

59 import scapy.route # noqa: F401 

60 

61################# 

62# Debug class # 

63################# 

64 

65 

66class debug: 

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

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

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

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

71 

72 

73#################### 

74# Send / Receive # 

75#################### 

76 

77_DOC_SNDRCV_PARAMS = """ 

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

79 :param pkt: the packet to send 

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

81 :param inter: delay between two packets during sending 

82 :param verbose: set verbosity level 

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

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

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

86 are answered 

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

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

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

90 packets will still be sent through pks 

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

92 Automatically enabled when a generator is passed as the packet 

93 :param _flood: 

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

95 Defaults to True. 

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

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

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

99 we have to stop the capture after this packet. 

100 """ 

101 

102 

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

104 

105 

106class SndRcvHandler(object): 

107 """ 

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

109 Do not use directly. 

110 

111 This matches the requests and answers. 

112 

113 Notes:: 

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

115 a good idea to use threaded mode. 

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

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

118 """ 

119 def __init__(self, 

120 pks, # type: SuperSocket 

121 pkt, # type: _PacketIterable 

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

123 inter=0, # type: int 

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

125 chainCC=False, # type: bool 

126 retry=0, # type: int 

127 multi=False, # type: bool 

128 first=False, # type: bool 

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

130 prebuild=False, # type: bool 

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

132 threaded=True, # type: bool 

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

134 chainEX=False, # type: bool 

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

136 **send_kwargs, # type: Any 

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 self.send_kwargs = send_kwargs 

166 # Instantiate packet holders 

167 if prebuild and not self._flood: 

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

169 else: 

170 self.tobesent = pkt 

171 

172 if retry < 0: 

173 autostop = retry = -retry 

174 else: 

175 autostop = 0 

176 

177 if timeout is not None and timeout < 0: 

178 self.timeout = None 

179 

180 while retry >= 0: 

181 self.breakout.clear() 

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

183 

184 if threaded or self._flood: 

185 # Send packets in thread. 

186 snd_thread = Thread( 

187 target=self._sndrcv_snd 

188 ) 

189 snd_thread.daemon = True 

190 

191 # Start routine with callback 

192 interrupted = None 

193 try: 

194 self._sndrcv_rcv(snd_thread.start) 

195 except KeyboardInterrupt as ex: 

196 interrupted = ex 

197 

198 self.breakout.set() 

199 

200 # Ended. Let's close gracefully 

201 if self._flood: 

202 # Flood: stop send thread 

203 self._flood.stop() 

204 snd_thread.join() 

205 

206 if interrupted and self.chainCC: 

207 raise interrupted 

208 else: 

209 # Send packets, then receive. 

210 try: 

211 self._sndrcv_rcv(self._sndrcv_snd) 

212 except KeyboardInterrupt: 

213 if self.chainCC: 

214 raise 

215 

216 if multi: 

217 remain = [ 

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

219 if not hasattr(p, '_answered') 

220 ] 

221 else: 

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

223 

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

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

226 retry = autostop 

227 

228 self.tobesent = remain 

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

230 break 

231 retry -= 1 

232 

233 if conf.debug_match: 

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

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

236 

237 # Clean the ans list to delete the field _answered 

238 if multi: 

239 for snd, _ in self.ans: 

240 if hasattr(snd, '_answered'): 

241 del snd._answered 

242 

243 if verbose: 

244 print( 

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

246 "remaining %i packets" % ( 

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

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

249 ) 

250 ) 

251 

252 self.ans_result = SndRcvList(self.ans) 

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

254 

255 def results(self): 

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

257 return self.ans_result, self.unans_result 

258 

259 def _stop_sniffer_if_done(self) -> None: 

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

261 if ( 

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

263 self.first and self.noans 

264 ): 

265 if self.sniffer and self.sniffer.running: 

266 self.sniffer.stop(join=False) 

267 

268 def _sndrcv_snd(self): 

269 # type: () -> None 

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

271 i = 0 

272 p = None 

273 try: 

274 if self.verbose: 

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

276 for p in self.tobesent: 

277 # Populate the dictionary of _sndrcv_rcv 

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

279 # has not been sent 

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

281 # Send packet 

282 self.pks.send(p, **self.send_kwargs) 

283 time.sleep(self.inter) 

284 if self.breakout.is_set(): 

285 break 

286 i += 1 

287 if self.verbose: 

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

289 except SystemExit: 

290 pass 

291 except Exception: 

292 if self.chainEX: 

293 raise 

294 else: 

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

296 finally: 

297 try: 

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

299 cast(Packet, p).sent_time 

300 except AttributeError: 

301 pass 

302 if self._flood: 

303 self.notans = self._flood.iterlen 

304 elif not self._send_done: 

305 self.notans = i 

306 self._send_done = True 

307 self._stop_sniffer_if_done() 

308 # In threaded mode, timeout 

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

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

311 if self.sniffer and self.sniffer.running: 

312 self.sniffer.stop() 

313 

314 def _process_packet(self, r): 

315 # type: (Packet) -> None 

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

317 if r is None: 

318 return 

319 ok = False 

320 h = r.hashret() 

321 if h in self.hsent: 

322 hlst = self.hsent[h] 

323 for i, sentpkt in enumerate(hlst): 

324 if r.answers(sentpkt): 

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

326 if self.verbose > 1: 

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

328 ok = True 

329 if not self.multi: 

330 del hlst[i] 

331 self.noans += 1 

332 else: 

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

334 self.noans += 1 

335 sentpkt._answered = 1 

336 break 

337 self._stop_sniffer_if_done() 

338 if not ok: 

339 if self.verbose > 1: 

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

341 self.nbrecv += 1 

342 if conf.debug_match: 

343 debug.recv.append(r) 

344 

345 def _sndrcv_rcv(self, callback): 

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

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

348 # This is blocking. 

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

350 self.sniffer = AsyncSniffer() 

351 self.sniffer._run( 

352 prn=self._process_packet, 

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

354 store=False, 

355 opened_socket=self.rcv_pks, 

356 session=self.session, 

357 stop_filter=self.stop_filter, 

358 started_callback=callback, 

359 chainCC=True, 

360 ) 

361 

362 

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

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

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

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

367 more appropriate in many cases. 

368 """ 

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

370 return sndrcver.results() 

371 

372 

373def __gen_send(s, # type: SuperSocket 

374 x, # type: _PacketIterable 

375 inter=0, # type: int 

376 loop=0, # type: int 

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

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

379 realtime=False, # type: bool 

380 return_packets=False, # type: bool 

381 *args, # type: Any 

382 **kargs # type: Any 

383 ): 

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

385 """ 

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

387 implement the send logic... 

388 

389 It will take care of iterating through the different packets 

390 """ 

391 if isinstance(x, str): 

392 x = conf.raw_layer(load=x) 

393 if not isinstance(x, Gen): 

394 x = SetGen(x) 

395 if verbose is None: 

396 verbose = conf.verb 

397 n = 0 

398 if count is not None: 

399 loop = -count 

400 elif not loop: 

401 loop = -1 

402 sent_packets = PacketList() if return_packets else None 

403 p = None 

404 try: 

405 while loop: 

406 dt0 = None 

407 for p in x: 

408 if realtime: 

409 ct = time.time() 

410 if dt0: 

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

412 if st > 0: 

413 time.sleep(st) 

414 else: 

415 dt0 = ct - float(p.time) 

416 s.send(p) 

417 if sent_packets is not None: 

418 sent_packets.append(p) 

419 n += 1 

420 if verbose: 

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

422 time.sleep(inter) 

423 if loop < 0: 

424 loop += 1 

425 except KeyboardInterrupt: 

426 pass 

427 finally: 

428 try: 

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

430 except AttributeError: 

431 pass 

432 if verbose: 

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

434 return sent_packets 

435 

436 

437def _send(x, # type: _PacketIterable 

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

439 inter=0, # type: int 

440 loop=0, # type: int 

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

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

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

444 realtime=False, # type: bool 

445 return_packets=False, # type: bool 

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

447 **kargs # type: Any 

448 ): 

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

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

451 need_closing = socket is None 

452 iface = resolve_iface(iface or conf.iface) 

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

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

455 count=count, verbose=verbose, 

456 realtime=realtime, return_packets=return_packets) 

457 if need_closing: 

458 socket.close() 

459 return results 

460 

461 

462@conf.commands.register 

463def send(x, # type: _PacketIterable 

464 **kargs # type: Any 

465 ): 

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

467 """ 

468 Send packets at layer 3 

469 

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

471 table: conf.route / conf.route6 

472 

473 :param x: the packets 

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

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

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

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

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

479 :param return_packets: return the sent packets 

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

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

482 :returns: None 

483 """ 

484 iface, ipv6 = _interface_selection(x, kargs.pop("iface", None)) 

485 return _send( 

486 x, 

487 lambda iface: iface.l3socket(ipv6), 

488 iface=iface, 

489 **kargs 

490 ) 

491 

492 

493@conf.commands.register 

494def sendp(x, # type: _PacketIterable 

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

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

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

498 **kargs # type: Any 

499 ): 

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

501 """ 

502 Send packets at layer 2 

503 

504 :param x: the packets 

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

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

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

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

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

510 :param return_packets: return the sent packets 

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

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

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

514 :returns: None 

515 """ 

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

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

518 return _send( 

519 x, 

520 lambda iface: iface.l2socket(), 

521 iface=iface, 

522 socket=socket, 

523 **kargs 

524 ) 

525 

526 

527@conf.commands.register 

528def sendpfast(x: _PacketIterable, 

529 pps: Optional[float] = None, 

530 mbps: Optional[float] = None, 

531 realtime: bool = False, 

532 count: Optional[int] = None, 

533 loop: int = 0, 

534 file_cache: bool = False, 

535 iface: Optional[_GlobInterfaceType] = None, 

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

537 parse_results: bool = False, 

538 ): 

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

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

541 

542 :param pps: packets per second 

543 :param mbps: MBits per second 

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

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

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

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

548 disk at each iteration 

549 :param iface: output interface 

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

551 :param parse_results: Return a dictionary of information 

552 outputted by tcpreplay (default=False) 

553 :returns: stdout, stderr, command used 

554 """ 

555 if iface is None: 

556 iface = conf.iface 

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

558 if pps is not None: 

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

560 elif mbps is not None: 

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

562 elif realtime is not None: 

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

564 else: 

565 argv.append("--topspeed") 

566 

567 if count: 

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

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

570 elif loop: 

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

572 if file_cache: 

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

574 

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

576 if replay_args is not None: 

577 argv.extend(replay_args) 

578 

579 f = get_temp_file() 

580 argv.append(f) 

581 wrpcap(f, x) 

582 results = None 

583 with ContextManagerSubprocess(conf.prog.tcpreplay): 

584 try: 

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

586 stderr=subprocess.PIPE) 

587 cmd.wait() 

588 except KeyboardInterrupt: 

589 if cmd: 

590 cmd.terminate() 

591 log_interactive.info("Interrupted by user") 

592 except Exception: 

593 os.unlink(f) 

594 raise 

595 finally: 

596 stdout, stderr = cmd.communicate() 

597 if stderr: 

598 log_runtime.warning(stderr.decode()) 

599 if parse_results: 

600 results = _parse_tcpreplay_result(stdout, stderr, argv) 

601 elif conf.verb > 2: 

602 log_runtime.info(stdout.decode()) 

603 if os.path.exists(f): 

604 os.unlink(f) 

605 return results 

606 

607 

608def _parse_tcpreplay_result(stdout_b, stderr_b, argv): 

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

610 """ 

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

612 Tested with tcpreplay v3.4.4 

613 Tested with tcpreplay v4.1.2 

614 :param stdout: stdout of tcpreplay subprocess call 

615 :param stderr: stderr of tcpreplay subprocess call 

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

617 :return: dictionary containing the results 

618 """ 

619 try: 

620 results = {} 

621 stdout = plain_str(stdout_b).lower() 

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

623 elements = { 

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

625 "rated": (float, float, float), 

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

627 "attempted": (int,), 

628 "successful": (int,), 

629 "failed": (int,), 

630 "truncated": (int,), 

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

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

633 } 

634 multi = { 

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

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

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

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

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

640 } 

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

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

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

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

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

646 line = line.strip() 

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

648 if line.startswith(elt): 

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

650 matches = re.search(regex, line) 

651 for i, typ in enumerate(_types): 

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

653 if matches: 

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

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

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

657 return results 

658 except Exception as parse_exception: 

659 if not conf.interactive: 

660 raise 

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

662 return {} 

663 

664 

665def _interface_selection( 

666 packet: _PacketIterable, 

667 iface: Optional[str] = None, 

668) -> Tuple[NetworkInterface, bool]: 

669 """ 

670 Select the network interface according to the layer 3 destination 

671 """ 

672 if iface is not None: 

673 try: 

674 packet.dst = ScopedIP(packet.dst, scope=iface) # type: ignore 

675 except AttributeError: 

676 raise AttributeError("Cannot use iface= with this packet type.") 

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

678 ipv6 = False 

679 if src: 

680 try: 

681 inet_pton(socket.AF_INET6, src) 

682 ipv6 = True 

683 except (ValueError, OSError): 

684 pass 

685 try: 

686 iff = resolve_iface(_iff or conf.iface) 

687 except AttributeError: 

688 iff = None 

689 return iff or conf.iface, ipv6 

690 

691 

692@conf.commands.register 

693def sr(x, # type: _PacketIterable 

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

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

696 nofilter=0, # type: int 

697 *args, # type: Any 

698 **kargs # type: Any 

699 ): 

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

701 """ 

702 Send and receive packets at layer 3 

703 

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

705 table: conf.route / conf.route6 

706 """ 

707 iface, ipv6 = _interface_selection(x, kargs.pop("iface", None)) 

708 s = iface.l3socket(ipv6)( 

709 promisc=promisc, filter=filter, 

710 iface=iface, nofilter=nofilter, 

711 ) 

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

713 s.close() 

714 return result 

715 

716 

717@conf.commands.register 

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

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

720 """ 

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

722 

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

724 table: conf.route / conf.route6 

725 """ 

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

727 if ans: 

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

729 return None 

730 

731 

732@conf.commands.register 

733def srp(x, # type: _PacketIterable 

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

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

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

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

738 nofilter=0, # type: int 

739 type=ETH_P_ALL, # type: int 

740 *args, # type: Any 

741 **kargs # type: Any 

742 ): 

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

744 """ 

745 Send and receive packets at layer 2 

746 """ 

747 if iface is None and iface_hint is not None: 

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

749 iface = resolve_iface(iface or conf.iface) 

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

751 filter=filter, nofilter=nofilter, type=type) 

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

753 s.close() 

754 return result 

755 

756 

757@conf.commands.register 

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

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

760 """ 

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

762 """ 

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

764 if len(ans) > 0: 

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

766 return None 

767 

768 

769# Append doc 

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

771 if sr_func.__doc__ is not None: 

772 sr_func.__doc__ += _DOC_SNDRCV_PARAMS 

773 

774 

775# SEND/RECV LOOP METHODS 

776 

777 

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

779 pkts, # type: _PacketIterable 

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

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

782 inter=1, # type: int 

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

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

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

786 store=1, # type: int 

787 *args, # type: Any 

788 **kargs # type: Any 

789 ): 

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

791 n = 0 

792 r = 0 

793 ct = conf.color_theme 

794 if verbose is None: 

795 verbose = conf.verb 

796 parity = 0 

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

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

799 if timeout is None: 

800 timeout = min(2 * inter, 5) 

801 try: 

802 while True: 

803 parity ^= 1 

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

805 if count is not None: 

806 if count == 0: 

807 break 

808 count -= 1 

809 start = time.monotonic() 

810 if verbose > 1: 

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

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

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

814 r += len(res[0]) 

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

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

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

818 for rcv in res[0]: 

819 print(col(prn(rcv))) 

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

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

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

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

824 for fail in res[1]: 

825 print(col(prnfail(fail))) 

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

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

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

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

830 )) 

831 if verbose == 1: 

832 if res[0]: 

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

834 if res[1]: 

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

836 if store: 

837 ans += res[0] 

838 unans += res[1] 

839 end = time.monotonic() 

840 if end - start < inter: 

841 time.sleep(inter + start - end) 

842 except KeyboardInterrupt: 

843 pass 

844 

845 if verbose and n > 0: 

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

847 return SndRcvList(ans), PacketList(unans) 

848 

849 

850@conf.commands.register 

851def srloop(pkts, # type: _PacketIterable 

852 *args, # type: Any 

853 **kargs # type: Any 

854 ): 

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

856 """ 

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

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

859 """ 

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

861 

862 

863@conf.commands.register 

864def srploop(pkts, # type: _PacketIterable 

865 *args, # type: Any 

866 **kargs # type: Any 

867 ): 

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

869 """ 

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

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

872 """ 

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

874 

875# SEND/RECV FLOOD METHODS 

876 

877 

878class _FloodGenerator(object): 

879 def __init__(self, tobesent, maxretries): 

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

881 self.tobesent = tobesent 

882 self.maxretries = maxretries 

883 self.stopevent = Event() 

884 self.iterlen = 0 

885 

886 def __iter__(self): 

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

888 i = 0 

889 while True: 

890 i += 1 

891 j = 0 

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

893 return 

894 for p in self.tobesent: 

895 if self.stopevent.is_set(): 

896 return 

897 j += 1 

898 yield p 

899 if self.iterlen == 0: 

900 self.iterlen = j 

901 

902 @property 

903 def sent_time(self): 

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

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

906 

907 @sent_time.setter 

908 def sent_time(self, val): 

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

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

911 

912 def stop(self): 

913 # type: () -> None 

914 self.stopevent.set() 

915 

916 

917def sndrcvflood(pks, # type: SuperSocket 

918 pkt, # type: _PacketIterable 

919 inter=0, # type: int 

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

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

922 chainCC=False, # type: bool 

923 timeout=None # type: Optional[int] 

924 ): 

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

926 """sndrcv equivalent for flooding.""" 

927 

928 flood_gen = _FloodGenerator(pkt, maxretries) 

929 return sndrcv( 

930 pks, flood_gen, 

931 inter=inter, verbose=verbose, 

932 chainCC=chainCC, timeout=timeout, 

933 _flood=flood_gen 

934 ) 

935 

936 

937@conf.commands.register 

938def srflood(x, # type: _PacketIterable 

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

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

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

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

943 *args, # type: Any 

944 **kargs # type: Any 

945 ): 

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

947 """Flood and receive packets at layer 3 

948 

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

950 table: conf.route / conf.route6 

951 

952 :param prn: function applied to packets received 

953 :param unique: only consider packets whose print 

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

955 :param filter: provide a BPF filter 

956 """ 

957 iface, ipv6 = _interface_selection(x, kargs.pop("iface", None)) 

958 s = iface.l3socket(ipv6)( 

959 promisc=promisc, filter=filter, 

960 iface=iface, nofilter=nofilter, 

961 ) 

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

963 s.close() 

964 return r 

965 

966 

967@conf.commands.register 

968def sr1flood(x, # type: _PacketIterable 

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

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

971 nofilter=0, # type: int 

972 *args, # type: Any 

973 **kargs # type: Any 

974 ): 

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

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

977 

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

979 table: conf.route / conf.route6 

980 

981 :param prn: function applied to packets received 

982 :param verbose: set verbosity level 

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

984 :param filter: provide a BPF filter 

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

986 """ 

987 iface, ipv6 = _interface_selection(x, kargs.pop("iface", None)) 

988 s = iface.l3socket(ipv6)( 

989 promisc=promisc, filter=filter, 

990 nofilter=nofilter, iface=iface, 

991 ) 

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

993 s.close() 

994 if len(ans) > 0: 

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

996 return None 

997 

998 

999@conf.commands.register 

1000def srpflood(x, # type: _PacketIterable 

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

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

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

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

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

1006 *args, # type: Any 

1007 **kargs # type: Any 

1008 ): 

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

1010 """Flood and receive packets at layer 2 

1011 

1012 :param prn: function applied to packets received 

1013 :param unique: only consider packets whose print 

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

1015 :param filter: provide a BPF filter 

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

1017 """ 

1018 if iface is None and iface_hint is not None: 

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

1020 iface = resolve_iface(iface or conf.iface) 

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

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

1023 s.close() 

1024 return r 

1025 

1026 

1027@conf.commands.register 

1028def srp1flood(x, # type: _PacketIterable 

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

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

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

1032 nofilter=0, # type: int 

1033 *args, # type: Any 

1034 **kargs # type: Any 

1035 ): 

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

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

1038 

1039 :param prn: function applied to packets received 

1040 :param verbose: set verbosity level 

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

1042 :param filter: provide a BPF filter 

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

1044 """ 

1045 iface = resolve_iface(iface or conf.iface) 

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

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

1048 s.close() 

1049 if len(ans) > 0: 

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

1051 return None 

1052 

1053# SNIFF METHODS 

1054 

1055 

1056class AsyncSniffer(object): 

1057 """ 

1058 Sniff packets and return a list of packets. 

1059 

1060 Args: 

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

1062 store: whether to store sniffed packets or discard them 

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

1064 is displayed. 

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

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

1067 --Ex: session=TCPSession 

1068 See below for more details. 

1069 filter: BPF filter to apply. 

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

1071 further action may be done. 

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

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

1074 instead of sniffing them 

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

1076 (default: False). 

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

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

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

1080 .recv() on. 

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

1082 we have to stop the capture after this packet. 

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

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

1085 on the default interface). 

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

1087 started_callback: called as soon as the sniffer starts sniffing 

1088 (default: None). 

1089 

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

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

1092 label (see examples below). 

1093 

1094 For more information about the session argument, see 

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

1096 

1097 Examples: synchronous 

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

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

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

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

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

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

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

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

1106 ... pkt.summary())) 

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

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

1109 ... pkt.summary())) 

1110 

1111 Examples: asynchronous 

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

1113 >>> t.start() 

1114 >>> time.sleep(1) 

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

1116 >>> t.stop() 

1117 """ 

1118 

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

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

1121 # Store keyword arguments 

1122 self.args = args 

1123 self.kwargs = kwargs 

1124 self.running = False 

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

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

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

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

1129 

1130 def _setup_thread(self): 

1131 # type: () -> None 

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

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

1134 try: 

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

1136 except Exception as ex: 

1137 self.exception = ex 

1138 # Prepare sniffing thread 

1139 self.thread = Thread( 

1140 target=_run_catch, 

1141 args=self.args, 

1142 kwargs=self.kwargs, 

1143 name="AsyncSniffer" 

1144 ) 

1145 self.thread.daemon = True 

1146 

1147 def _run(self, 

1148 count=0, # type: int 

1149 store=True, # type: bool 

1150 offline=None, # type: Any 

1151 quiet=False, # type: bool 

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

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

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

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

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

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

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

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

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

1161 chainCC=False, # type: bool 

1162 **karg # type: Any 

1163 ): 

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

1165 self.running = True 

1166 self.count = 0 

1167 lst = [] 

1168 # Start main thread 

1169 # instantiate session 

1170 if not isinstance(session, DefaultSession): 

1171 session = session or DefaultSession 

1172 session = session() 

1173 # sniff_sockets follows: {socket: label} 

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

1175 if opened_socket is not None: 

1176 if isinstance(opened_socket, list): 

1177 sniff_sockets.update( 

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

1179 for i, s in enumerate(opened_socket) 

1180 ) 

1181 elif isinstance(opened_socket, dict): 

1182 sniff_sockets.update( 

1183 (s, label) 

1184 for s, label in opened_socket.items() 

1185 ) 

1186 else: 

1187 sniff_sockets[opened_socket] = "socket0" 

1188 if offline is not None: 

1189 flt = karg.get('filter') 

1190 

1191 if isinstance(offline, str): 

1192 # Single file 

1193 offline = [offline] 

1194 if isinstance(offline, list) and \ 

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

1196 # List of files 

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

1198 fname if flt is None else 

1199 tcpdump(fname, 

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

1201 flt=flt, 

1202 getfd=True, 

1203 quiet=quiet) 

1204 ), fname) for fname in offline) 

1205 elif isinstance(offline, dict): 

1206 # Dict of files 

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

1208 fname if flt is None else 

1209 tcpdump(fname, 

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

1211 flt=flt, 

1212 getfd=True, 

1213 quiet=quiet) 

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

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

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

1217 offline = IterSocket(offline) 

1218 sniff_sockets[offline if flt is None else PcapReader( 

1219 tcpdump(offline, 

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

1221 flt=flt, 

1222 getfd=True, 

1223 quiet=quiet) 

1224 )] = offline 

1225 else: 

1226 # Other (file descriptors...) 

1227 sniff_sockets[PcapReader( # type: ignore 

1228 offline if flt is None else 

1229 tcpdump(offline, 

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

1231 flt=flt, 

1232 getfd=True, 

1233 quiet=quiet) 

1234 )] = offline 

1235 if not sniff_sockets or iface is not None: 

1236 # The _RL2 function resolves the L2socket of an iface 

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

1238 if isinstance(iface, list): 

1239 sniff_sockets.update( 

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

1241 ifname) 

1242 for ifname in iface 

1243 ) 

1244 elif isinstance(iface, dict): 

1245 sniff_sockets.update( 

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

1247 iflabel) 

1248 for ifname, iflabel in iface.items() 

1249 ) 

1250 else: 

1251 iface = iface or conf.iface 

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

1253 **karg)] = iface 

1254 

1255 # Get select information from the sockets 

1256 _main_socket = next(iter(sniff_sockets)) 

1257 select_func = _main_socket.select 

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

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

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

1261 warning("Warning: inconsistent socket types ! " 

1262 "The used select function " 

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

1264 

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

1266 if not nonblocking_socket: 

1267 # select is blocking: Add special control socket 

1268 from scapy.automaton import ObjectPipe 

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

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

1271 

1272 def stop_cb(): 

1273 # type: () -> None 

1274 if self.running and close_pipe: 

1275 close_pipe.send(None) 

1276 self.continue_sniff = False 

1277 self.stop_cb = stop_cb 

1278 else: 

1279 # select is non blocking 

1280 def stop_cb(): 

1281 # type: () -> None 

1282 self.continue_sniff = False 

1283 self.stop_cb = stop_cb 

1284 

1285 try: 

1286 self.continue_sniff = True 

1287 if started_callback: 

1288 started_callback() 

1289 

1290 # Start timeout 

1291 if timeout is not None: 

1292 stoptime = time.monotonic() + timeout 

1293 remain = None 

1294 

1295 while sniff_sockets and self.continue_sniff: 

1296 if timeout is not None: 

1297 remain = stoptime - time.monotonic() 

1298 if remain <= 0: 

1299 break 

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

1301 dead_sockets = [] 

1302 for s in sockets: 

1303 if s is close_pipe: # type: ignore 

1304 break 

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

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

1307 try: 

1308 packets = session.recv(s) 

1309 # A session can return multiple objects 

1310 for p in packets: 

1311 if lfilter and not lfilter(p): 

1312 continue 

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

1314 # post-processing 

1315 self.count += 1 

1316 if store: 

1317 lst.append(p) 

1318 if prn: 

1319 result = prn(p) 

1320 if result is not None: 

1321 print(result) 

1322 # check 

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

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

1325 self.continue_sniff = False 

1326 break 

1327 except EOFError: 

1328 # End of stream 

1329 try: 

1330 s.close() 

1331 except Exception: 

1332 pass 

1333 dead_sockets.append(s) 

1334 continue 

1335 except Exception as ex: 

1336 msg = " It was closed." 

1337 try: 

1338 # Make sure it's closed 

1339 s.close() 

1340 except Exception as ex2: 

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

1342 warning( 

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

1344 ) 

1345 dead_sockets.append(s) 

1346 if conf.debug_dissector >= 2: 

1347 raise 

1348 continue 

1349 # Removed dead sockets 

1350 for s in dead_sockets: 

1351 del sniff_sockets[s] 

1352 if len(sniff_sockets) == 1 and \ 

1353 close_pipe in sniff_sockets: # type: ignore 

1354 # Only the close_pipe left 

1355 del sniff_sockets[close_pipe] # type: ignore 

1356 except KeyboardInterrupt: 

1357 if chainCC: 

1358 raise 

1359 self.running = False 

1360 if opened_socket is None: 

1361 for s in sniff_sockets: 

1362 s.close() 

1363 elif close_pipe: 

1364 close_pipe.close() 

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

1366 

1367 def start(self): 

1368 # type: () -> None 

1369 """Starts AsyncSniffer in async mode""" 

1370 self._setup_thread() 

1371 if self.thread: 

1372 self.thread.start() 

1373 

1374 def stop(self, join=True): 

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

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

1377 if self.running: 

1378 self.stop_cb() 

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

1380 # Never started -> is there an exception? 

1381 if self.exception is not None: 

1382 raise self.exception 

1383 return None 

1384 if self.continue_sniff: 

1385 raise Scapy_Exception( 

1386 "Unsupported (offline or unsupported socket)" 

1387 ) 

1388 if join: 

1389 self.join() 

1390 return self.results 

1391 return None 

1392 else: 

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

1394 

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

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

1397 if self.thread: 

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

1399 if self.exception is not None: 

1400 raise self.exception 

1401 

1402 

1403@conf.commands.register 

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

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

1406 sniffer = AsyncSniffer() 

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

1408 return cast(PacketList, sniffer.results) 

1409 

1410 

1411sniff.__doc__ = AsyncSniffer.__doc__ 

1412 

1413 

1414@conf.commands.register 

1415def bridge_and_sniff(if1, # type: _GlobInterfaceType 

1416 if2, # type: _GlobInterfaceType 

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

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

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

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

1421 *args, # type: Any 

1422 **kargs # type: Any 

1423 ): 

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

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

1426 the exchanged packets. 

1427 

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

1429 :param if2: 

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

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

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

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

1434 one. 

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

1436 

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

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

1439 See help(sniff) for more. 

1440 """ 

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

1442 if arg in kargs: 

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

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

1445 del kargs[arg] 

1446 

1447 def _init_socket(iface, # type: _GlobInterfaceType 

1448 count, # type: int 

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

1450 ): 

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

1452 if isinstance(iface, SuperSocket): 

1453 return iface, "iface%d" % count 

1454 else: 

1455 if not L2socket: 

1456 iface = resolve_iface(iface or conf.iface) 

1457 L2socket = iface.l2socket() 

1458 return L2socket(iface=iface), iface 

1459 sckt1, if1 = _init_socket(if1, 1) 

1460 sckt2, if2 = _init_socket(if2, 2) 

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

1462 xfrms = {} 

1463 if xfrm12 is not None: 

1464 xfrms[if1] = xfrm12 

1465 if xfrm21 is not None: 

1466 xfrms[if2] = xfrm21 

1467 

1468 def prn_send(pkt): 

1469 # type: (Packet) -> None 

1470 try: 

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

1472 except KeyError: 

1473 return 

1474 if pkt.sniffed_on in xfrms: 

1475 try: 

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

1477 except Exception: 

1478 log_runtime.warning( 

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

1480 'received on %s -- dropping', 

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

1482 ) 

1483 return 

1484 else: 

1485 if isinstance(_newpkt, bool): 

1486 if not _newpkt: 

1487 return 

1488 newpkt = pkt 

1489 else: 

1490 newpkt = _newpkt 

1491 else: 

1492 newpkt = pkt 

1493 try: 

1494 sendsock.send(newpkt) 

1495 except Exception: 

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

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

1498 if prn is None: 

1499 prn = prn_send 

1500 else: 

1501 prn_orig = prn 

1502 

1503 def prn(pkt): 

1504 # type: (Packet) -> Any 

1505 prn_send(pkt) 

1506 return prn_orig(pkt) 

1507 

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

1509 *args, **kargs) 

1510 

1511 

1512@conf.commands.register 

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

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

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

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

1517 

1518 if 'iface' in kargs: 

1519 iface = kargs.get('iface') 

1520 elif 'opened_socket' in kargs: 

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

1522 else: 

1523 iface = conf.iface 

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

1525 

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

1527 # for Python 2 compatibility 

1528 i = [0] 

1529 

1530 def _cb(pkt): 

1531 # type: (Packet) -> None 

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

1533 i[0] += 1 

1534 

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

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