Delete IP from blockip only if not needed by other hosts.
authorPhilipp Spitzer <philipp@spitzer.priv.at>
Wed, 27 Jul 2016 21:07:24 +0000 (23:07 +0200)
committergregor herrmann <gregoa@debian.org>
Wed, 27 Jul 2016 22:21:38 +0000 (00:21 +0200)
bin/tdyndns_update

index 3f46d13..272a610 100755 (executable)
@@ -20,6 +20,19 @@ def ipfamily_by_ip(ip):
        assert False
 
 
+def forward_lookup(fqdn, ip_family):
+       """Returns the ip address of the fqdn or None if none is found..
+
+       :param fqdn: Fully qualified domain name.
+       :param ip_family: 'A' or 'AAAA'"""
+       filename = '/var/cache/bind/dyn.colgarra.priv.at'
+       zonename = os.path.basename(filename)
+       zone = dns.zone.from_file(filename, zonename, relativize=False)
+       for name, ttl, rdata in zone.iterate_rdatas(ip_family):
+               if name[:-1] == fqdn:  # [:-1] removes trailing dot
+                       return ipaddr.IPAddress(rdata.address)
+
+
 def reverse_lookup(ip):
        """Returns an iterator of fqdns for the given IP address.
 
@@ -59,16 +72,25 @@ def blockip_whitelist_add(ip):
        """
        :param ip: ipv4 address
        :raises a BlockipError in case of errors."""
-       command = ['iptables', '-I', 'blockip', '-s', str(ip), '-j', 'ACCEPT']
-       check_call(command)
+       if ipfamily_by_ip(ip) == 'A':
+               command = ['iptables', '-I', 'blockip', '-s', str(ip), '-j', 'ACCEPT']
+               check_call(command)
 
 
 def blockip_whitelist_delete(ip):
        """
        :param ip: ipv4 address
        :raises a BlockipError in case of errors."""
-       command = ['iptables', '-D', 'blockip', '-s', str(ip), '-j', 'ACCEPT']
-       check_call(command)
+       if ipfamily_by_ip(ip) == 'A':
+               command = ['iptables', '-D', 'blockip', '-s', str(ip), '-j', 'ACCEPT']
+               check_call(command)
+
+
+def blockip_whitelist_delete_if_unused(ip):
+       if ipfamily_by_ip(args.ip) == 'A':
+               sync_dynamic_zones()
+               if len(list(reverse_lookup(ip))) == 0:
+                       blockip_whitelist_delete(ip)
 
 
 def main(args):
@@ -79,15 +101,15 @@ def main(args):
                                nsupdate_delete(args.fqdn, 'AAAA')
                        else:
                                nsupdate_delete(args.fqdn, ipfamily_by_ip(args.ip))
-                               if ipfamily_by_ip(args.ip) == 'A':
-                                       sync_dynamic_zones()
-                                       if len(list(reverse_lookup(args.ip))) == 0:
-                                               blockip_whitelist_delete(args.ip)
+                               blockip_whitelist_delete_if_unused(args.ip)
                else:
-                       nsupdate_delete(args.fqdn, ipfamily_by_ip(args.ip))
+                       ipfamily = ipfamily_by_ip(args.ip)
+                       old_ip = forward_lookup(args.fqdn, ipfamily)
+                       nsupdate_delete(args.fqdn, ipfamily)
+                       if old_ip is not None:
+                               blockip_whitelist_delete_if_unused(old_ip)
                        nsupdate_add(args.fqdn, args.ttl, args.ip)
-                       if ipfamily_by_ip(args.ip) == 'A':
-                               blockip_whitelist_add(args.ip)
+                       blockip_whitelist_add(args.ip)
        except CalledProcessError as e:
                sys.exit(e.returncode)