Now the IP address is only deleted from the blockip whitelist when it is not used...
authorPhilipp Spitzer <philipp@spitzer.priv.at>
Wed, 27 Jul 2016 19:49:38 +0000 (21:49 +0200)
committergregor herrmann <gregoa@debian.org>
Wed, 27 Jul 2016 22:21:38 +0000 (00:21 +0200)
bin/tdyndns_update

index 45c4264..3f46d13 100755 (executable)
@@ -1,23 +1,15 @@
 #!/usr/bin/python
+import os
 import sys
 import re
 import argparse
-from subprocess import Popen, PIPE, call
+from subprocess import Popen, PIPE, check_call, CalledProcessError
 import ipaddr
+import dns.zone  # http://www.dnspython.org/
 
 
-class ExternalProgramError(RuntimeError):
-       pass
-
-
-class NsupdateError(ExternalProgramError):
-       def __init__(self, returncode):
-               self.returncode = returncode
-
-
-class BlockipError(ExternalProgramError):
-       def __init__(self, returncode):
-               self.returncode = returncode
+def sync_dynamic_zones():
+       check_call(['rndc', 'sync'])
 
 
 def ipfamily_by_ip(ip):
@@ -28,6 +20,18 @@ def ipfamily_by_ip(ip):
        assert False
 
 
+def reverse_lookup(ip):
+       """Returns an iterator of fqdns for the given IP address.
+
+       :param ip: Instance of ipaddr.IPv4Address or ipaddr.IPv6Address"""
+       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(ipfamily_by_ip(ip)):
+               if ipaddr.IPAddress(rdata.address) == ip:
+                       yield str(name)
+
+
 def nsupdate_add(fqdn, ttl, ip):
        """
        :param fqdn: Fully qualified domain name
@@ -37,7 +41,7 @@ def nsupdate_add(fqdn, ttl, ip):
        p = Popen(['nsupdate', '-l'], stdin=PIPE)
        p.communicate(command)
        if p.returncode != 0:
-               raise NsupdateError(p.returncode)
+               raise CalledProcessError(p.returncode, 'nsupdate -l')
 
 def nsupdate_delete(fqdn, ip_family):
        """
@@ -48,7 +52,7 @@ def nsupdate_delete(fqdn, ip_family):
        p = Popen(['nsupdate', '-l'], stdin=PIPE)
        p.communicate(command)
        if p.returncode != 0:
-               raise NsupdateError(p.returncode)
+               raise CalledProcessError(p.returncode, 'nsupdate -l')
 
 
 def blockip_whitelist_add(ip):
@@ -56,9 +60,7 @@ 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']
-       p = call(command)
-       if p != 0:
-               raise BlockipError(p)
+       check_call(command)
 
 
 def blockip_whitelist_delete(ip):
@@ -66,9 +68,7 @@ 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']
-       p = call(command)
-       if p != 0:
-               raise BlockipError(p)
+       check_call(command)
 
 
 def main(args):
@@ -80,13 +80,15 @@ def main(args):
                        else:
                                nsupdate_delete(args.fqdn, ipfamily_by_ip(args.ip))
                                if ipfamily_by_ip(args.ip) == 'A':
-                                       blockip_whitelist_delete(args.ip)
+                                       sync_dynamic_zones()
+                                       if len(list(reverse_lookup(args.ip))) == 0:
+                                               blockip_whitelist_delete(args.ip)
                else:
                        nsupdate_delete(args.fqdn, ipfamily_by_ip(args.ip))
                        nsupdate_add(args.fqdn, args.ttl, args.ip)
                        if ipfamily_by_ip(args.ip) == 'A':
                                blockip_whitelist_add(args.ip)
-       except ExternalProgramError as e:
+       except CalledProcessError as e:
                sys.exit(e.returncode)