def _parse_tcpreplay_result(stdout, stderr, argv, results_dict): """ Parse the output of tcpreplay and modify the results_dict to populate output information. Tested with tcpreplay v3.4.4 Tested with tcpreplay v4.1.2 :param stdout: stdout of tcpreplay subprocess call :param stderr: stderr of tcpreplay subprocess call :param argv: the command used in the subprocess call :param results_dict: empty dictionary to be modified when putting in results :return: None """ try: stdout = str(stdout, "utf-8").replace("\nRated: ", "\t\tRated: ").replace("\t", "").split("\n") stderr = str(stderr, "utf-8").replace("\t", "").split("\n") actual = stdout[0].split(" ") results_dict["packets"] = int(actual[1]), results_dict["bytes"] = int(actual[3][1:]), results_dict["time"] = float(actual[7]), results_dict["bps"] = float(actual[9]), results_dict["mbps"] = float(actual[11]), results_dict["pps"] = float(actual[13]), results_dict["attempted"] = int(stdout[2].split(" ")[-1:][0]), results_dict["successful"] = int(stdout[3].split(" ")[-1:][0]), results_dict["failed"] = int(stdout[4].split(" ")[-1:][0]), results_dict["retried_enobufs"] = int(stdout[5].split(" ")[-1:][0]), results_dict["retried_eagain"] = int(stdout[6].split(" ")[-1][0]), results_dict["command"] = str(argv), results_dict["warnings"] = stderr[:len(stderr) - 1] except Exception as parse_exception: log_runtime.error("Error parsing output: " + str(parse_exception))
def fileno(self): if WINDOWS: log_runtime.error("Cannot get selectable PCAP fd on Windows") return -1 else: # This does not exist under Windows return pcap_get_selectable_fd(self.pcap)
def send(self, x): try: sx = raw(x) x.sent_time = time.time() self.outs.sendto(sx, (x.dst, 0)) except socket.error as msg: log_runtime.error(msg)
def __init__(self, device, snaplen, promisc, to_ms, monitor=None): device = network_name(device) self.errbuf = create_string_buffer(PCAP_ERRBUF_SIZE) self.iface = create_string_buffer(device.encode("utf8")) self.dtl = None if monitor: if WINDOWS and not conf.use_npcap: raise OSError("On Windows, this feature requires NPcap !") # Npcap-only functions from scapy.libs.winpcapy import pcap_create, \ pcap_set_snaplen, pcap_set_promisc, \ pcap_set_timeout, pcap_set_rfmon, pcap_activate self.pcap = pcap_create(self.iface, self.errbuf) pcap_set_snaplen(self.pcap, snaplen) pcap_set_promisc(self.pcap, promisc) pcap_set_timeout(self.pcap, to_ms) if pcap_set_rfmon(self.pcap, 1) != 0: log_runtime.error("Could not set monitor mode") if pcap_activate(self.pcap) != 0: raise OSError("Could not activate the pcap handler") else: self.pcap = pcap_open_live(self.iface, snaplen, promisc, to_ms, self.errbuf) error = bytes(bytearray(self.errbuf)).strip(b"\x00") if error: raise OSError(error) if WINDOWS: # Winpcap/Npcap exclusive: make every packet to be instantly # returned, and not buffered within Winpcap/Npcap pcap_setmintocopy(self.pcap, 0) self.header = POINTER(pcap_pkthdr)() self.pkt_data = POINTER(c_ubyte)() self.bpf_program = bpf_program()
def _parse_tcpreplay_result(stdout, stderr, argv): """ Parse the output of tcpreplay and modify the results_dict to populate output information. # noqa: E501 Tested with tcpreplay v3.4.4 Tested with tcpreplay v4.1.2 :param stdout: stdout of tcpreplay subprocess call :param stderr: stderr of tcpreplay subprocess call :param argv: the command used in the subprocess call :return: dictionary containing the results """ try: results_dict = {} stdout = plain_str(stdout).replace("\nRated: ", "\t\tRated: ").replace( "\t", "").split("\n") # noqa: E501 stderr = plain_str(stderr).replace("\t", "").split("\n") actual = [x for x in stdout[0].split(" ") if x] results_dict["packets"] = int(actual[1]) results_dict["bytes"] = int(actual[3][1:]) results_dict["time"] = float(actual[7]) results_dict["bps"] = float(actual[10]) results_dict["mbps"] = float(actual[12]) results_dict["pps"] = float(actual[14]) results_dict["attempted"] = int(stdout[2].split(" ")[-1:][0]) results_dict["successful"] = int(stdout[3].split(" ")[-1:][0]) results_dict["failed"] = int(stdout[4].split(" ")[-1:][0]) results_dict["retried_enobufs"] = int(stdout[5].split(" ")[-1:][0]) results_dict["retried_eagain"] = int(stdout[6].split(" ")[-1][0]) results_dict["command"] = str(argv) results_dict["warnings"] = stderr[:len(stderr) - 1] return results_dict except Exception as parse_exception: log_runtime.error("Error parsing output: " + str(parse_exception)) return {}
def __exit__(self, exc_type, exc_value, traceback): if isinstance(exc_value, (OSError, TypeError)): msg = "%s: executing %r failed" % (self.name, self.prog) if self.prog else "Could not execute %s, is it installed ?" % self.name if not conf.interactive: raise OSError(msg) else: log_runtime.error(msg, exc_info=True) return True # Suppress the exception
def guess_payload_class(self, payload): try: dlpdu_type = payload[0] return EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[dlpdu_type] except KeyError: log_runtime.error('{}.guess_payload_class() - unknown or invalid ' 'DLPDU type'.format(self.__class__.__name__)) return Packet.guess_payload_class(self, payload)
def p0f_getlocalsigs(): """This function returns a dictionary of signatures indexed by p0f db (e.g., p0f_kdb, p0fa_kdb, ...) for the local TCP/IP stack. You need to have your firewall at least accepting the TCP packets from/to a high port (30000 <= x <= 40000) on your loopback interface. Please note that the generated signatures come from the loopback interface and may (are likely to) be different than those generated on "normal" interfaces.""" pid = os.fork() port = random.randint(30000, 40000) if pid > 0: # parent: sniff result = {} def addresult(res): # TODO: wildcard window size in some cases? and maybe some # other values? if res[0] not in result: result[res[0]] = [res[1]] else: if res[1] not in result[res[0]]: result[res[0]].append(res[1]) # XXX could we try with a "normal" interface using other hosts iface = conf.route.route('127.0.0.1')[0] # each packet is seen twice: S + RA, S + SA + A + FA + A # XXX are the packets also seen twice on non Linux systems ? count = 14 pl = sniff(iface=iface, filter='tcp and port ' + str(port), count=count, timeout=3) # noqa: E501 for pkt in pl: for elt in packet2p0f(pkt): addresult(elt) os.waitpid(pid, 0) elif pid < 0: log_runtime.error("fork error") else: # child: send # XXX erk time.sleep(1) s1 = socket.socket(socket.AF_INET, type=socket.SOCK_STREAM) # S & RA try: s1.connect(('127.0.0.1', port)) except socket.error: pass # S, SA, A, FA, A s1.bind(('127.0.0.1', port)) s1.connect(('127.0.0.1', port)) # howto: get an RST w/o ACK packet s1.close() os._exit(0) return result
def guess_payload_class(self, payload): try: dlpdu_type = payload[0] return EtherCat.ETHERCAT_TYPE12_DLPDU_TYPES[dlpdu_type] except KeyError: log_runtime.error( '{}.guess_payload_class() - unknown or invalid ' 'DLPDU type'.format(self.__class__.__name__)) return Packet.guess_payload_class(self, payload)
def setfilter(self, f): filter_exp = create_string_buffer(f.encode("utf8")) if pcap_compile(self.pcap, byref(self.bpf_program), filter_exp, 0, -1) == -1: # noqa: E501 log_runtime.error("Could not compile filter expression %s", f) return False else: if pcap_setfilter(self.pcap, byref(self.bpf_program)) == -1: log_runtime.error("Could not set filter %s", f) return False return True
def _parse_tcpreplay_result(stdout_b, stderr_b, argv): # type: (bytes, bytes, List[str]) -> Dict[str, Any] """ Parse the output of tcpreplay and modify the results_dict to populate output information. # noqa: E501 Tested with tcpreplay v3.4.4 Tested with tcpreplay v4.1.2 :param stdout: stdout of tcpreplay subprocess call :param stderr: stderr of tcpreplay subprocess call :param argv: the command used in the subprocess call :return: dictionary containing the results """ try: results = {} stdout = plain_str(stdout_b).lower() stderr = plain_str(stderr_b).strip().split("\n") elements = { "actual": (int, int, float), "rated": (float, float, float), "flows": (int, float, int, int), "attempted": (int,), "successful": (int,), "failed": (int,), "truncated": (int,), "retried packets (eno": (int,), "retried packets (eag": (int,), } multi = { "actual": ("packets", "bytes", "time"), "rated": ("bps", "mbps", "pps"), "flows": ("flows", "fps", "flow_packets", "non_flow"), "retried packets (eno": ("retried_enobufs",), "retried packets (eag": ("retried_eagain",), } float_reg = r"([0-9]*\.[0-9]+|[0-9]+)" int_reg = r"([0-9]+)" any_reg = r"[^0-9]*" r_types = {int: int_reg, float: float_reg} for line in stdout.split("\n"): line = line.strip() for elt, _types in elements.items(): if line.startswith(elt): regex = any_reg.join([r_types[x] for x in _types]) matches = re.search(regex, line) for i, typ in enumerate(_types): name = multi.get(elt, [elt])[i] if matches: results[name] = typ(matches.group(i + 1)) results["command"] = " ".join(argv) results["warnings"] = stderr[:-1] return results except Exception as parse_exception: if not conf.interactive: raise log_runtime.error("Error parsing output: %s", parse_exception) return {}
def _parse_tcpreplay_result(stdout, stderr, argv): """ Parse the output of tcpreplay and modify the results_dict to populate output information. # noqa: E501 Tested with tcpreplay v3.4.4 Tested with tcpreplay v4.1.2 :param stdout: stdout of tcpreplay subprocess call :param stderr: stderr of tcpreplay subprocess call :param argv: the command used in the subprocess call :return: dictionary containing the results """ try: results = {} stdout = plain_str(stdout).lower() stderr = plain_str(stderr).strip().split("\n") elements = { "actual": (int, int, float), "rated": (float, float, float), "flows": (int, float, int, int), "attempted": (int,), "successful": (int,), "failed": (int,), "truncated": (int,), "retried packets (eno": (int,), "retried packets (eag": (int,), } multi = { "actual": ("packets", "bytes", "time"), "rated": ("bps", "mbps", "pps"), "flows": ("flows", "fps", "flow_packets", "non_flow"), "retried packets (eno": ("retried_enobufs",), "retried packets (eag": ("retried_eagain",), } float_reg = r"([0-9]*\.[0-9]+|[0-9]+)" int_reg = r"([0-9]+)" any_reg = r"[^0-9]*" r_types = {int: int_reg, float: float_reg} for line in stdout.split("\n"): line = line.strip() for elt, _types in elements.items(): if line.startswith(elt): regex = any_reg.join([r_types[x] for x in _types]) matches = re.search(regex, line) for i, typ in enumerate(_types): name = multi.get(elt, [elt])[i] results[name] = typ(matches.group(i + 1)) results["command"] = " ".join(argv) results["warnings"] = stderr[:-1] return results except Exception as parse_exception: if not conf.interactive: raise log_runtime.error("Error parsing output: " + str(parse_exception)) return {}
def setmonitor(self, enable=True): """Alias for setmode('monitor') or setmode('managed') Only available with Npcap""" # We must reset the monitor cache if enable: res = self.setmode('monitor') else: res = self.setmode('managed') if not res: log_runtime.error("Npcap WlanHelper returned with an error code !") self.cache_mode = None tmp = self.cache_mode = self.ismonitor() return tmp if enable else (not tmp)
def send(self, x): # type: (Packet) -> int try: sx = raw(x) if self.outs: x.sent_time = time.time() return self.outs.sendto(sx, (x.dst, 0)) except AttributeError: raise ValueError( "Missing 'dst' attribute in the first layer to be " "sent using a native L3 socket ! (make sure you passed the " "IP layer)") except socket.error as msg: log_runtime.error(msg) return 0
def do_dissect_payload(self, s): if s: cls = self.guess_payload_class(s) try: p = cls(s, _internal=1, _underlayer=self) except KeyboardInterrupt: raise except: if conf.debug_dissector: if isinstance(cls,type) and issubclass(cls,Packet): log_runtime.error("%s dissector failed" % cls.name) else: log_runtime.error("%s.guess_payload_class() returned [%s]" % (self.__class__.__name__,repr(cls))) if cls is not None: raise p = conf.raw_layer(s, _internal=1, _underlayer=self) self.add_payload(p)
def send(self, x): sx = raw(x) if hasattr(x, "sent_time"): x.sent_time = time.time() if self.mode_tun: try: proto = conf.l3types[type(x)] except KeyError: log_runtime.warning( "Cannot find layer 3 protocol value to send %s in " "conf.l3types, using 0", x.name if hasattr(x, "name") else type(x).__name__ ) proto = 0 sx = struct.pack('!HH', 0, proto) + sx try: os.write(self.outs.fileno(), sx) except socket.error: log_runtime.error("%s send", self.__class__.__name__, exc_info=True)
def send(self, x): sx = raw(x) if hasattr(x, "sent_time"): x.sent_time = time.time() if self.mode_tun: try: proto = conf.l3types[type(x)] except KeyError: log_runtime.warning( "Cannot find layer 3 protocol value to send %s in " "conf.l3types, using 0", x.name if hasattr(x, "name") else type(x).__name__ ) proto = 0 sx = struct.pack('!HH', 0, proto) + sx try: os.write(self.outs.fileno(), sx) except socket.error: log_runtime.error("%s send", self.__class__.__name__, exc_info=True) # noqa: E501
def send(self, x): if hasattr(x, "sent_time"): x.sent_time = time.time() if self.kernel_packet_class == IPv46: # IPv46 is an auto-detection wrapper; we should just push through # packets normally if we got IP or IPv6. if not isinstance(x, (IP, IPv6)): x = IP() / x elif not isinstance(x, self.kernel_packet_class): x = self.kernel_packet_class() / x sx = raw(x) try: self.outs.write(sx) self.outs.flush() except socket.error: log_runtime.error("%s send", self.__class__.__name__, exc_info=True)
def __init__( self, iface=None, # type: Optional[Union[str, NetworkInterface]] type=ETH_P_ALL, # type: int promisc=None, # type: Optional[Any] filter=None, # type: Optional[Any] nofilter=0, # type: int monitor=None, # type: Optional[Any] ): # type: (...) -> None self.iface = network_name(iface or conf.iface) self.type = type self.promisc = conf.sniff_promisc if promisc is None else promisc self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type)) self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 0) if not nofilter: if conf.except_filter: if filter: filter = "(%s) and not (%s)" % (filter, conf.except_filter) else: filter = "not (%s)" % conf.except_filter if filter is not None: try: attach_filter(self.ins, filter, self.iface) except (ImportError, Scapy_Exception) as ex: log_runtime.error("Cannot set filter: %s", ex) if self.promisc: set_promisc(self.ins, self.iface) self.ins.bind((self.iface, type)) _flush_fd(self.ins.fileno()) self.ins.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, conf.bufsize) if not six.PY2: # Receive Auxiliary Data (VLAN tags) try: self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1) self.ins.setsockopt(socket.SOL_SOCKET, SO_TIMESTAMPNS, 1) self.auxdata_available = True except OSError: # Note: Auxiliary Data is only supported since # Linux 2.6.21 msg = "Your Linux Kernel does not support Auxiliary Data!" log_runtime.info(msg) if not isinstance(self, L2ListenSocket): self.outs = self.ins # type: socket.socket self.outs.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, conf.bufsize) else: self.outs = None # type: ignore sa_ll = self.ins.getsockname() if sa_ll[3] in conf.l2types: self.LL = conf.l2types.num2layer[sa_ll[3]] self.lvl = 2 elif sa_ll[1] in conf.l3types: self.LL = conf.l3types.num2layer[sa_ll[1]] self.lvl = 3 else: self.LL = conf.default_l2 self.lvl = 2 warning( "Unable to guess type (interface=%s protocol=%#x family=%i). Using %s", sa_ll[0], sa_ll[1], sa_ll[3], self.LL.name) # noqa: E501
def __init__(self, iface=None, type=ETH_P_ALL, promisc=None, filter=None, nofilter=0, monitor=None): self.iface = network_name(iface or conf.iface) self.type = type self.promisc = conf.sniff_promisc if promisc is None else promisc if monitor is not None: log_runtime.info( "The 'monitor' argument has no effect on native linux sockets." ) self.ins = socket.socket( socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type)) if not nofilter: if conf.except_filter: if filter: filter = "(%s) and not (%s)" % (filter, conf.except_filter) else: filter = "not (%s)" % conf.except_filter if filter is not None: try: attach_filter(self.ins, filter, iface) except ImportError as ex: log_runtime.error("Cannot set filter: %s", ex) if self.promisc: set_promisc(self.ins, self.iface) self.ins.bind((self.iface, type)) _flush_fd(self.ins) self.ins.setsockopt( socket.SOL_SOCKET, socket.SO_RCVBUF, conf.bufsize ) if not six.PY2: # Receive Auxiliary Data (VLAN tags) try: self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1) self.ins.setsockopt( socket.SOL_SOCKET, SO_TIMESTAMPNS, 1 ) self.auxdata_available = True except OSError: # Note: Auxiliary Data is only supported since # Linux 2.6.21 msg = "Your Linux Kernel does not support Auxiliary Data!" log_runtime.info(msg) if isinstance(self, L2ListenSocket): self.outs = None else: self.outs = self.ins self.outs.setsockopt( socket.SOL_SOCKET, socket.SO_SNDBUF, conf.bufsize ) sa_ll = self.ins.getsockname() if sa_ll[3] in conf.l2types: self.LL = conf.l2types[sa_ll[3]] self.lvl = 2 elif sa_ll[1] in conf.l3types: self.LL = conf.l3types[sa_ll[1]] self.lvl = 3 else: self.LL = conf.default_l2 self.lvl = 2 warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s", sa_ll[0], sa_ll[1], sa_ll[3], self.LL.name) # noqa: E501
def __exit__(self, exc_type, exc_value, traceback): if exc_type == OSError: msg = "%s: executing %r failed" log_runtime.error(msg, self.name, conf.prog.wireshark, exc_info=1) return True # Suppress the exception
def sndrcv(pks, pkt, timeout=None, inter=0, verbose=None, chainCC=0, retry=0, multi=0): if not isinstance(pkt, Gen): pkt = SetGen(pkt) if verbose is None: verbose = conf.verb debug.recv = plist.PacketList([], "Unanswered") debug.sent = plist.PacketList([], "Sent") debug.match = plist.SndRcvList([]) 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] notans = len(tobesent) hsent = {} for i in tobesent: h = i.hashret() if h in hsent: hsent[h].append(i) else: hsent[h] = [i] if retry < 0: retry = -retry autostop = retry else: autostop = 0 while retry >= 0: found = 0 if timeout < 0: timeout = None rdpipe, wrpipe = os.pipe() rdpipe = os.fdopen(rdpipe) wrpipe = os.fdopen(wrpipe, "w") pid = 1 try: pid = os.fork() if pid == 0: try: sys.stdin.close() rdpipe.close() try: i = 0 if verbose: print "Begin emission:" for p in tobesent: pks.send(p) i += 1 time.sleep(inter) if verbose: print "Finished to send %i packets." % i except SystemExit: pass except KeyboardInterrupt: pass except: log_runtime.exception("--- Error in child %i" % os.getpid()) log_runtime.info("--- Error in child %i" % os.getpid()) finally: try: os.setpgrp() # Chance process group to avoid ctrl-C sent_times = [ p.sent_time for p in all_stimuli if p.sent_time ] cPickle.dump((conf.netcache, sent_times), wrpipe) wrpipe.close() except: pass elif pid < 0: log_runtime.error("fork error") else: wrpipe.close() stoptime = 0 remaintime = None inmask = [rdpipe, pks] try: try: while 1: if stoptime: remaintime = stoptime - time.time() if remaintime <= 0: break r = None if not isinstance( pks, StreamSocket) and (FREEBSD or DARWIN): inp, out, err = select(inmask, [], [], 0.05) if len(inp) == 0 or pks in inp: r = pks.nonblock_recv() else: inp = [] try: inp, out, err = select( inmask, [], [], remaintime) except IOError, exc: if exc.errno != errno.EINTR: raise if len(inp) == 0: break if pks in inp: r = pks.recv(MTU) if rdpipe in inp: if timeout: stoptime = time.time() + timeout del (inmask[inmask.index(rdpipe)]) if r is None: continue ok = 0 h = r.hashret() if h in hsent: hlst = hsent[h] for i, sentpkt in enumerate(hlst): if r.answers(sentpkt): ans.append((sentpkt, r)) if verbose > 1: os.write(1, "*") ok = 1 if not multi: del hlst[i] notans -= 1 else: if not hasattr( sentpkt, '_answered'): notans -= 1 sentpkt._answered = 1 break if notans == 0 and not multi: break if not ok: if verbose > 1: os.write(1, ".") nbrecv += 1 if conf.debug_match: debug.recv.append(r) except KeyboardInterrupt: if chainCC: raise finally: try: nc, sent_times = cPickle.load(rdpipe) except EOFError: warning( "Child died unexpectedly. Packets may have not been sent %i" % os.getpid()) else: conf.netcache.update(nc) for p, t in zip(all_stimuli, sent_times): p.sent_time = t os.waitpid(pid, 0) finally: if pid == 0: os._exit(0) remain = list(itertools.chain(*hsent.itervalues())) if multi: remain = [p for p in remain if not hasattr(p, '_answered')] if autostop and len(remain) > 0 and len(remain) != len(tobesent): retry = autostop tobesent = remain if len(tobesent) == 0: break retry -= 1 if conf.debug_match: debug.sent = plist.PacketList(remain[:], "Sent") debug.match = plist.SndRcvList(ans[:]) #clean the ans list to delete the field _answered if (multi): for s, r in ans: if hasattr(s, '_answered'): del (s._answered) if verbose: print "\nReceived %i packets, got %i answers, remaining %i packets" % ( nbrecv + len(ans), len(ans), notans) return plist.SndRcvList(ans), plist.PacketList(remain, "Unanswered")
def sndrcv(pks, pkt, timeout = None, inter = 0, verbose=None, chainCC=0, retry=0, multi=0): if not isinstance(pkt, Gen): pkt = SetGen(pkt) if verbose is None: verbose = conf.verb debug.recv = plist.PacketList([],"Unanswered") debug.sent = plist.PacketList([],"Sent") debug.match = plist.SndRcvList([]) 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] notans = len(tobesent) hsent={} for i in tobesent: h = i.hashret() if h in hsent: hsent[h].append(i) else: hsent[h] = [i] if retry < 0: retry = -retry autostop=retry else: autostop=0 while retry >= 0: found=0 if timeout < 0: timeout = None rdpipe,wrpipe = os.pipe() rdpipe=os.fdopen(rdpipe) wrpipe=os.fdopen(wrpipe,"w") pid=1 try: pid = os.fork() if pid == 0: try: sys.stdin.close() rdpipe.close() try: i = 0 if verbose: print("Begin emission:") for p in tobesent: pks.send(p) i += 1 time.sleep(inter) if verbose: print("Finished to send %i packets." % i) except SystemExit: pass except KeyboardInterrupt: pass except: log_runtime.exception("--- Error in child %i" % os.getpid()) log_runtime.info("--- Error in child %i" % os.getpid()) finally: try: os.setpgrp() # Chance process group to avoid ctrl-C sent_times = [p.sent_time for p in all_stimuli if p.sent_time] six.moves.cPickle.dump( (conf.netcache,sent_times), wrpipe ) wrpipe.close() except: pass elif pid < 0: log_runtime.error("fork error") else: wrpipe.close() stoptime = 0 remaintime = None inmask = [rdpipe,pks] try: try: while True: if stoptime: remaintime = stoptime-time.time() if remaintime <= 0: break r = None if conf.use_bpf: from scapy.arch.bpf.supersocket import bpf_select inp = bpf_select(inmask) if pks in inp: r = pks.recv() elif not isinstance(pks, StreamSocket) and (FREEBSD or DARWIN or OPENBSD): inp, out, err = select(inmask,[],[], 0.05) if len(inp) == 0 or pks in inp: r = pks.nonblock_recv() else: inp = [] try: inp, out, err = select(inmask,[],[], remaintime) except (IOError, select_error) as exc: # select.error has no .errno attribute if exc.args[0] != errno.EINTR: raise if len(inp) == 0: break if pks in inp: r = pks.recv(MTU) if rdpipe in inp: if timeout: stoptime = time.time()+timeout del(inmask[inmask.index(rdpipe)]) if r is None: continue ok = 0 h = r.hashret() if h in hsent: hlst = hsent[h] for i, sentpkt in enumerate(hlst): if r.answers(sentpkt): ans.append((sentpkt, r)) if verbose > 1: os.write(1, "*") ok = 1 if not multi: del hlst[i] notans -= 1 else: if not hasattr(sentpkt, '_answered'): notans -= 1 sentpkt._answered = 1 break if notans == 0 and not multi: break if not ok: if verbose > 1: os.write(1, ".") nbrecv += 1 if conf.debug_match: debug.recv.append(r) except KeyboardInterrupt: if chainCC: raise finally: try: nc,sent_times = six.moves.cPickle.load(rdpipe) except EOFError: warning("Child died unexpectedly. Packets may have not been sent %i"%os.getpid()) else: conf.netcache.update(nc) for p,t in zip(all_stimuli, sent_times): p.sent_time = t os.waitpid(pid,0) finally: if pid == 0: os._exit(0) remain = list(itertools.chain(*six.itervalues(hsent))) if multi: remain = [p for p in remain if not hasattr(p, '_answered')] if autostop and len(remain) > 0 and len(remain) != len(tobesent): retry = autostop tobesent = remain if len(tobesent) == 0: break retry -= 1 if conf.debug_match: debug.sent=plist.PacketList(remain[:],"Sent") debug.match=plist.SndRcvList(ans[:]) #clean the ans list to delete the field _answered if (multi): for s,r in ans: if hasattr(s, '_answered'): del(s._answered) if verbose: print("\nReceived %i packets, got %i answers, remaining %i packets" % (nbrecv+len(ans), len(ans), notans)) return plist.SndRcvList(ans),plist.PacketList(remain,"Unanswered")