From a80424e91d3489af69a7a90f7e3770c6d0777e72 Mon Sep 17 00:00:00 2001 From: Pierre LALET <pierre.lalet@cea.fr> Date: Fri, 25 Aug 2017 12:29:28 +0200 Subject: [PATCH] sendrecv: clean-up --- scapy/sendrecv.py | 152 +++++++++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 69 deletions(-) diff --git a/scapy/sendrecv.py b/scapy/sendrecv.py index 04dd3976..dee5a746 100644 --- a/scapy/sendrecv.py +++ b/scapy/sendrecv.py @@ -47,7 +47,8 @@ class debug: #################### -def _sndrcv_snd(pks, timeout, inter, verbose, tobesent, all_stimuli, stopevent): +def _sndrcv_snd(pks, timeout, inter, verbose, tobesent, stopevent): + """Function used in the sending thread of sndrcv()""" try: i = 0 if verbose: @@ -63,8 +64,7 @@ def _sndrcv_snd(pks, timeout, inter, verbose, tobesent, all_stimuli, stopevent): except KeyboardInterrupt: pass except: - log_runtime.exception("--- Error sending packets") - log_runtime.info("--- Error sending packets") + log_runtime.info("--- Error sending packets", exc_info=True) if timeout is not None: stopevent.wait(timeout) stopevent.set() @@ -80,8 +80,6 @@ loop def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False, retry=0, multi=False): - if conf.use_bpf: - from scapy.arch.bpf.supersocket import bpf_select if not isinstance(pkt, Gen): pkt = SetGen(pkt) if verbose is None: @@ -92,7 +90,7 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False, nbrecv=0 ans = [] # do it here to fix random fields, so that parent and child have the same - all_stimuli = tobesent = [p for p in pkt] + tobesent = [p for p in pkt] notans = len(tobesent) hsent={} @@ -106,43 +104,43 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False, else: autostop = 0 + if WINDOWS: + def _get_pkt(): + return pks.recv(MTU) + elif conf.use_bpf: + from scapy.arch.bpf.supersocket import bpf_select + def _get_pkt(): + if bpf_select([pks]): + return pks.recv() + elif conf.use_pcap or (not isinstance(pks, StreamSocket) + and (DARWIN or FREEBSD or OPENBSD)): + def _get_pkt(): + res = pks.nonblock_recv() + if res is None: + time.sleep(0.05) + return res + else: + def _get_pkt(): + try: + inp, _, _ = select([pks], [], [], 0.05) + except (IOError, select_error) as exc: + # select.error has no .errno attribute + if exc.args[0] != errno.EINTR: + raise + else: + if inp: + return pks.recv(MTU) + if stopevent.is_set(): + raise _BreakException() + while retry >= 0: if timeout < 0: timeout = None stopevent = threading.Event() - if WINDOWS: - def _get_pkt(): - return pks.recv(MTU) - elif conf.use_bpf: - def _get_pkt(): - if bpf_select([pks]): - return pks.recv() - elif conf.use_pcap or (not isinstance(pks, StreamSocket) - and (DARWIN or FREEBSD or OPENBSD)): - def _get_pkt(): - res = pks.nonblock_recv() - if res is None: - time.sleep(0.05) - return res - else: - def _get_pkt(): - try: - inp, _, _ = select([pks], [], [], 0.05) - except (IOError, select_error) as exc: - # select.error has no .errno attribute - if exc.args[0] != errno.EINTR: - raise - else: - if inp: - return pks.recv(MTU) - if stopevent.is_set(): - raise _BreakException() - thread = threading.Thread( target=_sndrcv_snd, - args=(pks, timeout, inter, verbose, tobesent, all_stimuli, - stopevent), + args=(pks, timeout, inter, verbose, tobesent, stopevent), ) thread.start() @@ -203,7 +201,7 @@ def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=False, retry -= 1 if conf.debug_match: - debug.sent=plist.PacketList(remain[:],"Sent") + debug.sent=plist.PacketList(remain[:], "Sent") debug.match=plist.SndRcvList(ans[:]) # Clean the ans list to delete the field _answered @@ -565,33 +563,49 @@ iface: listen answers only on the given interface""" def sniff(count=0, store=True, offline=None, prn=None, lfilter=None, L2socket=None, timeout=None, opened_socket=None, stop_filter=None, iface=None, *arg, **karg): - """Sniff packets -sniff([count=0,] [prn=None,] [store=1,] [offline=None,] -[lfilter=None,] + L2ListenSocket args) -> list of packets - -count: number of packets to capture. 0 means infinity -store: whether to store sniffed packets or discard them -prn: function to apply to each packet. If something is returned, it - is displayed. - Ex: prn = lambda x: x.summary() -filter: BPF filter -lfilter: python function applied to each packet to determine if further - action may be done - Ex: lfilter = lambda x: x.haslayer(Padding) -offline: pcap file (or list of pcap files) to read packets from, instead - of sniffing them -timeout: stop sniffing after a given time (default: None) -L2socket: use the provided L2socket (default: use conf.L2listen) -opened_socket: provide an object (or a list of objects) ready to use .recv() on -stop_filter: python function applied to each packet to determine if we have - to stop the capture after this packet. - Ex: stop_filter = lambda x: x.haslayer(TCP) -iface: interface or list of interfaces (default: None for sniffing on - all interfaces) + """ + +Sniff packets and return a list of packets. + +Arguments: + + count: number of packets to capture. 0 means infinity. + + store: whether to store sniffed packets or discard them + + prn: function to apply to each packet. If something is returned, it + is displayed. + + Ex: prn = lambda x: x.summary() + + filter: BPF filter to apply. + + lfilter: Python function applied to each packet to determine if + further action may be done. + + Ex: lfilter = lambda x: x.haslayer(Padding) + + offline: PCAP file (or list of PCAP files) to read packets from, + instead of sniffing them + + timeout: stop sniffing after a given time (default: None). + + L2socket: use the provided L2socket (default: use conf.L2listen). + + opened_socket: provide an object (or a list of objects) ready to use + .recv() on. + + stop_filter: Python function applied to each packet to determine if + we have to stop the capture after this packet. + + Ex: stop_filter = lambda x: x.haslayer(TCP) + + iface: interface or list of interfaces (default: None for sniffing + on all interfaces). The iface, offline and opened_socket parameters can be either an element, a list of elements, or a dict object mapping an element to a -label (see examples below) +label (see examples below). Examples: @@ -602,14 +616,14 @@ Examples: >>> sniff(iface="eth0", prn=Packet.summary) >>> sniff(iface=["eth0", "mon0"], - ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, pkt.summary())) + ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, + ... pkt.summary())) >>> sniff(iface={"eth0": "Ethernet", "mon0": "Wifi"}, - ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, pkt.summary())) + ... prn=lambda pkt: "%s: %s" % (pkt.sniffed_on, + ... pkt.summary())) """ - if conf.use_bpf: - from scapy.arch.bpf.supersocket import bpf_select c = 0 sniff_sockets = {} # socket: label dict if opened_socket is not None: @@ -660,6 +674,7 @@ Examples: remain = None read_allowed_exceptions = () if conf.use_bpf: + from scapy.arch.bpf.supersocket import bpf_select def _select(sockets): return bpf_select(sockets, remain) elif WINDOWS: @@ -680,7 +695,6 @@ Examples: return [] raise try: - stop_event = False while sniff_sockets: if timeout is not None: remain = stoptime-time.time() @@ -720,9 +734,9 @@ Examples: @conf.commands.register -def bridge_and_sniff(if1, if2, count=0, store=1, offline=None, prn=None, - lfilter=None, L2socket=None, timeout=None, - stop_filter=None, *args, **kargs): +def bridge_and_sniff(if1, if2, count=0, store=1, prn=None, lfilter=None, + L2socket=None, timeout=None, stop_filter=None, *args, + **kargs): """Forward traffic between two interfaces and sniff packets exchanged bridge_and_sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2Socket args) -> list of packets -- GitLab