From: Michael Tremer Date: Tue, 11 Oct 2016 17:14:33 +0000 (+0200) Subject: unbound: Public static leases in DNS, too X-Git-Tag: v2.19-core106~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=86c9deb2ea39001c488b7b65f6dfac6fe88a1a35;p=people%2Fstevee%2Fipfire-2.x.git unbound: Public static leases in DNS, too Signed-off-by: Michael Tremer --- diff --git a/config/unbound/unbound-dhcp-leases-bridge b/config/unbound/unbound-dhcp-leases-bridge index 862b5814f0..91bdb4f362 100644 --- a/config/unbound/unbound-dhcp-leases-bridge +++ b/config/unbound/unbound-dhcp-leases-bridge @@ -64,8 +64,9 @@ def reverse_pointer_to_ip_address(rr): return ".".join(parts) class UnboundDHCPLeasesBridge(object): - def __init__(self, dhcp_leases_file, unbound_leases_file): + def __init__(self, dhcp_leases_file, fix_leases_file, unbound_leases_file): self.leases_file = dhcp_leases_file + self.fix_leases_file = fix_leases_file self.unbound = UnboundConfigWriter(unbound_leases_file) self.running = False @@ -77,7 +78,7 @@ class UnboundDHCPLeasesBridge(object): # Initially read leases file self.update_dhcp_leases() - i = inotify.adapters.Inotify([self.leases_file]) + i = inotify.adapters.Inotify([self.leases_file, self.fix_leases_file]) for event in i.event_gen(): # End if we are requested to terminate @@ -93,12 +94,21 @@ class UnboundDHCPLeasesBridge(object): if "IN_MODIFY" in type_names: self.update_dhcp_leases() + # If the file is deleted, we re-add the watcher + if "IN_IGNORED" in type_names: + i.add_watch(watch_path) + log.info("Unbound DHCP Leases Bridge terminated") def update_dhcp_leases(self): - log.info("Reading DHCP leases from %s" % self.leases_file) + leases = [] + + for lease in DHCPLeases(self.leases_file): + leases.append(lease) + + for lease in FixLeases(self.fix_leases_file): + leases.append(lease) - leases = DHCPLeases(self.leases_file) self.unbound.update_dhcp_leases(leases) def terminate(self): @@ -117,6 +127,8 @@ class DHCPLeases(object): return iter(self._leases) def _parse(self): + log.info("Reading DHCP leases from %s" % self.path) + leases = [] with open(self.path) as f: @@ -179,6 +191,58 @@ class DHCPLeases(object): return properties +class FixLeases(object): + cache = {} + + def __init__(self, path): + self.path = path + + self._leases = self.cache[self.path] = self._parse() + + def __iter__(self): + return iter(self._leases) + + def _parse(self): + log.info("Reading fix leases from %s" % self.path) + + leases = [] + now = datetime.datetime.utcnow() + + with open(self.path) as f: + for line in f.readlines(): + line = line.rstrip() + + try: + hwaddr, ipaddr, enabled, a, b, c, hostname = line.split(",") + except ValueError: + log.warning("Could not parse line: %s" % line) + continue + + # Skip any disabled leases + if not enabled == "on": + continue + + l = Lease(ipaddr, { + "binding" : "state active", + "client-hostname" : hostname, + "hardware" : "ethernet %s" % hwaddr, + "starts" : now.strftime("%w %Y/%m/%d %H:%M:%S"), + "ends" : "never", + }) + leases.append(l) + + # Try finding any deleted leases + for lease in self.cache.get(self.path, []): + if lease in leases: + continue + + # Free the deleted lease + lease.free() + leases.append(lease) + + return leases + + class Lease(object): def __init__(self, ipaddr, properties): self.ipaddr = ipaddr @@ -208,6 +272,11 @@ class Lease(object): state = state.split(" ", 1) return state[1] + def free(self): + self._properties.update({ + "binding" : "state free", + }) + @property def active(self): return self.binding_state == "active" @@ -430,6 +499,8 @@ if __name__ == "__main__": metavar="PATH", help="Path to the DHCPd leases file") parser.add_argument("--unbound-leases", default="/etc/unbound/dhcp-leases.conf", metavar="PATH", help="Path to the unbound configuration file") + parser.add_argument("--fix-leases", default="/var/ipfire/dhcp/fixleases", + metavar="PATH", help="Path to the fix leases file") # Parse command line arguments args = parser.parse_args() @@ -444,7 +515,7 @@ if __name__ == "__main__": setup_logging(loglevel) - bridge = UnboundDHCPLeasesBridge(args.dhcp_leases, args.unbound_leases) + bridge = UnboundDHCPLeasesBridge(args.dhcp_leases, args.fix_leases, args.unbound_leases) ctx = daemon.DaemonContext(detach_process=args.daemon) ctx.signal_map = {