Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/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

710 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 

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 rcv_pks: if set, will be used instead of pks to receive packets. 

89 packets will still be sent through pks 

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

91 Automatically enabled when a generator is passed as the packet 

92 :param _flood: 

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

94 defaults to False. 

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

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

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

98 we have to stop the capture after this packet. 

99 """ 

100 

101 

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

103 

104 

105class SndRcvHandler(object): 

106 """ 

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

108 Do not use directly. 

109 

110 This matches the requests and answers. 

111 

112 Notes:: 

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

114 a good idea to use threaded mode. 

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

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

117 """ 

118 def __init__(self, 

119 pks, # type: SuperSocket 

120 pkt, # type: _PacketIterable 

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

122 inter=0, # type: int 

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

124 chainCC=False, # type: bool 

125 retry=0, # type: int 

126 multi=False, # type: bool 

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

128 prebuild=False, # type: bool 

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

130 threaded=False, # type: bool 

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

132 chainEX=False, # type: bool 

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

134 ): 

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

136 # Instantiate all arguments 

137 if verbose is None: 

138 verbose = conf.verb 

139 if conf.debug_match: 

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

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

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

143 self.nbrecv = 0 

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

145 self.pks = pks 

146 self.rcv_pks = rcv_pks or pks 

147 self.inter = inter 

148 self.verbose = verbose 

149 self.chainCC = chainCC 

150 self.multi = multi 

151 self.timeout = timeout 

152 self.session = session 

153 self.chainEX = chainEX 

154 self.stop_filter = stop_filter 

155 self._send_done = False 

156 self.notans = 0 

157 self.noans = 0 

158 self._flood = _flood 

159 self.threaded = threaded 

160 self.breakout = False 

161 # Instantiate packet holders 

162 if prebuild and not self._flood: 

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

164 else: 

165 self.tobesent = pkt 

166 

167 if retry < 0: 

168 autostop = retry = -retry 

169 else: 

170 autostop = 0 

171 

172 if timeout is not None and timeout < 0: 

173 self.timeout = None 

174 

175 while retry >= 0: 

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

177 

178 if threaded or self._flood: 

179 # Send packets in thread. 

180 snd_thread = Thread( 

181 target=self._sndrcv_snd 

182 ) 

183 snd_thread.daemon = True 

184 

185 # Start routine with callback 

186 interrupted = None 

187 try: 

188 self._sndrcv_rcv(snd_thread.start) 

189 except KeyboardInterrupt as ex: 

190 interrupted = ex 

191 

192 self.breakout = True 

193 

194 # Ended. Let's close gracefully 

195 if self._flood: 

196 # Flood: stop send thread 

197 self._flood.stop() 

198 snd_thread.join() 

199 

200 if interrupted and self.chainCC: 

201 raise interrupted 

202 else: 

203 # Send packets, then receive. 

204 try: 

205 self._sndrcv_rcv(self._sndrcv_snd) 

206 except KeyboardInterrupt: 

207 if self.chainCC: 

208 raise 

209 

210 if multi: 

211 remain = [ 

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

213 if not hasattr(p, '_answered') 

214 ] 

215 else: 

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

217 

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

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

220 retry = autostop 

221 

222 self.tobesent = remain 

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

224 break 

225 retry -= 1 

226 

227 if conf.debug_match: 

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

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

230 

231 # Clean the ans list to delete the field _answered 

232 if multi: 

233 for snd, _ in self.ans: 

234 if hasattr(snd, '_answered'): 

235 del snd._answered 

236 

237 if verbose: 

238 print( 

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

240 "remaining %i packets" % ( 

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

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

243 ) 

244 ) 

245 

246 self.ans_result = SndRcvList(self.ans) 

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

248 

249 def results(self): 

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

251 return self.ans_result, self.unans_result 

252 

253 def _sndrcv_snd(self): 

254 # type: () -> None 

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

256 i = 0 

257 p = None 

258 try: 

259 if self.verbose: 

260 print("Begin emission:") 

261 for p in self.tobesent: 

262 # Populate the dictionary of _sndrcv_rcv 

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

264 # has not been sent 

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

266 # Send packet 

267 self.pks.send(p) 

268 if self.inter: 

269 time.sleep(self.inter) 

270 if self.breakout: 

271 break 

272 i += 1 

273 if self.verbose: 

274 print("Finished sending %i packets." % i) 

275 except SystemExit: 

276 pass 

277 except Exception: 

278 if self.chainEX: 

279 raise 

280 else: 

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

282 finally: 

283 try: 

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

285 cast(Packet, p).sent_time 

286 except AttributeError: 

287 pass 

288 if self._flood: 

289 self.notans = self._flood.iterlen 

290 elif not self._send_done: 

291 self.notans = i 

292 self._send_done = True 

293 # In threaded mode, timeout. 

294 if self.threaded and self.timeout is not None and not self.breakout: 

295 t = time.monotonic() + self.timeout 

296 while time.monotonic() < t: 

297 if self.breakout: 

298 break 

299 time.sleep(0.1) 

300 if self.sniffer and self.sniffer.running: 

301 self.sniffer.stop() 

302 

303 def _process_packet(self, r): 

304 # type: (Packet) -> None 

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

306 if r is None: 

307 return 

308 ok = False 

309 h = r.hashret() 

310 if h in self.hsent: 

311 hlst = self.hsent[h] 

312 for i, sentpkt in enumerate(hlst): 

313 if r.answers(sentpkt): 

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

315 if self.verbose > 1: 

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

317 ok = True 

318 if not self.multi: 

319 del hlst[i] 

320 self.noans += 1 

321 else: 

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

323 self.noans += 1 

324 sentpkt._answered = 1 

325 break 

326 if self._send_done and self.noans >= self.notans and not self.multi: 

327 if self.sniffer and self.sniffer.running: 

328 self.sniffer.stop(join=False) 

329 if not ok: 

330 if self.verbose > 1: 

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

332 self.nbrecv += 1 

333 if conf.debug_match: 

334 debug.recv.append(r) 

335 

336 def _sndrcv_rcv(self, callback): 

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

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

339 # This is blocking. 

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

341 self.sniffer = AsyncSniffer() 

342 self.sniffer._run( 

343 prn=self._process_packet, 

344 timeout=None if self.threaded else self.timeout, 

345 store=False, 

346 opened_socket=self.rcv_pks, 

347 session=self.session, 

348 stop_filter=self.stop_filter, 

349 started_callback=callback, 

350 chainCC=True, 

351 ) 

352 

353 

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

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

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

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

358 more appropriate in many cases. 

359 """ 

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

