def recv(self, x=MTU): ll = self.ins.datalink() if ll in conf.l2types: cls = conf.l2types[ll] else: cls = conf.default_l2 warning( "Unable to guess datalink type (interface=%s linktype=%i). Using %s" % (self.iface, ll, cls.name)) pkt = self.ins.next() if pkt is not None: ts, pkt = pkt if pkt is None: return try: pkt = cls(pkt) except KeyboardInterrupt: raise except: if conf.debug_dissector: raise pkt = conf.raw_layer(pkt) pkt.time = ts return pkt
def get_if_raw_addr(ifname): i = dnet.intf() try: return i.get(ifname)["addr"].data except OSError: warning("No MAC address found on %s !" % ifname) return "\0\0\0\0"
def recv(self, x=MTU): ll = self.ins.datalink() if ll in conf.l2types: cls = conf.l2types[ll] else: cls = conf.default_l2 warning( "Unable to guess datalink type (interface=%s linktype=%i). Using %s" % (self.iface, ll, cls.name) ) pkt = self.ins.next() if pkt is not None: ts, pkt = pkt if pkt is None: return try: pkt = cls(pkt) except KeyboardInterrupt: raise except: if conf.debug_dissector: raise pkt = conf.raw_layer(pkt) pkt.time = ts return pkt
def get_blen(self): """Get the BPF buffer length""" try: ret = fcntl.ioctl(self.ins, BIOCGBLEN, struct.pack("I", 0)) return struct.unpack("I", ret)[0] except IOError, err: warning("Unable to get the BPF buffer length") return
def get_stats(self): """Get received / dropped statistics""" try: ret = fcntl.ioctl(self.ins, BIOCGSTATS, struct.pack("2I", 0, 0)) return struct.unpack("2I", ret) except IOError, err: warning("Unable to get stats from BPF !") return (None, None)
def get_if_raw_addr(ifname): """Returns the IPv4 address configured on 'ifname', packed with inet_pton.""" # Get ifconfig output try: fd = os.popen("%s %s" % (conf.prog.ifconfig, ifname)) except OSError, msg: warning("Failed to execute ifconfig: (%s)" % msg) return "\0\0\0\0"
def guess_cls(self): """Guess the packet class that must be used on the interface""" # Get the data link type try: ret = fcntl.ioctl(self.ins, BIOCGDLT, struct.pack('I', 0)) ret = struct.unpack('I', ret)[0] except IOError, err: warning("BIOCGDLT failed: unable to guess type. Using Ethernet !") return Ether
def set_nonblock(self, set_flag=True): """Set the non blocking flag on the socket""" # Get the current flags if self.fd_flags is None: try: self.fd_flags = fcntl.fcntl(self.ins, fcntl.F_GETFL) except IOError, err: warning("Can't get flags on this file descriptor !") return
def __init__(self, *args, **kargs): self.pcap = pcap.pcapObject() if sys.platform == 'darwin' and 'pcap_set_rfmon' not in dir(self.pcap): warning("Mac OS WiFI monitor mode not supported unless python-libpcap patched for OS X is used.") if sys.platform == 'darwin': self.pcap.pcap_set_rfmon(args[0], 1) self.pcap.pcap_activate() else: self.pcap.open_live(*args, **kargs)
def get_if_raw_hwaddr(ifname): """Returns the packed MAC address configured on 'ifname'.""" NULL_MAC_ADDRESS = '\x00'*6 # Handle the loopback interface separately if ifname == LOOPBACK_NAME: return (ARPHDR_LOOPBACK, NULL_MAC_ADDRESS) # Get ifconfig output try: fd = os.popen("%s %s" % (conf.prog.ifconfig, ifname)) except OSError, msg: warning("Failed to execute ifconfig: (%s)" % msg) raise Scapy_Exception("Failed to execute ifconfig: (%s)" % msg)
def get_working_ifaces(): """ Returns an ordered list of interfaces that could be used with BPF. Note: the order mimics pcap_findalldevs() behavior """ # Only root is allowed to perform the following ioctl() call if os.getuid() != 0: return [] # Test all network interfaces interfaces = [] for ifname in get_if_list(): # Unlike pcap_findalldevs(), we do not care of loopback interfaces. if ifname == LOOPBACK_NAME: continue # Get interface flags try: result = get_if(ifname, SIOCGIFFLAGS) except IOError, msg: warning("ioctl(SIOCGIFFLAGS) failed on %s !" % ifname) continue # Convert flags ifflags = struct.unpack("16xH14x", result)[0] if ifflags & 0x1: # IFF_UP # Get a BPF handle fd, _ = get_dev_bpf() if fd is None: raise Scapy_Exception("No /dev/bpf are available !") # Check if the interface can be used try: fcntl.ioctl(fd, BIOCSETIF, struct.pack("16s16x", ifname)) interfaces.append((ifname, int(ifname[-1]))) except IOError, err: pass # Close the file descriptor os.close(fd)
def self_build(self, field_pos_list=None): if self.afi is None: if self.ip4 is not None: self.afi = 1 elif self.ip6 is not None: self.afi = 2 if self.has_ifindex and self.ifindex is None: warning('has_ifindex set but ifindex is not set.') if self.has_ipaddr and self.afi is None: warning('has_ipaddr set but afi is not set.') if self.has_ipaddr and self.ip4 is None and self.ip6 is None: warning('has_ipaddr set but ip4 or ip6 is not set.') if self.has_ifname and self.ifname is None: warning('has_ifname set but ifname is not set.') if self.has_mtu and self.mtu is None: warning('has_mtu set but mtu is not set.') return ICMPExtensionObject.self_build(self, field_pos_list=field_pos_list)
def get_working_ifaces(): """ Returns an ordered list of interfaces that could be used with BPF. Note: the order mimics pcap_findalldevs() behavior """ # Only root is allowed to perform the following ioctl() call if os.getuid() != 0: return [] # Test all network interfaces interfaces = [] for ifname in get_if_list(): # Unlike pcap_findalldevs(), we do not care of loopback interfaces. # GV: why ?!? if ifname == LOOPBACK_NAME: continue # Get interface flags try: result = get_if(ifname, SIOCGIFFLAGS) except IOError, msg: warning("ioctl(SIOCGIFFLAGS) failed on %s !" % ifname) continue # Convert flags ifflags = struct.unpack("16xH14x", result)[0] if ifflags & 0x1: # IFF_UP # Get a BPF handle fd, _ = get_dev_bpf() if fd is None: raise Scapy_Exception("No /dev/bpf are available !") # Check if the interface can be used try: fcntl.ioctl(fd, BIOCSETIF, struct.pack("16s16x", ifname)) interfaces.append((ifname, int(ifname[-1]))) except IOError, err: pass # Close the file descriptor os.close(fd)
def recv(self, x=BPF_BUFFER_LENGTH): """Receive a frame from the network""" if self.buffered_frames(): # Get a frame from the buffer return self.get_frame() else: # Get data from BPF try: bpf_buffer = os.read(self.ins, x) except EnvironmentError, e: if e.errno == errno.EAGAIN: return else: warning("BPF recv(): %s" % e) return # Extract all frames from the BPF buffer self.extract_frames(bpf_buffer) return self.get_frame()
def send(self, x): iff, a, gw = x.route() if iff is None: iff = conf.iface ifs, cls = self.iflist.get(iff, (None, None)) if ifs is None: iftype = self.intf.get(iff)["type"] if iftype == dnet.INTF_TYPE_ETH: try: cls = conf.l2types[1] except KeyError: warning("Unable to find Ethernet class. Using nothing") ifs = dnet.eth(iff) else: ifs = dnet.ip() self.iflist[iff] = ifs, cls if cls is None: sx = str(x) else: sx = str(cls() / x) x.sent_time = time.time() ifs.send(sx)
def __del__(self): warning( "__del__: don't know how to close the file descriptor. Bugs ahead ! Please report this bug." )
def fileno(self): warning( "fileno: pcapy API does not permit to get capure file descriptor. Bugs ahead! Press Enter to trigger packet reading" ) return 0
def __init__(self, *args, **kargs): if sys.platform == 'darwin': warning("Mac OS WiFI monitor mode not supported unless patched python-libpcap is used.") self.pcap = pcap.open_live(*args, **kargs)
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")
try: ret = fcntl.ioctl(self.ins, BIOCGDLT, struct.pack('I', 0)) ret = struct.unpack('I', ret)[0] except IOError, err: warning("BIOCGDLT failed: unable to guess type. Using Ethernet !") return Ether # *BSD loopback interface if OPENBSD and ret == 12: # DTL_NULL on OpenBSD return Loopback # Retrieve the corresponding class cls = conf.l2types.get(ret, None) if cls is None: cls = Ether warning("Unable to guess type. Using Ethernet !") return cls def set_nonblock(self, set_flag=True): """Set the non blocking flag on the socket""" # Get the current flags if self.fd_flags is None: try: self.fd_flags = fcntl.fcntl(self.ins, fcntl.F_GETFL) except IOError, err: warning("Can't get flags on this file descriptor !") return # Set the non blocking flag
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 get_if_raw_addr(ifname): """Returns the IPv4 address configured on 'ifname', packed with inet_pton.""" # Get ifconfig output try: fd = os.popen("%s %s" % (conf.prog.ifconfig, ifname)) except OSError, msg: warning("Failed to execute ifconfig: (%s)" % msg) return "\0\0\0\0" # Get IPv4 addresses addresses = [l for l in fd if l.find("netmask") >= 0] if not addresses: warning("No IPv4 address found on %s !" % ifname) return "\0\0\0\0" # Pack the first address address = addresses[0].split(' ')[1] return socket.inet_pton(socket.AF_INET, address) def get_if_raw_hwaddr(ifname): """Returns the packed MAC address configured on 'ifname'.""" NULL_MAC_ADDRESS = '\x00' * 6 # Handle the loopback interface separately if ifname == LOOPBACK_NAME: return (ARPHDR_LOOPBACK, NULL_MAC_ADDRESS)