]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - config/unbound/unbound-dhcp-leases-bridge
unbound: Skip invalid hostnames
[people/pmueller/ipfire-2.x.git] / config / unbound / unbound-dhcp-leases-bridge
index a3e16616efd35fa92952693ab783b7fd99fe8993..862b5814f03f073c83178fb25f73192507a22477 100644 (file)
@@ -22,6 +22,7 @@
 import argparse
 import datetime
 import daemon
+import ipaddress
 import logging
 import logging.handlers
 import re
@@ -48,6 +49,20 @@ def setup_logging(loglevel=logging.INFO):
 
 log = logging.getLogger("dhcp")
 
+def ip_address_to_reverse_pointer(address):
+       parts = address.split(".")
+       parts.reverse()
+
+       return "%s.in-addr.arpa" % ".".join(parts)
+
+def reverse_pointer_to_ip_address(rr):
+       parts = rr.split(".")
+
+       # Only take IP address part
+       parts = reversed(parts[0:4])
+
+       return ".".join(parts)
+
 class UnboundDHCPLeasesBridge(object):
        def __init__(self, dhcp_leases_file, unbound_leases_file):
                self.leases_file = dhcp_leases_file
@@ -212,19 +227,65 @@ class Lease(object):
        def hostname(self):
                hostname = self._properties.get("client-hostname")
 
+               if hostname is None:
+                       return
+
                # Remove any ""
-               if hostname:
-                       hostname = hostname.replace("\"", "")
+               hostname = hostname.replace("\"", "")
 
-               return hostname
+               # Only return valid hostnames
+               m = re.match(r"^[A-Z0-9\-]{1,63}$", hostname, re.I)
+               if m:
+                       return hostname
 
        @property
        def domain(self):
-               return "local" # XXX
+               # Load ethernet settings
+               ethernet_settings = self.read_settings("/var/ipfire/ethernet/settings")
+
+               # Load DHCP settings
+               dhcp_settings = self.read_settings("/var/ipfire/dhcp/settings")
+
+               subnets = {}
+               for zone in ("GREEN", "BLUE"):
+                       if not dhcp_settings.get("ENABLE_%s" % zone) == "on":
+                               continue
+
+                       netaddr = ethernet_settings.get("%s_NETADDRESS" % zone)
+                       submask = ethernet_settings.get("%s_NETMASK" % zone)
+
+                       subnet = ipaddress.ip_network("%s/%s" % (netaddr, submask))
+                       domain = dhcp_settings.get("DOMAIN_NAME_%s" % zone)
+
+                       subnets[subnet] = domain
+
+               address = ipaddress.ip_address(self.ipaddr)
+
+               for subnet, domain in subnets.items():
+                       if address in subnet:
+                               return domain
+
+               # Fall back to localdomain if no match could be found
+               return "localdomain"
+
+       @staticmethod
+       def read_settings(filename):
+               settings = {}
+
+               with open(filename) as f:
+                       for line in f.readlines():
+                               # Remove line-breaks
+                               line = line.rstrip()
+
+                               k, v = line.split("=", 1)
+                               settings[k] = v
+
+               return settings
 
        @property
        def fqdn(self):
-               return "%s.%s" % (self.hostname, self.domain)
+               if self.hostname:
+                       return "%s.%s" % (self.hostname, self.domain)
 
        @staticmethod
        def _parse_time(s):
@@ -255,12 +316,17 @@ class Lease(object):
 
        @property
        def rrset(self):
+               # If the lease does not have a valid FQDN, we cannot create any RRs
+               if self.fqdn is None:
+                       return []
+
                return [
                        # Forward record
                        (self.fqdn, "%s" % LOCAL_TTL, "IN A", self.ipaddr),
 
                        # Reverse record
-                       (self.ipaddr, "%s" % LOCAL_TTL, "IN PTR", self.fqdn),
+                       (ip_address_to_reverse_pointer(self.ipaddr), "%s" % LOCAL_TTL,
+                               "IN PTR", self.fqdn),
                ]
 
 
@@ -292,20 +358,24 @@ class UnboundConfigWriter(object):
                        if record_type == "A":
                                ret[hostname] = content
                        elif record_type == "PTR":
-                               ret[content] = hostname
+                               ret[content] = reverse_pointer_to_ip_address(hostname)
 
                return ret
 
        def update_dhcp_leases(self, leases):
-               # Strip all non-active or expired leases
-               leases = [l for l in leases if l.active and not l.expired]
+               # 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 
+               # 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 not fqdn in (l.fqdn for l in leases):
+                       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]
+
                # Find any leases that have been added
                new_leases = [l for l in leases
                        if l.fqdn not in self.existing_leases]