361 return sndrcver.results() 

362 

363 

364def __gen_send(s, # type: SuperSocket 

365 x, # type: _PacketIterable 

366 inter=0, # type: int 

367 loop=0, # type: int 

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

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

370 realtime=False, # type: bool 

371 return_packets=False, # type: bool 

372 *args, # type: Any 

373 **kargs # type: Any 

374 ): 

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

376 """ 

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

378 implement the send logic... 

379 

380 It will take care of iterating through the different packets 

381 """ 

382 if isinstance(x, str): 

383 x = conf.raw_layer(load=x) 

384 if not isinstance(x, Gen): 

385 x = SetGen(x) 

386 if verbose is None: 

387 verbose = conf.verb 

388 n = 0 

389 if count is not None: 

390 loop = -count 

391 elif not loop: 

392 loop = -1 

393 sent_packets = PacketList() if return_packets else None 

394 p = None 

395 try: 

396 while loop: 

397 dt0 = None 

398 for p in x: 

399 if realtime: 

400 ct = time.time() 

401 if dt0: 

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

403 if st > 0: 

404 time.sleep(st) 

405 else: 

406 dt0 = ct - float(p.time) 

407 s.send(p) 

408 if sent_packets is not None: 

409 sent_packets.append(p) 

410 n += 1 

411 if verbose: 

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

413 time.sleep(inter) 

414 if loop < 0: 

415 loop += 1 

416 except KeyboardInterrupt: 

417 pass 

418 finally: 

419 try: 

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

421 except AttributeError: 

422 pass 

423 if verbose: 

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

425 return sent_packets 

