X-Git-Url: https://git.toastfreeware.priv.at/toast/tdyndns.git/blobdiff_plain/2c1037c4fe9bd6282161b1d46c45140b79d2c627..25ea32904b9ca333a10d45d3a68f822a64505737:/bin/nsupdate_dyndns diff --git a/bin/nsupdate_dyndns b/bin/nsupdate_dyndns index dd9d5f0..4452fe0 100755 --- a/bin/nsupdate_dyndns +++ b/bin/nsupdate_dyndns @@ -1,9 +1,83 @@ -#!/bin/bash +#!/usr/bin/python +import sys +import re +import argparse +from subprocess import Popen, PIPE +import ipaddr -hostname=$1 -myip=$2 -type=$3 # A or AAAA -ttl=600 -domain=dyn.colgarra.priv.at -echo -e "update delete $hostname.$domain $type\nupdate add $hostname.$domain $ttl IN $type $myip\n" | nsupdate -l +class NsupdateError(Exception): + def __init__(self, returncode): + self.returncode = returncode + + +def ipfamily_by_ip(ip): + if isinstance(ip, ipaddr.IPv4Address): + return 'A' + elif isinstance(ip, ipaddr.IPv6Address): + return 'AAAA' + assert False + + +def nsupdate_add(fqdn, ttl, ip): + """ + :param fqdn: Fully qualified domain name + :param ip_family: A or AAAA + :raises an NsupdateError in case of errors.""" + command = "update add {fqdn} {ttl} IN {ip_family} {ip}\n\n".format(fqdn=fqdn, ttl=ttl, ip_family=ipfamily_by_ip(ip), ip=ip) + p = Popen(['nsupdate', '-l'], stdin=PIPE) + p.communicate(command) + if p.returncode != 0: + raise NsupdateError(p.returncode) + + +def nsupdate_delete(fqdn, ip_family): + """ + :param fqdn: Fully qualified domain name + :param ip_family: A or AAAA + :raises an NsupdateError in case of errors.""" + command = "update delete {fqdn} {ip_family}\n\n".format(fqdn=fqdn, ip_family=ip_family) + p = Popen(['nsupdate', '-l'], stdin=PIPE) + p.communicate(command) + if p.returncode != 0: + raise NsupdateError(p.returncode) + + +def main(args): + try: + if args.delete: + if args.ip is None: + nsupdate_delete(args.fqdn, 'A') + nsupdate_delete(args.fqdn, 'AAAA') + else: + nsupdate_delete(args.fqdn, ipfamily_by_ip(args.ip)) + else: + nsupdate_delete(args.fqdn, ipfamily_by_ip(args.ip)) + nsupdate_add(args.fqdn, args.ttl, args.ip) + except NsupdateError as e: + sys.exit(e.returncode) + + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Add or delete a domain name from dyndns (simplifies call to nsupdate).') + parser.add_argument('-d', '--delete', action='store_true', help='delete instead of add') + parser.add_argument('-i', '--ip', help='IP address (either IPv4 or IPv6)') + parser.add_argument('-t', '--ttl', type=int, default=600, help='TTL (default: 600)') + parser.add_argument('fqdn', help='fully qualified domain name to add or delete, e.g. myserver.dyn.example.com') + args = parser.parse_args() + + # check ip + if not args.delete and not args.ip: + parser.error('The IP address is mandatory') + if args.ip: + try: + args.ip = ipaddr.IPAddress(args.ip) # throws an exception if the IP address is not valid + except ValueError: + parser.error('The IP address is not valid') + + # check fqdn + if re.match(r'[-0-9a-z]+(\.[-0-9a-z]+)*$', args.fqdn) is None: + parser.error('The fqdn has an invalid format.') + + main(args)