1## This file is part of Scapy 2## See http://www.secdev.org/projects/scapy for more informations 3## Copyright (C) Philippe Biondi <phil@secdev.org> 4## This program is published under a GPLv2 license 5 6""" 7Functions to send and receive packets. 8""" 9 10from __future__ import absolute_import, print_function 11import errno 12import itertools 13import threading 14import os 15from select import select, error as select_error 16import subprocess 17import time 18 19from scapy.consts import DARWIN, FREEBSD, OPENBSD, WINDOWS 20from scapy.data import ETH_P_ALL, MTU 21from scapy.config import conf 22from scapy.packet import Gen 23from scapy.utils import get_temp_file, PcapReader, tcpdump, wrpcap 24from scapy import plist 25from scapy.error import log_runtime, log_interactive 26from scapy.base_classes import SetGen 27from scapy.supersocket import StreamSocket, L3RawSocket, L2ListenTcpdump 28from scapy.modules import six 29from scapy.modules.six.moves import map 30if conf.route is None: 31 # unused import, only to initialize conf.route 32 import scapy.route 33from scapy.supersocket import SuperSocket 34 35################# 36## Debug class ## 37################# 38 39class debug: 40 recv=[] 41 sent=[] 42 match=[] 43 44 45#################### 46## Send / Receive ## 47#################### 48 49 50def _sndrcv_snd(pks, timeout, inter, verbose, tobesent, stopevent): 51 """Function used in the sending thread of sndrcv()""" 52 try: 53 i = 0 54 if verbose: 55 print("Begin emission:") 56 for p in tobesent: 57 pks.send(p) 58 i += 1 59 time.sleep(inter) 60 if verbose: 61 print("Finished to send %i packets." % i) 62 except SystemExit: 63 pass 64 except KeyboardInterrupt: 65 pass 66 except: 67 log_runtime.info("--- Error sending packets", exc_info=True) 68 if timeout is not None: 69 stopevent.wait(timeout) 70 stopevent.set() 71 72class _BreakException(Exception): 73 """A dummy exception used in _get_pkt() to get out of the infinite 74loop 75 76 """ 77 pass 78 79def _sndrcv_rcv(pks, tobesent, stopevent, nbrecv, notans, verbose, chainCC, 80 multi): 81 """Function used to recieve packets and check their hashret""" 82 ans = [] 83 hsent = {} 84 for i in tobesent: 85 h = i.hashret() 86 hsent.setdefault(i.hashret(), []).append(i) 87 88 if WINDOWS: 89 def _get_pkt(): 90 return pks.recv(MTU) 91 elif conf.use_bpf: 92 from scapy.arch.bpf.supersocket import bpf_select 93 def _get_pkt(): 94 if bpf_select([pks]): 95 return pks.recv() 96 elif (conf.use_pcap and not isinstance(pks, (StreamSocket, L3RawSocket, L2ListenTcpdump))) or \ 97 (not isinstance(pks, (StreamSocket, L2ListenTcpdump)) and (DARWIN or FREEBSD or OPENBSD)): 98 def _get_pkt(): 99 res = pks.nonblock_recv() 100 if res is None: 101 time.sleep(0.05) 102 return res 103 else: 104 def _get_pkt(): 105 try: 106 inp, _, _ = select([pks], [], [], 0.05) 107 except (IOError, select_error) as exc: 108 # select.error has no .errno attribute 109 if exc.args[0] != errno.EINTR: 110 raise 111 else: 112 if inp: 113 return pks.recv(MTU) 114 if stopevent.is_set(): 115 raise _BreakException() 116 117 try: 118 try: 119 while True: 120 r = _get_pkt() 121 if r is None: 122 if stopevent.is_set(): 123 break 124 continue 125 ok = False 126 h = r.hashret() 127 if h in hsent: 128 hlst = hsent[h] 129 for i, sentpkt in enumerate(hlst): 130 if r.answers(sentpkt): 131 ans.append((sentpkt, r)) 132 if verbose > 1: 133 os.write(1, b"*") 134 ok = True 135 if not multi: 136 del hlst[i] 137 notans -= 1 138 else: 139 if not hasattr(sentpkt, '_answered'): 140 notans -= 1 141 sentpkt._answered = 1 142 break 143 if notans == 0 and not multi: 144 break 145 if not ok: 146 if verbose > 1: 147 os.write(1, b".") 148 nbrecv += 1 149 if conf.debug_match: 150 debug.recv.append(r) 151 except KeyboardInterrupt: 152 if chainCC: 153 raise 154 except _BreakException: 155 pass 156 finally: 157 stopevent.set() 158 return (hsent, ans, nbrecv, notans) 159 160def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False, 161 retry=0, multi=False, rcv_pks=None): 162 """Scapy raw function to send a packet and recieve its answer. 163 WARNING: This is an internal function. Using sr/srp/sr1/srp is 164 more appropriate in many cases. 165 166 pks: SuperSocket instance to send/recieve packets 167 pkt: the packet to send 168 rcv_pks: if set, will be used instead of pks to recieve packets. packets will still 169 be sent through pks 170 nofilter: put 1 to avoid use of BPF filters 171 retry: if positive, how many times to resend unanswered packets 172 if negative, how many times to retry when no more packets are answered 173 timeout: how much time to wait after the last packet has been sent 174 verbose: set verbosity level 175 multi: whether to accept multiple answers for the same stimulus""" 176 if not isinstance(pkt, Gen): 177 pkt = SetGen(pkt) 178 if verbose is None: 179 verbose = conf.verb 180 debug.recv = plist.PacketList([],"Unanswered") 181 debug.sent = plist.PacketList([],"Sent") 182 debug.match = plist.SndRcvList([]) 183 nbrecv = 0 184 ans = [] 185 # do it here to fix random fields, so that parent and child have the same 186 tobesent = [p for p in pkt] 187 notans = len(tobesent) 188 189 if retry < 0: 190 retry = -retry 191 autostop = retry 192 else: 193 autostop = 0 194 195 while retry >= 0: 196 if timeout is not None and timeout < 0: 197 timeout = None 198 stopevent = threading.Event() 199 200 thread = threading.Thread( 201 target=_sndrcv_snd, 202 args=(pks, timeout, inter, verbose, tobesent, stopevent), 203 ) 204 thread.start() 205 206 hsent, newans, nbrecv, notans = _sndrcv_rcv( 207 (rcv_pks or pks), tobesent, stopevent, nbrecv, notans, verbose, chainCC, multi, 208 ) 209 thread.join() 210 ans.extend(newans) 211 212 remain = list(itertools.chain(*six.itervalues(hsent))) 213 if multi: 214 remain = [p for p in remain if not hasattr(p, '_answered')] 215 216 if autostop and len(remain) > 0 and len(remain) != len(tobesent): 217 retry = autostop 218 219 tobesent = remain 220 if len(tobesent) == 0: 221 break 222 retry -= 1 223 224 if conf.debug_match: 225 debug.sent=plist.PacketList(remain[:], "Sent") 226 debug.match=plist.SndRcvList(ans[:]) 227 228 # Clean the ans list to delete the field _answered 229 if multi: 230 for snd, _ in ans: 231 if hasattr(snd, '_answered'): 232 del snd._answered 233 234 if verbose: 235 print("\nReceived %i packets, got %i answers, remaining %i packets" % (nbrecv+len(ans), len(ans), notans)) 236 return plist.SndRcvList(ans), plist.PacketList(remain, "Unanswered") 237 238 239def __gen_send(s, x, inter=0, loop=0, count=None, verbose=None, realtime=None, return_packets=False, *args, **kargs): 240 if isinstance(x, str): 241 x = conf.raw_layer(load=x) 242 if not isinstance(x, Gen): 243 x = SetGen(x) 244 if verbose is None: 245 verbose = conf.verb 246 n = 0 247 if count is not None: 248 loop = -count 249 elif not loop: 250 loop = -1 251 if return_packets: 252 sent_packets = plist.PacketList() 253 try: 254 while loop: 255 dt0 = None 256 for p in x: 257 if realtime: 258 ct = time.time() 259 if dt0: 260 st = dt0+p.time-ct 261 if st > 0: 262 time.sleep(st) 263 else: 264 dt0 = ct-p.time 265 s.send(p) 266 if return_packets: 267 sent_packets.append(p) 268 n += 1 269 if verbose: 270 os.write(1,b".") 271 time.sleep(inter) 272 if loop < 0: 273 loop += 1 274 except KeyboardInterrupt: 275 pass 276 s.close() 277 if verbose: 278 print("\nSent %i packets." % n) 279 if return_packets: 280 return sent_packets 281 282@conf.commands.register 283def send(x, inter=0, loop=0, count=None, verbose=None, realtime=None, return_packets=False, socket=None, 284 *args, **kargs): 285 """Send packets at layer 3 286send(packets, [inter=0], [loop=0], [count=None], [verbose=conf.verb], [realtime=None], [return_packets=False], 287 [socket=None]) -> None""" 288 if socket is None: 289 socket = conf.L3socket(*args, **kargs) 290 return __gen_send(socket, x, inter=inter, loop=loop, count=count,verbose=verbose, 291 realtime=realtime, return_packets=return_packets) 292 293@conf.commands.register 294def sendp(x, inter=0, loop=0, iface=None, iface_hint=None, count=None, verbose=None, realtime=None, 295 return_packets=False, socket=None, *args, **kargs): 296 """Send packets at layer 2 297sendp(packets, [inter=0], [loop=0], [iface=None], [iface_hint=None], [count=None], [verbose=conf.verb], 298 [realtime=None], [return_packets=False], [socket=None]) -> None""" 299 if iface is None and iface_hint is not None and socket is None: 300 iface = conf.route.route(iface_hint)[0] 301 if socket is None: 302 socket = conf.L2socket(iface=iface, *args, **kargs) 303 return __gen_send(socket, x, inter=inter, loop=loop, count=count, 304 verbose=verbose, realtime=realtime, return_packets=return_packets) 305 306@conf.commands.register 307def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None): 308 """Send packets at layer 2 using tcpreplay for performance 309 pps: packets per second 310 mpbs: MBits per second 311 realtime: use packet's timestamp, bending time with real-time value 312 loop: number of times to process the packet list 313 file_cache: cache packets in RAM instead of reading from disk at each iteration 314 iface: output interface """ 315 if iface is None: 316 iface = conf.iface 317 argv = [conf.prog.tcpreplay, "--intf1=%s" % iface ] 318 if pps is not None: 319 argv.append("--pps=%i" % pps) 320 elif mbps is not None: 321 argv.append("--mbps=%f" % mbps) 322 elif realtime is not None: 323 argv.append("--multiplier=%f" % realtime) 324 else: 325 argv.append("--topspeed") 326 327 if loop: 328 argv.append("--loop=%i" % loop) 329 if file_cache: 330 argv.append("--preload-pcap") 331 332 f = get_temp_file() 333 argv.append(f) 334 wrpcap(f, x) 335 try: 336 subprocess.check_call(argv) 337 except KeyboardInterrupt: 338 log_interactive.info("Interrupted by user") 339 except Exception: 340 if conf.interactive: 341 log_interactive.error("Cannot execute [%s]", argv[0], exc_info=True) 342 else: 343 raise 344 finally: 345 os.unlink(f) 346 347 348 349 350 351@conf.commands.register 352def sr(x, promisc=None, filter=None, iface=None, nofilter=0, *args,**kargs): 353 """Send and receive packets at layer 3 354nofilter: put 1 to avoid use of BPF filters 355retry: if positive, how many times to resend unanswered packets 356 if negative, how many times to retry when no more packets are answered 357timeout: how much time to wait after the last packet has been sent 358verbose: set verbosity level 359multi: whether to accept multiple answers for the same stimulus 360filter: provide a BPF filter 361iface: listen answers only on the given interface""" 362 if "timeout" not in kargs: 363 kargs["timeout"] = -1 364 s = conf.L3socket(promisc=promisc, filter=filter, iface=iface, nofilter=nofilter) 365 result = sndrcv(s, x, *args, **kargs) 366 s.close() 367 return result 368 369@conf.commands.register 370def sr1(x, promisc=None, filter=None, iface=None, nofilter=0, *args,**kargs): 371 """Send packets at layer 3 and return only the first answer 372nofilter: put 1 to avoid use of BPF filters 373retry: if positive, how many times to resend unanswered packets 374 if negative, how many times to retry when no more packets are answered 375timeout: how much time to wait after the last packet has been sent 376verbose: set verbosity level 377multi: whether to accept multiple answers for the same stimulus 378filter: provide a BPF filter 379iface: listen answers only on the given interface""" 380 if "timeout" not in kargs: 381 kargs["timeout"] = -1 382 s=conf.L3socket(promisc=promisc, filter=filter, nofilter=nofilter, iface=iface) 383 ans, _ = sndrcv(s, x, *args, **kargs) 384 s.close() 385 if len(ans) > 0: 386 return ans[0][1] 387 else: 388 return None 389 390@conf.commands.register 391def srp(x, promisc=None, iface=None, iface_hint=None, filter=None, nofilter=0, type=ETH_P_ALL, *args,**kargs): 392 """Send and receive packets at layer 2 393nofilter: put 1 to avoid use of BPF filters 394retry: if positive, how many times to resend unanswered packets 395 if negative, how many times to retry when no more packets are answered 396timeout: how much time to wait after the last packet has been sent 397verbose: set verbosity level 398multi: whether to accept multiple answers for the same stimulus 399filter: provide a BPF filter 400iface: work only on the given interface""" 401 if "timeout" not in kargs: 402 kargs["timeout"] = -1 403 if iface is None and iface_hint is not None: 404 iface = conf.route.route(iface_hint)[0] 405 s = conf.L2socket(promisc=promisc, iface=iface, filter=filter, nofilter=nofilter, type=type) 406 result = sndrcv(s, x, *args, **kargs) 407 s.close() 408 return result 409 410@conf.commands.register 411def srp1(*args,**kargs): 412 """Send and receive packets at layer 2 and return only the first answer 413nofilter: put 1 to avoid use of BPF filters 414retry: if positive, how many times to resend unanswered packets 415 if negative, how many times to retry when no more packets are answered 416timeout: how much time to wait after the last packet has been sent 417verbose: set verbosity level 418multi: whether to accept multiple answers for the same stimulus 419filter: provide a BPF filter 420iface: work only on the given interface""" 421 if "timeout" not in kargs: 422 kargs["timeout"] = -1 423 ans, _ = srp(*args, **kargs) 424 if len(ans) > 0: 425 return ans[0][1] 426 else: 427 return None 428 429# SEND/RECV LOOP METHODS 430 431def __sr_loop(srfunc, pkts, prn=lambda x:x[1].summary(), prnfail=lambda x:x.summary(), inter=1, timeout=None, count=None, verbose=None, store=1, *args, **kargs): 432 n = 0 433 r = 0 434 ct = conf.color_theme 435 if verbose is None: 436 verbose = conf.verb 437 parity = 0 438 ans=[] 439 unans=[] 440 if timeout is None: 441 timeout = min(2*inter, 5) 442 try: 443 while True: 444 parity ^= 1 445 col = [ct.even,ct.odd][parity] 446 if count is not None: 447 if count == 0: 448 break 449 count -= 1 450 start = time.time() 451 if verbose > 1: 452 print("\rsend...\r", end=' ') 453 res = srfunc(pkts, timeout=timeout, verbose=0, chainCC=True, *args, **kargs) 454 n += len(res[0])+len(res[1]) 455 r += len(res[0]) 456 if verbose > 1 and prn and len(res[0]) > 0: 457 msg = "RECV %i:" % len(res[0]) 458 print("\r"+ct.success(msg), end=' ') 459 for p in res[0]: 460 print(col(prn(p))) 461 print(" "*len(msg), end=' ') 462 if verbose > 1 and prnfail and len(res[1]) > 0: 463 msg = "fail %i:" % len(res[1]) 464 print("\r"+ct.fail(msg), end=' ') 465 for p in res[1]: 466 print(col(prnfail(p))) 467 print(" "*len(msg), end=' ') 468 if verbose > 1 and not (prn or prnfail): 469 print("recv:%i fail:%i" % tuple(map(len, res[:2]))) 470 if store: 471 ans += res[0] 472 unans += res[1] 473 end=time.time() 474 if end-start < inter: 475 time.sleep(inter+start-end) 476 except KeyboardInterrupt: 477 pass 478 479 if verbose and n>0: 480 print(ct.normal("\nSent %i packets, received %i packets. %3.1f%% hits." % (n,r,100.0*r/n))) 481 return plist.SndRcvList(ans),plist.PacketList(unans) 482 483@conf.commands.register 484def srloop(pkts, *args, **kargs): 485 """Send a packet at layer 3 in loop and print the answer each time 486srloop(pkts, [prn], [inter], [count], ...) --> None""" 487 return __sr_loop(sr, pkts, *args, **kargs) 488 489@conf.commands.register 490def srploop(pkts, *args, **kargs): 491 """Send a packet at layer 2 in loop and print the answer each time 492srloop(pkts, [prn], [inter], [count], ...) --> None""" 493 return __sr_loop(srp, pkts, *args, **kargs) 494 495# SEND/RECV FLOOD METHODS 496 497def sndrcvflood(pks, pkt, inter=0, verbose=None, chainCC=False, prn=lambda x: x): 498 if not verbose: 499 verbose = conf.verb 500 if not isinstance(pkt, Gen): 501 pkt = SetGen(pkt) 502 tobesent = [p for p in pkt] 503 504 stopevent = threading.Event() 505 count_packets = six.moves.queue.Queue() 506 507 def send_in_loop(tobesent, stopevent, count_packets=count_packets): 508 """Infinite generator that produces the same packet until stopevent is triggered.""" 509 while True: 510 for p in tobesent: 511 if stopevent.is_set(): 512 raise StopIteration() 513 count_packets.put(0) 514 yield p 515 516 infinite_gen = send_in_loop(tobesent, stopevent) 517 518 # We don't use _sndrcv_snd verbose (it messes the logs up as in a thread that ends after recieving) 519 thread = threading.Thread( 520 target=_sndrcv_snd, 521 args=(pks, None, inter, False, infinite_gen, stopevent), 522 ) 523 thread.start() 524 525 hsent, ans, nbrecv, notans = _sndrcv_rcv(pks, tobesent, stopevent, 0, len(tobesent), verbose, chainCC, False) 526 thread.join() 527 remain = list(itertools.chain(*six.itervalues(hsent))) 528 # Apply prn 529 ans = [(x, prn(y)) for (x, y) in ans] 530 531 if verbose: 532 print("\nReceived %i packets, got %i answers, remaining %i packets. Sent a total of %i packets." % (nbrecv+len(ans), len(ans), notans, count_packets.qsize())) 533 count_packets.empty() 534 del count_packets 535 536 return plist.SndRcvList(ans), plist.PacketList(remain, "Unanswered") 537 538@conf.commands.register 539def srflood(x, promisc=None, filter=None, iface=None, nofilter=None, *args,**kargs): 540 """Flood and receive packets at layer 3 541prn: function applied to packets received 542unique: only consider packets whose print 543nofilter: put 1 to avoid use of BPF filters 544filter: provide a BPF filter 545iface: listen answers only on the given interface""" 546 s = conf.L3socket(promisc=promisc, filter=filter, iface=iface, nofilter=nofilter) 547 r=sndrcvflood(s,x,*args,**kargs) 548 s.close() 549 return r 550 551@conf.commands.register 552def sr1flood(x, promisc=None, filter=None, iface=None, nofilter=0, *args,**kargs): 553 """Flood and receive packets at layer 3 and return only the first answer 554prn: function applied to packets received 555verbose: set verbosity level 556nofilter: put 1 to avoid use of BPF filters 557filter: provide a BPF filter 558iface: listen answers only on the given interface""" 559 s=conf.L3socket(promisc=promisc, filter=filter, nofilter=nofilter, iface=iface) 560 ans, _ = sndrcvflood(s, x, *args, **kargs) 561 s.close() 562 if len(ans) > 0: 563 return ans[0][1] 564 else: 565 return None 566 567@conf.commands.register 568def srpflood(x, promisc=None, filter=None, iface=None, iface_hint=None, nofilter=None, *args,**kargs): 569 """Flood and receive packets at layer 2 570prn: function applied to packets received 571unique: only consider packets whose print 572nofilter: put 1 to avoid use of BPF filters 573filter: provide a BPF filter 574iface: listen answers only on the given interface""" 575 if iface is None and iface_hint is not None: 576 iface = conf.route.route(iface_hint)[0] 577 s = conf.L2socket(promisc=promisc, filter=filter, iface=iface, nofilter=nofilter) 578 r=sndrcvflood(s,x,*args,**kargs) 579 s.close() 580 return r 581 582@conf.commands.register 583def srp1flood(x, promisc=None, filter=None, iface=None, nofilter=0, *args,**kargs): 584 """Flood and receive packets at layer 2 and return only the first answer 585prn: function applied to packets received 586verbose: set verbosity level 587nofilter: put 1 to avoid use of BPF filters 588filter: provide a BPF filter 589iface: listen answers only on the given interface""" 590 s=conf.L2socket(promisc=promisc, filter=filter, nofilter=nofilter, iface=iface) 591 ans, _ = sndrcvflood(s, x, *args, **kargs) 592 s.close() 593 if len(ans) > 0: 594 return ans[0][1] 595 else: 596 return None 597 598# SNIFF METHODS 599 600@conf.commands.register 601def sniff(count=0, store=True, offline=None, prn=None, lfilter=None, 602 L2socket=None, timeout=None, opened_socket=None, 603 stop_filter=None, iface=None, *arg, **karg): 604 """ 605 606Sniff packets and return a list of packets. 607 608Arguments: 609 610 count: number of packets to capture. 0 means infinity. 611 612 store: whether to store sniffed packets or discard them 613 614 prn: function to apply to each packet. If something is returned, it 615 is displayed. 616 617 Ex: prn = lambda x: x.summary() 618 619 filter: BPF filter to apply. 620 621 lfilter: Python function applied to each packet to determine if 622 further action may be done. 623 624 Ex: lfilter = lambda x: x.haslayer(Padding) 625 626 offline: PCAP file (or list of PCAP files) to read packets from, 627 instead of sniffing them 628 629 timeout: stop sniffing after a given time (default: None). 630 631 L2socket: use the provided L2socket (default: use conf.L2listen). 632 633 opened_socket: provide an object (or a list of objects) ready to use 634 .recv() on. 635 636 stop_filter: Python function applied to each packet to determine if 637 we have to stop the capture after this packet. 638 639 Ex: stop_filter = lambda x: x.haslayer(TCP) 640 641 iface: interface or list of interfaces (default: None for sniffing 642 on all interfaces). 643 644The iface, offline and opened_socket parameters can be either an 645element, a list of elements, or a dict object mapping an element to a 646label (see examples below). 647 648Examples: 649 650 >>> sniff(filter="arp") 651 652 >>> sniff(lfilter=lambda pkt: ARP in pkt) 653 654 >>> sniff(iface="eth0", prn=Packet.summary) 655 656 >>> sniff(iface=["eth0", "mon0"], 657 ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, 658 ... pkt.summary())) 659 660 >>> sniff(iface={"eth0": "Ethernet", "mon0": "Wifi"}, 661 ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, 662 ... pkt.summary())) 663 664 """ 665 c = 0 666 sniff_sockets = {} # socket: label dict 667 if opened_socket is not None: 668 if isinstance(opened_socket, list): 669 sniff_sockets.update((s, "socket%d" % i) 670 for i, s in enumerate(opened_socket)) 671 elif isinstance(opened_socket, dict): 672 sniff_sockets.update((s, label) 673 for s, label in six.iteritems(opened_socket)) 674 else: 675 sniff_sockets[opened_socket] = "socket0" 676 if offline is not None: 677 flt = karg.get('filter') 678 if isinstance(offline, list): 679 sniff_sockets.update((PcapReader( 680 fname if flt is None else 681 tcpdump(fname, args=["-w", "-", flt], getfd=True) 682 ), fname) for fname in offline) 683 elif isinstance(offline, dict): 684 sniff_sockets.update((PcapReader( 685 fname if flt is None else 686 tcpdump(fname, args=["-w", "-", flt], getfd=True) 687 ), label) for fname, label in six.iteritems(offline)) 688 else: 689 sniff_sockets[PcapReader( 690 offline if flt is None else 691 tcpdump(offline, args=["-w", "-", flt], getfd=True) 692 )] = offline 693 if not sniff_sockets or iface is not None: 694 if L2socket is None: 695 L2socket = conf.L2listen 696 if isinstance(iface, list): 697 sniff_sockets.update( 698 (L2socket(type=ETH_P_ALL, iface=ifname, *arg, **karg), ifname) 699 for ifname in iface 700 ) 701 elif isinstance(iface, dict): 702 sniff_sockets.update( 703 (L2socket(type=ETH_P_ALL, iface=ifname, *arg, **karg), iflabel) 704 for ifname, iflabel in six.iteritems(iface) 705 ) 706 else: 707 sniff_sockets[L2socket(type=ETH_P_ALL, iface=iface, 708 *arg, **karg)] = iface 709 lst = [] 710 if timeout is not None: 711 stoptime = time.time()+timeout 712 remain = None 713 read_allowed_exceptions = () 714 if conf.use_bpf: 715 from scapy.arch.bpf.supersocket import bpf_select 716 def _select(sockets): 717 return bpf_select(sockets, remain) 718 elif WINDOWS: 719 from scapy.arch.pcapdnet import PcapTimeoutElapsed 720 read_allowed_exceptions = (PcapTimeoutElapsed,) 721 def _select(sockets): 722 try: 723 return sockets 724 except PcapTimeoutElapsed: 725 return [] 726 else: 727 def _select(sockets): 728 try: 729 return select(sockets, [], [], remain)[0] 730 except select_error as exc: 731 # Catch 'Interrupted system call' errors 732 if exc[0] == errno.EINTR: 733 return [] 734 raise 735 try: 736 while sniff_sockets: 737 if timeout is not None: 738 remain = stoptime-time.time() 739 if remain <= 0: 740 break 741 ins = _select(sniff_sockets) 742 for s in ins: 743 try: 744 p = s.recv() 745 except read_allowed_exceptions: 746 continue 747 if p is None: 748 del sniff_sockets[s] 749 break 750 if lfilter and not lfilter(p): 751 continue 752 p.sniffed_on = sniff_sockets[s] 753 if store: 754 lst.append(p) 755 c += 1 756 if prn: 757 r = prn(p) 758 if r is not None: 759 print(r) 760 if stop_filter and stop_filter(p): 761 sniff_sockets = [] 762 break 763 if 0 < count <= c: 764 sniff_sockets = [] 765 break 766 except KeyboardInterrupt: 767 pass 768 if opened_socket is None: 769 for s in sniff_sockets: 770 s.close() 771 return plist.PacketList(lst,"Sniffed") 772 773 774@conf.commands.register 775def bridge_and_sniff(if1, if2, xfrm12=None, xfrm21=None, prn=None, L2socket=None, 776 *args, **kargs): 777 """Forward traffic between interfaces if1 and if2, sniff and return 778the exchanged packets. 779 780Arguments: 781 782 if1, if2: the interfaces to use (interface names or opened sockets). 783 784 xfrm12: a function to call when forwarding a packet from if1 to 785 if2. If it returns True, the packet is forwarded as it. If it 786 returns False or None, the packet is discarded. If it returns a 787 packet, this packet is forwarded instead of the original packet 788 one. 789 790 xfrm21: same as xfrm12 for packets forwarded from if2 to if1. 791 792 The other arguments are the same than for the function sniff(), 793 except for offline, opened_socket and iface that are ignored. 794 See help(sniff) for more. 795 796 """ 797 for arg in ['opened_socket', 'offline', 'iface']: 798 if arg in kargs: 799 log_runtime.warning("Argument %s cannot be used in " 800 "bridge_and_sniff() -- ignoring it.", arg) 801 del kargs[arg] 802 def _init_socket(iface, count): 803 if isinstance(iface, SuperSocket): 804 return iface, "iface%d" % count 805 else: 806 return (L2socket or conf.L2socket)(iface=iface), iface 807 sckt1, if1 = _init_socket(if1, 1) 808 sckt2, if2 = _init_socket(if2, 2) 809 peers = {if1: sckt2, if2: sckt1} 810 xfrms = {} 811 if xfrm12 is not None: 812 xfrms[if1] = xfrm12 813 if xfrm21 is not None: 814 xfrms[if2] = xfrm21 815 def prn_send(pkt): 816 try: 817 sendsock = peers[pkt.sniffed_on] 818 except KeyError: 819 return 820 if pkt.sniffed_on in xfrms: 821 try: 822 newpkt = xfrms[pkt.sniffed_on](pkt) 823 except: 824 log_runtime.warning( 825 'Exception in transformation function for packet [%s] ' 826 'received on %s -- dropping', 827 pkt.summary(), pkt.sniffed_on, exc_info=True 828 ) 829 return 830 else: 831 if newpkt is True: 832 newpkt = pkt.original 833 elif not newpkt: 834 return 835 else: 836 newpkt = pkt.original 837 try: 838 sendsock.send(newpkt) 839 except: 840 log_runtime.warning('Cannot forward packet [%s] received on %s', 841 pkt.summary(), pkt.sniffed_on, exc_info=True) 842 if prn is None: 843 prn = prn_send 844 else: 845 prn_orig = prn 846 def prn(pkt): 847 prn_send(pkt) 848 return prn_orig(pkt) 849 850 return sniff(opened_socket={sckt1: if1, sckt2: if2}, prn=prn, 851 *args, **kargs) 852 853 854@conf.commands.register 855def tshark(*args,**kargs): 856 """Sniff packets and print them calling pkt.summary(), a bit like text wireshark""" 857 print("Capturing on '" + str(kargs.get('iface') if 'iface' in kargs else conf.iface) + "'") 858 i = [0] # This should be a nonlocal variable, using a mutable object for Python 2 compatibility 859 def _cb(pkt): 860 print("%5d\t%s" % (i[0], pkt.summary())) 861 i[0] += 1 862 sniff(prn=_cb, store=False, *args, **kargs) 863 print("\n%d packet%s captured" % (i[0], 's' if i[0] > 1 else '')) 864