426 

427 

428def _send(x, # type: _PacketIterable 

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

430 inter=0, # type: int 

431 loop=0, # type: int 

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

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

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

435 realtime=False, # type: bool 

436 return_packets=False, # type: bool 

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

438 **kargs # type: Any 

439 ): 

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

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

442 need_closing = socket is None 

443 iface = resolve_iface(iface or conf.iface) 

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

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

446 count=count, verbose=verbose, 

447 realtime=realtime, return_packets=return_packets) 

448 if need_closing: 

449 socket.close() 

450 return results 

451 

452 

453@conf.commands.register 

454def send(x, # type: _PacketIterable 

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

456 **kargs # type: Any 

457 ): 

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

459 """ 

460 Send packets at layer 3 

461 

462 :param x: the packets 

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

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

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

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

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

468 :param return_packets: return the sent packets 

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

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

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

472 :returns: None 

473 """ 

474 iface, ipv6 = _interface_selection(iface, x) 

475 return _send( 

476 x, 

477 lambda iface: iface.l3socket(ipv6), 

478 iface=iface, 

479 **kargs 

480 ) 

481 

482 

483@conf.commands.register 

484def sendp(x, # type: _PacketIterable 

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

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

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

488 **kargs # type: Any 

489 ): 

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

491 """ 

492 Send packets at layer 2 

493 

494 :param x: the packets 

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

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

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

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

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

500 :param return_packets: return the sent packets 

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

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

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

504 :returns: None 

505 """ 

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

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

508 return _send( 

509 x, 

510 lambda iface: iface.l2socket(), 

511 iface=iface, 

512 socket=socket, 

513 **kargs 

514 ) 

515 

516 

517@conf.commands.register 

518def sendpfast(x: _PacketIterable, 

519 pps: Optional[float] = None, 

520 mbps: Optional[float] = None, 

521 realtime: bool = False, 

522 count: Optional[int] = None, 

523 loop: int = 0, 

524 file_cache: bool = False, 

525 iface: Optional[_GlobInterfaceType] = None, 

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

527 parse_results: bool = False, 

528 ): 

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

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

531 

532 :param pps: packets per second 

533 :param mbps: MBits per second 

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

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

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

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

538 disk at each iteration 

539 :param iface: output interface 

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

541 :param parse_results: Return a dictionary of information 

542 outputted by tcpreplay (default=False) 

543 :returns: stdout, stderr, command used 

544 """ 

545 if iface is None: 

546 iface = conf.iface 

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

548 if pps is not None: 

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

550 elif mbps is not None: 

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

552 elif realtime is not None: 

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

554 else: 

555 argv.append("--topspeed") 

556 

557 if count: 

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

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

560 elif loop: 

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

562 if file_cache: 

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

564 

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

566 if replay_args is not None: 

567 argv.extend(replay_args) 

568 

569 f = get_temp_file() 

570 argv.append(f) 

571 wrpcap(f, x) 

572 results = None 

573 with ContextManagerSubprocess(conf.prog.tcpreplay): 

574 try: 

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

576 stderr=subprocess.PIPE) 

577 except KeyboardInterrupt: 

578 log_interactive.info("Interrupted by user") 

579 except Exception: 

580 os.unlink(f) 

581 raise 

582 else: 

583 stdout, stderr = cmd.communicate() 

584 if stderr: 

585 log_runtime.warning(stderr.decode()) 

586 if parse_results: 

587 results = _parse_tcpreplay_result(stdout, stderr, argv) 

588 elif conf.verb > 2: 

589 log_runtime.info(stdout.decode()) 

590 if os.path.exists(f): 

591 os.unlink(f) 

592 return results 

593 

594 

595def _parse_tcpreplay_result(stdout_b, stderr_b, argv): 

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

597 """ 

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

599 Tested with tcpreplay v3.4.4 

600 Tested with tcpreplay v4.1.2 

601 :param stdout: stdout of tcpreplay subprocess call 

602 :param stderr: stderr of tcpreplay subprocess call 

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

604 :return: dictionary containing the results 

