def _active_get_mapping(self): # Anly working on A record now if ((self._active_timer != None) and (self._active_timer.is_alive())): return try: results = resolver.query(self.rule, 'A') ttl = results.ttl self._active_timer = Timer(ttl, self._active_get_mapping_expired) self._active_timer.start() new_active_results = [] # These two reduce churn: only adds things that weren't there from the # previous pass, only deletes things that aren't there from this pass. # Add new addresses for addr in results: new_active_results.append(addr) if addr not in self._active_results: print "adding addr: " + str(addr) self.add_rule_cb(ipv4_src=str(addr), eth_type=ether.ETH_TYPE_IP) self.add_rule_cb(ipv4_dst=str(addr), eth_type=ether.ETH_TYPE_IP) # Remove old addresses for addr in self._active_results: if addr not in results: self.remove_rule_cb(ipv4_src=str(addr), eth_type=ether.ETH_TYPE_IP) self.remove_rule_cb(ipv4_dst=str(addr), eth_type=ether.ETH_TYPE_IP) self._active_results = new_active_results except (resolver.NoAnswer, exception.Timeout, resolver.NXDOMAIN): self.logger.info("Could not query for " + self.rule + ". Trying again in 30 seconds.") self._active_timer = Timer(30, self._active_get_mapping_expired) self._active_timer.start() self._active_results = []
class DNSMetadataEntry(MetadataEntry): def __init__(self, data_source, engine, rule, add_rule_cb, remove_rule_cb): super(DNSMetadataEntry, self).__init__(data_source, engine, rule) self.register_callbacks(add_rule_cb, remove_rule_cb) self.data_source.set_new_callback(self.handle_new_entry_callback) if ACTIVE_MAPPING == True: self._active_timer = None self._active_results = [] self._active_get_mapping() def handle_expiration_callback(self, addr, entry): self.logger.info("DNSMetadataEntry.handle_expiration_callback(): called with " + addr) #need to remove the rules that was generated by the particular DNSEntry #TODO self.remove_rule_cb(ipv4_src=str(addr), eth_type=ether.ETH_TYPE_IP) self.remove_rule_cb(ipv4_dst=str(addr), eth_type=ether.ETH_TYPE_IP) def handle_new_entry_callback(self, addr, entry): self.logger.info("DNSMetadataEntry.handle_new_entry_callback(): called with " + addr) for name in entry.names: if name == self.rule: self.add_rule_cb(ipv4_src=str(addr), eth_type=ether.ETH_TYPE_IP) self.add_rule_cb(ipv4_dst=str(addr), eth_type=ether.ETH_TYPE_IP) self.logger.debug(" New rule for " + name) entry.register_timeout_callback(self.handle_expiration_callback) def _active_get_mapping_expired(self): #self.logger.debug("_active_get_mapping_expired() called " + str(self._active_timer.is_alive())) self._active_timer.cancel() self._active_get_mapping() def _active_get_mapping(self): # Anly working on A record now if ((self._active_timer != None) and (self._active_timer.is_alive())): return try: results = resolver.query(self.rule, 'A') ttl = results.ttl self._active_timer = Timer(ttl, self._active_get_mapping_expired) self._active_timer.start() new_active_results = [] # These two reduce churn: only adds things that weren't there from the # previous pass, only deletes things that aren't there from this pass. # Add new addresses for addr in results: new_active_results.append(addr) if addr not in self._active_results: print "adding addr: " + str(addr) self.add_rule_cb(ipv4_src=str(addr), eth_type=ether.ETH_TYPE_IP) self.add_rule_cb(ipv4_dst=str(addr), eth_type=ether.ETH_TYPE_IP) # Remove old addresses for addr in self._active_results: if addr not in results: self.remove_rule_cb(ipv4_src=str(addr), eth_type=ether.ETH_TYPE_IP) self.remove_rule_cb(ipv4_dst=str(addr), eth_type=ether.ETH_TYPE_IP) self._active_results = new_active_results except (resolver.NoAnswer, exception.Timeout, resolver.NXDOMAIN): self.logger.info("Could not query for " + self.rule + ". Trying again in 30 seconds.") self._active_timer = Timer(30, self._active_get_mapping_expired) self._active_timer.start() self._active_results = []
def _set_and_start_timer(self): time_to_go = self.expiry - datetime.now() self.timer = Timer(time_to_go.total_seconds(), self._call_callbacks) self.timer.start()
class DNSClassifierEntry: def __init__(self, IP, names, classification, ttl, expiry=None): self.IP = IP self.names = names self.classification = classification self.ttl = ttl if expiry is datetime: self.expiry = expiry else: self.expiry = datetime.now() + timedelta(seconds=ttl) # callbacks! self.timeout_callbacks = [] self.timer = None def __del__(self): if self.timer is not None: self.timer.cancel() def print_entry(self, offset=""): names_str = "" for name in self.names: names_str = names_str + name + " " if (self.is_expired()): expired = "Expired" else: expired = "Not expired" print offset + self.IP print offset + names_str print offset + str(self.ttl) print offset + self.classification print offset + str(self.expiry) print offset + expired def is_expired(self, expiry=None): if expiry is datetime: expiration_time = expiry else: expiration_time = datetime.now() return self.expiry < expiration_time def update_expiry(self, ttl): self.ttl = ttl self.expiry = datetime.now() + timedelta(seconds=ttl) if self.timer is not None: self.timer.cancel() self._set_and_start_timer() def register_timeout_callback(self, func): if func not in self.timeout_callbacks: self.timeout_callbacks.append(func) if self.timer is None and not self.is_expired(): self._set_and_start_timer() def _call_callbacks(self): # This is called when it expires. for cb in self.timeout_callbacks: cb(self.IP, self) def _set_and_start_timer(self): time_to_go = self.expiry - datetime.now() self.timer = Timer(time_to_go.total_seconds(), self._call_callbacks) self.timer.start()