def __init__(self, poll_delay=2, prune_period=3600): self.delay = poll_delay self.arp_table = {} self.prune_period = prune_period self.am = AllertManager() self._stop = Event() self.mute = False self.fake = False self.rxq = Queue(1) self.txq = Queue(1) super(ARPHandler, self).__init__() self.daemon = True
class ARPHandler(Process): def __init__(self, poll_delay=2, prune_period=3600): self.delay = poll_delay self.arp_table = {} self.prune_period = prune_period self.am = AllertManager() self._stop = Event() self.mute = False self.fake = False self.rxq = Queue(1) self.txq = Queue(1) super(ARPHandler, self).__init__() self.daemon = True def get_table(self): """Expose arp table by refference.""" if not self.txq.empty(): self.arp_table = self.txq.get() return self.arp_table def update_table(self,table): """ Allow the client application to update the proccess ARP table """ if self.rxq.empty(): # Copy the table to class memory self.arp_table = deepcopy(table) # Copy the table to forked proccess memory self.rxq.put(table) return True else: return False def arp_monitor_callback(self, pkt): """Convert the return of the arp monitor to dictionary entries.""" if ARP in pkt and pkt[ARP].op in (1, 2): hwaddr = pkt.sprintf(r"%ARP.hwsrc%") ipsrc = pkt.sprintf(r"%ARP.psrc%") host = self.arp_resolve(ipsrc) entry = OrderedDict( [('mac', hwaddr), ('hostname', self.arp_resolve(ipsrc)), ('alias', ''), ("time", datetime.now()), ("color", "")]) time.sleep(0.1) self.add_to_table(ipsrc, entry) print ("%s %s %s" % (host, ipsrc, hwaddr)), self.txq.empty() def arp_scan(self): """Scan the network using ARP requests for alive hosts.""" conf.verb = 0 ans, unans = srp(Ether(dst='ff:ff:ff:ff:ff:ff') / ARP(pdst="192.168.0.1/24"), timeout=2,\ iface="eth0", inter=0.1) hosts = {} for snd, rcv in ans: hwaddr = rcv.sprintf(r"%Ether.src%") ipsrc = rcv.sprintf(r"%ARP.psrc%") hosts[ipsrc] = {'hostname': '', 'mac': hwaddr, 'alias': ''} hosts[ipsrc]['hostname'] = self.arp_resolve(ipsrc) return hosts def arp_resolve(self, ip_target): """Resolve the hostname for given ip address.""" try: host = gethostbyaddr(ip_target)[0] except: host = "N.A" return host def prune(self): """Function that will remove old entries from arp_table.""" # Copy the latest version of the table if self.txq.empty(): return False temp_table = self.txq.get() now = datetime.now() for key in temp_table.keys(): dlta = now - temp_table[key]['time'] # If equal and larger remove it if dlta.days >= self.prune_period: temp_table.pop(key) return self.update_table(temp_table) def add_to_table(self, ip, entry): """Add a new entry to the ARP table and allert if it exists and is tracked.""" #print "\nEntry", entry, len(self.arp_table), hex(id(self.arp_table)),self.arp_table.keys() # if there is a new table from application copy it to memory if not self.rxq.empty(): print "Rx-sync" self.arp_table = self.rxq.get() # If there is space in the queue push the table from memory if self.txq.empty(): self.txq.put(self.arp_table) # If the device has the same IP as before if ip in self.arp_table.keys() and entry[ 'mac'] == self.arp_table[ip]['mac']: pass # If the ip has been modified but address still registered elif entry['mac'] in repr(self.arp_table): for key in self.arp_table: if self.arp_table[key]['mac'] == entry['mac']: break else: return False # If it does not exist add it to the table else: self.arp_table[ip] = entry return True # If mute is asserted do not report if self.mute: return False # Only broadcast allert if the device is tracked try: color = self.arp_table[ip]['color'] except KeyError: color = '' if color: al = self.arp_table[ip]['alias'] hst = self.arp_table[ip]['hostname'] self.am.broadcast( "%s AKA %s has joined the network" % (hst, al), color) return False def fake_data(self): """ Simulate ARP scan with preset fake data """ # Pick a random device from the fake dataset and remove it idx = randint(0, len(data_d) - 1) #Sleep a random number of seconds sleep(randint(0, 10)) key = data_d.keys()[idx] # Add the new entry in the ARP table (this is will be replaced # by arp callbacks tempentry = data_d[key] tempentry["time"] = datetime.now() self.add_to_table(key, tempentry) def run(self): """ Main Thread Loop """ # Both entries are blocking so no loop required try: if self.fake: self.fake_sniff() else: sniff(prn=self.arp_monitor_callback, filter="arp", store=0) except KeyboardInterrupt: print "Proccess Exit"#, self.arp_table def fake_sniff(self): """ Blocking method to simulate sniffing with fake data """ while True: self.fake_data() def set_fake(self): """ Set fakedata mode """ self.fake = True def set_mute(self, mute=True): """ Disable Thread Reporting """ self.mute = mute