605 """ 

606 try: 

607 results = {} 

608 stdout = plain_str(stdout_b).lower() 

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

610 elements = { 

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

612 "rated": (float, float, float), 

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

614 "attempted": (int,), 

615 "successful": (int,), 

616 "failed": (int,), 

617 "truncated": (int,), 

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

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

620 } 

621 multi = { 

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

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

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

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

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

627 } 

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

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

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

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

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

633 line = line.strip() 

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

635 if line.startswith(elt): 

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

637 matches = re.search(regex, line) 

638 for i, typ in enumerate(_types): 

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

640 if matches: 

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

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

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

644 return results 

645 except Exception as parse_exception: 

646 if not conf.interactive: 

647 raise 

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

649 return {} 

650 

651 

652def _interface_selection(iface, # type: Optional[_GlobInterfaceType] 

653 packet # type: _PacketIterable 

654 ): 

655 # type: (...) -> Tuple[NetworkInterface, bool] 

656 """ 

657 Select the network interface according to the layer 3 destination 

658 """ 

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

660 ipv6 = False 

661 if src: 

662 try: 

663 inet_pton(socket.AF_INET6, src) 

664 ipv6 = True 

665 except (ValueError, OSError): 

666 pass 

667 if iface is None: 

668 try: 

669 iff = resolve_iface(_iff or conf.iface) 

670 except AttributeError: 

671 iff = None 

672 return iff or conf.iface, ipv6 

673 

674 return resolve_iface(iface), ipv6 

675 

676 

677@conf.commands.register 

678def sr(x, # type: _PacketIterable 

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

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

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

682 nofilter=0, # type: int 

683 *args, # type: Any 

684 **kargs # type: Any 

685 ): 

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

687 """ 

688 Send and receive packets at layer 3 

689 """ 

690 iface, ipv6 = _interface_selection(iface, x) 

691 s = iface.l3socket(ipv6)( 

692 promisc=promisc, filter=filter, 

693 iface=iface, nofilter=nofilter, 

694 ) 

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

696 s.close() 

697 return result 

698 

699 

700@conf.commands.register 

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

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

703 """ 

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

705 """ 

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

707 if ans: 

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

709 return None 

710 

711 

712@conf.commands.register 

713def srp(x, # type: _PacketIterable 

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

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

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

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

718 nofilter=0, # type: int 

719 type=ETH_P_ALL, # type: int 

720 *args, # type: Any 

721 **kargs # type: Any 

722 ): 

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

724 """ 

725 Send and receive packets at layer 2 

726 """ 

727 if iface is None and iface_hint is not None: 

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

729 iface = resolve_iface(iface or conf.iface) 

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

731 filter=filter, nofilter=nofilter, type=type) 

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

733 s.close() 

734 return result 

735 

736 

737@conf.commands.register 

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

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

740 """ 

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

742 """ 

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

744 if len(ans) > 0: 

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

746 return None 

747 

748 

749# Append doc 

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

751 if sr_func.__doc__ is not None: 

752 sr_func.__doc__ += _DOC_SNDRCV_PARAMS 

753 

754 

755# SEND/RECV LOOP METHODS 

756 

757 

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

759 pkts, # type: _PacketIterable 

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

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

762 inter=1, # type: int 

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

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

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

766 store=1, # type: int 

767 *args, # type: Any 

768 **kargs # type: Any 

769 ): 

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

771 n = 0 

772 r = 0 

773 ct = conf.color_theme 

774 if verbose is None: 

775 verbose = conf.verb 

776 parity = 0 

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

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

779 if timeout is None: 

780 timeout = min(2 * inter, 5) 

781 try: 

782 while True: 

783 parity ^= 1 

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

785 if count is not None: 

786 if count == 0: 

787 break 

788 count -= 1 

789 start = time.monotonic() 

790 if verbose > 1: 

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

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

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

794 r += len(res[0]) 

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

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

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

798 for rcv in res[0]: 

799 print(col(prn(rcv))) 

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

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

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

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

804 for fail in res[1]: 

805 print(col(prnfail(fail))) 

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

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

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

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

810 )) 

811 if verbose == 1: 

812 if res[0]: 

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

814 if res[1]: 

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

816 if store: 

817 ans += res[0] 

818 unans += res[1] 

819 end = time.monotonic() 

820 if end - start < inter: 

821 time.sleep(inter + start - end) 

822 except KeyboardInterrupt: 

823 pass 

824 

825 if verbose and n > 0: 

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

827 return SndRcvList(ans), PacketList(unans) 

828 

829 

830@conf.commands.register 

831def srloop(pkts, # type: _PacketIterable 

832 *args, # type: Any 

833 **kargs # type: Any 

834 ): 

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

836 """ 

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

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

