X-Git-Url: http://git.ipfire.org/?p=ipfire-2.x.git;a=blobdiff_plain;f=config%2Funbound%2Funbound-dhcp-leases-bridge;h=a8cd837bbfbf17b08cf03cd77eb5c11f7b56233d;hp=70da1e03180e7650e95b5621a2e04bc4333b590f;hb=b666975ec292fec239aa6023dc79abf5538c9d95;hpb=5d4f3a42cea5e4224aa4ba469dd7bc182ece4b67 diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge index 70da1e0318..a8cd837bbf 100644 --- a/config/unbound/unbound-dhcp-leases-bridge +++ b/config/unbound/unbound-dhcp-leases-bridge @@ -25,9 +25,11 @@ import daemon import ipaddress import logging import logging.handlers +import os import re import signal import subprocess +import tempfile import inotify.adapters @@ -123,6 +125,23 @@ class UnboundDHCPLeasesBridge(object): for lease in FixLeases(self.fix_leases_file): leases.append(lease) + # Skip any leases that also are a static host + leases = [l for l in leases if not l.fqdn in self.hosts] + + # Remove any inactive or expired leases + leases = [l for l in leases if l.active and not l.expired] + + # Dump leases + if leases: + log.debug("DHCP Leases:") + for lease in leases: + log.debug(" %s:" % lease.fqdn) + log.debug(" State: %s" % lease.binding_state) + log.debug(" Start: %s" % lease.time_starts) + log.debug(" End : %s" % lease.time_ends) + if lease.expired: + log.debug(" Expired") + self.unbound.update_dhcp_leases(leases) def read_static_hosts(self): @@ -205,7 +224,7 @@ class DHCPLeases(object): # exists in the list of known leases. If so replace # if with the most recent lease for i, l in enumerate(leases): - if l.hwaddr == lease.hwaddr: + if l.ipaddr == lease.ipaddr: leases[i] = max(lease, l) break @@ -455,51 +474,15 @@ class UnboundConfigWriter(object): def __init__(self, path): self.path = path - @property - def existing_leases(self): - local_data = self._control("list_local_data") - ret = {} - - for line in local_data.splitlines(): - try: - hostname, ttl, x, record_type, content = line.split("\t") - except ValueError: - continue - - # Ignore everything that is not A or PTR - if not record_type in ("A", "PTR"): - continue - - if hostname.endswith("."): - hostname = hostname[:-1] - - if content.endswith("."): - content = content[:-1] - - if record_type == "A": - ret[hostname] = content - elif record_type == "PTR": - ret[content] = reverse_pointer_to_ip_address(hostname) - - return ret + self._cached_leases = [] def update_dhcp_leases(self, leases): - # Cache all expired or inactive leases - expired_leases = [l for l in leases if l.expired or not l.active] - # Find any leases that have expired or do not exist any more # but are still in the unbound local data - removed_leases = [] - for fqdn, address in self.existing_leases.items(): - if fqdn in (l.fqdn for l in expired_leases): - removed_leases += [fqdn, address] - - # Strip all non-active or expired leases - leases = [l for l in leases if l.active and not l.expired] + removed_leases = [l for l in self._cached_leases if not l in leases] # Find any leases that have been added - new_leases = [l for l in leases - if l.fqdn not in self.existing_leases] + new_leases = [l for l in leases if l not in self._cached_leases] # End here if nothing has changed if not new_leases and not removed_leases: @@ -509,34 +492,58 @@ class UnboundConfigWriter(object): self.write_dhcp_leases(leases) # Update unbound about changes - for hostname in removed_leases: - log.debug("Removing all records for %s" % hostname) - self._control("local_data_remove", hostname) + for l in removed_leases: + try: + for name, ttl, type, content in l.rrset: + log.debug("Removing records for %s" % name) + self._control("local_data_remove", name) + + # If the lease cannot be removed we will try the next one + except: + continue + + # If the removal was successful, we will remove it from the cache + else: + self._cached_leases.remove(l) for l in new_leases: - for rr in l.rrset: - log.debug("Adding new record %s" % " ".join(rr)) - self._control("local_data", *rr) + try: + for rr in l.rrset: + log.debug("Adding new record %s" % " ".join(rr)) + self._control("local_data", *rr) + + # If the lease cannot be added we will try the next one + except: + continue + # Add lease to cache when successfully added + else: + self._cached_leases.append(l) def write_dhcp_leases(self, leases): - with open(self.path, "w") as f: + with tempfile.NamedTemporaryFile(mode="w", delete=False) as f: + filename = f.name + for l in leases: for rr in l.rrset: f.write("local-data: \"%s\"\n" % " ".join(rr)) + os.rename(filename, self.path) + def _control(self, *args): command = ["unbound-control"] command.extend(args) try: - return subprocess.check_output(command) + subprocess.check_output(command) # Log any errors except subprocess.CalledProcessError as e: log.critical("Could not run %s, error code: %s: %s" % ( " ".join(command), e.returncode, e.output)) + raise + if __name__ == "__main__": parser = argparse.ArgumentParser(description="Bridge for DHCP Leases and Unbound DNS")