X-Git-Url: https://git.toastfreeware.priv.at/toast/tdyndns.git/blobdiff_plain/8693ac19b712eeece371d48c4e2af3325386eb1b..50b28146b7c48d276d60710078cc779f17a1bce4:/bin/tdyndns_update diff --git a/bin/tdyndns_update b/bin/tdyndns_update index 45c4264..3f46d13 100755 --- a/bin/tdyndns_update +++ b/bin/tdyndns_update @@ -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)