839 """ 

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

841 

842 

843@conf.commands.register 

844def srploop(pkts, # type: _PacketIterable 

845 *args, # type: Any 

846 **kargs # type: Any 

847 ): 

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

849 """ 

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

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

852 """ 

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

854 

855# SEND/RECV FLOOD METHODS 

856 

857 

858class _FloodGenerator(object): 

859 def __init__(self, tobesent, maxretries): 

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

861 self.tobesent = tobesent 

862 self.maxretries = maxretries 

863 self.stopevent = Event() 

864 self.iterlen = 0 

865 

866 def __iter__(self): 

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

868 i = 0 

869 while True: 

870 i += 1 

871 j = 0 

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

873 return 

874 for p in self.tobesent: 

875 if self.stopevent.is_set(): 

876 return 

877 j += 1 

878 yield p 

879 if self.iterlen == 0: 

880 self.iterlen = j 

881 

882 @property 

883 def sent_time(self): 

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

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

886 

887 @sent_time.setter 

888 def sent_time(self, val): 

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

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

891 

892 def stop(self): 

893 # type: () -> None 

894 self.stopevent.set() 

895 

896 

897def sndrcvflood(pks, # type: SuperSocket 

898 pkt, # type: _PacketIterable 

899 inter=0, # type: int 

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

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

902 chainCC=False, # type: bool 

903 timeout=None # type: Optional[int] 

904 ): 

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

906 """sndrcv equivalent for flooding.""" 

907 

908 flood_gen = _FloodGenerator(pkt, maxretries) 

909 return sndrcv( 

910 pks, flood_gen, 

911 inter=inter, verbose=verbose, 

912 chainCC=chainCC, timeout=timeout, 

913 _flood=flood_gen 

914 ) 

915 

916 

917@conf.commands.register 

918def srflood(x, # type: _PacketIterable 

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

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

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

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

923 *args, # type: Any 

924 **kargs # type: Any 

925 ): 

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

927 """Flood and receive packets at layer 3 

928 

929 :param prn: function applied to packets received 

930 :param unique: only consider packets whose print 

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

932 :param filter: provide a BPF filter 

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

934 """ 

935 iface, ipv6 = _interface_selection(iface, x) 

936 s = iface.l3socket(ipv6)( 

937 promisc=promisc, filter=filter, 

938 iface=iface, nofilter=nofilter, 

939 ) 

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

941 s.close() 

942 return r 

943 

944 

945@conf.commands.register 

946def sr1flood(x, # type: _PacketIterable 

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

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

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

950 nofilter=0, # type: int 

951 *args, # type: Any 

952 **kargs # type: Any 

953 ): 

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

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

956 

957 :param prn: function applied to packets received 

958 :param verbose: set verbosity level 

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

960 :param filter: provide a BPF filter 

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

962 """ 

963 iface, ipv6 = _interface_selection(iface, x) 

964 s = iface.l3socket(ipv6)( 

965 promisc=promisc, filter=filter, 

966 nofilter=nofilter, iface=iface, 

967 ) 

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

969 s.close() 

970 if len(ans) > 0: 

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

972 return None 

973 

974 

975@conf.commands.register 

976def srpflood(x, # type: _PacketIterable 

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

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

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

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

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

982 *args, # type: Any 

983 **kargs # type: Any 

984 ): 

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

986 """Flood and receive packets at layer 2 

987 

988 :param prn: function applied to packets received 

989 :param unique: only consider packets whose print 

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

991 :param filter: provide a BPF filter 

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

993 """ 

994 if iface is None and iface_hint is not None: 

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

996 iface = resolve_iface(iface or conf.iface) 

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

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

999 s.close() 

1000 return r 

1001 

1002 

1003@conf.commands.register 

1004def srp1flood(x, # type: _PacketIterable 

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

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

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

1008 nofilter=0, # type: int 

1009 *args, # type: Any 

1010 **kargs # type: Any 

1011 ): 

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

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

1014 

1015 :param prn: function applied to packets received 

1016 :param verbose: set verbosity level 

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

1018 :param filter: provide a BPF filter 

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

1020 """ 

1021 iface = resolve_iface(iface or conf.iface) 

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

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# SNIFF METHODS 

1030 

1031 

1032class AsyncSniffer(object): 

1033 """ 

1034 Sniff packets and return a list of packets. 

1035 

1036 Args: 

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

1038 store: whether to store sniffed packets or discard them 

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

1040 is displayed. 

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

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

1043 --Ex: session=TCPSession 

1044 See below for more details. 

1045 filter: BPF filter to apply. 

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

1047 further action may be done. 

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

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

1050 instead of sniffing them 

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

1052 (default: False). 

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

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

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

1056 .recv() on. 

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

1058 we have to stop the capture after this packet. 

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

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

1061 on the default interface). 

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

1063 started_callback: called as soon as the sniffer starts sniffing 

1064 (default: None). 

1065 

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

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

1068 label (see examples below). 

1069 

1070 For more information about the session argument, see 

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

1072 

1073 Examples: synchronous 

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

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

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

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

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

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

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

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

1082 ... pkt.summary())) 

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

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

1085 ... pkt.summary())) 

1086 

1087 Examples: asynchronous 

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

1089 >>> t.start() 

1090 >>> time.sleep(1) 

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

1092 >>> t.stop() 

1093 """ 

1094 

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

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

1097 # Store keyword arguments 

1098 self.args = args 

1099 self.kwargs = kwargs 

1100 self.running = False 

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

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

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

1104 

1105 def _setup_thread(self): 

1106 # type: () -> None 

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

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

1109 try: 

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

1111 except Exception as ex: 

1112 self.exception = ex 

1113 # Prepare sniffing thread 

1114 self.thread = Thread( 

1115 target=_run_catch, 

1116 args=self.args, 

1117 kwargs=self.kwargs, 

1118 name="AsyncSniffer" 

1119 ) 

1120 self.thread.daemon = True 

1121 

1122 def _run(self, 

1123 count=0, # type: int 

1124 store=True, # type: bool 

1125 offline=None, # type: Any 

1126 quiet=False, # type: bool 

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

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

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

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

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

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

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

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

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

1136 chainCC=False, # type: bool 

1137 **karg # type: Any 

1138 ): 

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

1140 self.running = True 

1141 self.count = 0 

1142 lst = [] 

1143 # Start main thread 

1144 # instantiate session 

1145 if not isinstance(session, DefaultSession): 

1146 session = session or DefaultSession 

1147 session = session() 

1148 # sniff_sockets follows: {socket: label} 

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

1150 if opened_socket is not None: 

1151 if isinstance(opened_socket, list): 

1152 sniff_sockets.update( 

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

1154 for i, s in enumerate(opened_socket) 

1155 ) 

1156 elif isinstance(opened_socket, dict): 

1157 sniff_sockets.update( 

1158 (s, label) 

1159 for s, label in opened_socket.items() 

1160 ) 

1161 else: 

1162 sniff_sockets[opened_socket] = "socket0" 

1163 if offline is not None: 

1164 flt = karg.get('filter') 

1165 

1166 if isinstance(offline, str): 

1167 # Single file 

1168 offline = [offline] 

1169 if isinstance(offline, list) and \ 

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

1171 # List of files 

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

1173 fname if flt is None else 

1174 tcpdump(fname, 

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

1176 flt=flt, 

1177 getfd=True, 

1178 quiet=quiet) 

1179 ), fname) for fname in offline) 

1180 elif isinstance(offline, dict): 

1181 # Dict of files 

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

1183 fname if flt is None else 

1184 tcpdump(fname, 

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

1186 flt=flt, 

1187 getfd=True, 

1188 quiet=quiet) 

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

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

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

1192 offline = IterSocket(offline) 

1193 sniff_sockets[offline if flt is None else PcapReader( 

1194 tcpdump(offline, 

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

1196 flt=flt, 

1197 getfd=True, 

1198 quiet=quiet) 

1199 )] = offline 

1200 else: 

1201 # Other (file descriptors...) 

1202 sniff_sockets[PcapReader( # type: ignore 

1203 offline if flt is None else 

1204 tcpdump(offline, 

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

1206 flt=flt, 

1207 getfd=True, 

1208 quiet=quiet) 

1209 )] = offline 

1210 if not sniff_sockets or iface is not None: 

1211 # The _RL2 function resolves the L2socket of an iface 

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

1213 if isinstance(iface, list): 

1214 sniff_sockets.update( 

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

1216 ifname) 

1217 for ifname in iface 

1218 ) 

1219 elif isinstance(iface, dict): 

1220 sniff_sockets.update( 

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

1222 iflabel) 

1223 for ifname, iflabel in iface.items() 

1224 ) 

1225 else: 

1226 iface = iface or conf.iface 

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

1228 **karg)] = iface 

1229 

1230 # Get select information from the sockets 

1231 _main_socket = next(iter(sniff_sockets)) 

1232 select_func = _main_socket.select 

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

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

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

1236 warning("Warning: inconsistent socket types ! " 

1237 "The used select function " 

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

1239 

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

1241 if not nonblocking_socket: 

1242 # select is blocking: Add special control socket 

1243 from scapy.automaton import ObjectPipe 

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

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

1246 

1247 def stop_cb(): 

1248 # type: () -> None 

1249 if self.running and close_pipe: 

1250 close_pipe.send(None) 

1251 self.continue_sniff = False 

1252 self.stop_cb = stop_cb 

1253 else: 

1254 # select is non blocking 

1255 def stop_cb(): 

1256 # type: () -> None 

1257 self.continue_sniff = False 

1258 self.stop_cb = stop_cb 

1259 

1260 try: 

1261 if started_callback: 

1262 started_callback() 

1263 self.continue_sniff = True 

1264 

1265 # Start timeout 

1266 if timeout is not None: 

1267 stoptime = time.monotonic() + timeout 

1268 remain = None 

1269 

1270 while sniff_sockets and self.continue_sniff: 

1271 if timeout is not None: 

1272 remain = stoptime - time.monotonic() 

1273 if remain <= 0: 

1274 break 

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

1276 dead_sockets = [] 

1277 for s in sockets: 

1278 if s is close_pipe: # type: ignore 

1279 break 

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

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

1282 try: 

1283 packets = session.recv(s) 

1284 # A session can return multiple objects 

1285 for p in packets: 

1286 if lfilter and not lfilter(p): 

1287 continue 

1288 p.sniffed_on = sniff_sockets[s] 

1289 # post-processing 

1290 self.count += 1 

1291 if store: 

1292 lst.append(p) 

1293 if prn: 

1294 result = prn(p) 

1295 if result is not None: 

1296 print(result) 

1297 # check 

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

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

1300 self.continue_sniff = False 

1301 break 

1302 except EOFError: 

1303 # End of stream 

1304 try: 

1305 s.close() 

1306 except Exception: 

1307 pass 

1308 dead_sockets.append(s) 

1309 continue 

1310 except Exception as ex: 

1311 msg = " It was closed." 

1312 try: 

1313 # Make sure it's closed 

1314 s.close() 

1315 except Exception as ex2: 

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

1317 warning( 

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

1319 ) 

1320 dead_sockets.append(s) 

1321 if conf.debug_dissector >= 2: 

1322 raise 

1323 continue 

1324 # Removed dead sockets 

1325 for s in dead_sockets: 

1326 del sniff_sockets[s] 

1327 if len(sniff_sockets) == 1 and \ 

1328 close_pipe in sniff_sockets: # type: ignore 

1329 # Only the close_pipe left 

1330 del sniff_sockets[close_pipe] # type: ignore 

1331 except KeyboardInterrupt: 

1332 if chainCC: 

1333 raise 

1334 self.running = False 

1335 if opened_socket is None: 

1336 for s in sniff_sockets: 

1337 s.close() 

1338 elif close_pipe: 

1339 close_pipe.close() 

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

1341 

1342 def start(self): 

1343 # type: () -> None 

1344 """Starts AsyncSniffer in async mode""" 

1345 self._setup_thread() 

1346 if self.thread: 

1347 self.thread.start() 

1348 

1349 def stop(self, join=True): 

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

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

1352 if self.running: 

1353 try: 

1354 self.stop_cb() 

1355 except AttributeError: 

1356 raise Scapy_Exception( 

1357 "Unsupported (offline or unsupported socket)" 

1358 ) 

1359 if join: 

1360 self.join() 

1361 return self.results 

1362 return None 

1363 else: 

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

1365 

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

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

1368 if self.thread: 

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

1370 if self.exception is not None: 

1371 raise self.exception 

1372 

1373 

1374@conf.commands.register 

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

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

1377 sniffer = AsyncSniffer() 

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

1379 return cast(PacketList, sniffer.results) 

1380 

1381 

1382sniff.__doc__ = AsyncSniffer.__doc__ 

1383 

1384 

1385@conf.commands.register 

1386def bridge_and_sniff(if1, # type: _GlobInterfaceType 

1387 if2, # type: _GlobInterfaceType 

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

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

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

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

1392 *args, # type: Any 

1393 **kargs # type: Any 

1394 ): 

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

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

1397 the exchanged packets. 

1398 

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

1400 :param if2: 

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

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

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

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

1405 one. 

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

1407 

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

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

1410 See help(sniff) for more. 

1411 """ 

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

1413 if arg in kargs: 

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

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

1416 del kargs[arg] 

1417 

1418 def _init_socket(iface, # type: _GlobInterfaceType 

1419 count, # type: int 

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

1421 ): 

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

1423 if isinstance(iface, SuperSocket): 

1424 return iface, "iface%d" % count 

1425 else: 

1426 if not L2socket: 

1427 iface = resolve_iface(iface or conf.iface) 

1428 L2socket = iface.l2socket() 

1429 return L2socket(iface=iface), iface 

1430 sckt1, if1 = _init_socket(if1, 1) 

1431 sckt2, if2 = _init_socket(if2, 2) 

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

1433 xfrms = {} 

1434 if xfrm12 is not None: 

1435 xfrms[if1] = xfrm12 

1436 if xfrm21 is not None: 

1437 xfrms[if2] = xfrm21 

1438 

1439 def prn_send(pkt): 

1440 # type: (Packet) -> None 

1441 try: 

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

1443 except KeyError: 

1444 return 

1445 if pkt.sniffed_on in xfrms: 

1446 try: 

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

1448 except Exception: 

1449 log_runtime.warning( 

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

1451 'received on %s -- dropping', 

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

1453 ) 

1454 return 

1455 else: 

1456 if isinstance(_newpkt, bool): 

1457 if not _newpkt: 

1458 return 

1459 newpkt = pkt 

1460 else: 

1461 newpkt = _newpkt 

1462 else: 

1463 newpkt = pkt 

1464 try: 

1465 sendsock.send(newpkt) 

1466 except Exception: 

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

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

1469 if prn is None: 

1470 prn = prn_send 

1471 else: 

1472 prn_orig = prn 

1473 

1474 def prn(pkt): 

1475 # type: (Packet) -> Any 

1476 prn_send(pkt) 

1477 return prn_orig(pkt) 

1478 

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

1480 *args, **kargs) 

1481 

1482 

1483@conf.commands.register 

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

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

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

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

1488 

1489 if 'iface' in kargs: 

1490 iface = kargs.get('iface') 

1491 elif 'opened_socket' in kargs: 

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

1493 else: 

1494 iface = conf.iface 

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

1496 

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

1498 # for Python 2 compatibility 

1499 i = [0] 

1500 

1501 def _cb(pkt): 

1502 # type: (Packet) -> None 

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

1504 i[0] += 1 

1505 

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

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