This script is now in Python.
authorPhilipp Spitzer <philipp@spitzer.priv.at>
Tue, 25 Mar 2014 22:41:11 +0000 (23:41 +0100)
committerPhilipp Spitzer <philipp@spitzer.priv.at>
Tue, 25 Mar 2014 22:53:07 +0000 (23:53 +0100)
bin/nsupdate_dyndns

index dd9d5f0..604da6b 100755 (executable)
@@ -1,9 +1,63 @@
-#!/bin/bash
+#!/usr/bin/python
+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
+def ipfamily_by_ip(ip):
+       if isinstance(ip, ipaddr.IPv4Address):
+               return 'A'
+       elif isinstance(ip, ipaddr.IPv6Address):
+               return 'AAAA'
+       assert False
+
+
+def nsupdate_add(hostname, domain, ttl, ip):
+       """ip_family: A or AAAA"""
+       command = "update add {hostname}.{domain} {ttl} IN {ip_family} {ip}\n\n".format(hostname=hostname, domain=domain, ttl=ttl, ip_family=ipfamily_by_ip(ip), ip=ip)
+       p = Popen(['nsupdate', '-l'], stdin=PIPE)
+       p.communicate(command)
+
+
+def nsupdate_delete(hostname, domain, ip_family):
+       """ip_family: A or AAAA"""
+       command = "update delete {hostname}.{domain} {ip_family}\n\n".format(hostname=hostname, domain=domain, ip_family=ip_family)
+       p = Popen(['nsupdate', '-l'], stdin=PIPE)
+       p.communicate(command)
+
+
+def main(args):
+       if args.delete:
+               nsupdate_delete(args.hostname, args.domain, 'A')
+               nsupdate_delete(args.hostname, args.domain, 'AAAA')
+       else:
+               nsupdate_delete(args.hostname, args.domain, ipfamily_by_ip(args.ip))
+               nsupdate_add(args.hostname, args.domain, args.ttl, args.ip)
+
+
+if __name__ == '__main__':
+       parser = argparse.ArgumentParser(description='Add or delete a hostname 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('hostname', help='hostname to add or delete, e.g. myserver')
+       args = parser.parse_args()
+
+       args.domain = 'dyn.colgarra.priv.at' # <---- TODO
+       args.ttl = 600 # <---- TODO
+
+       # 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 hostname
+       if re.match(r'[-0-9a-z]+(\.[-0-9a-z]+)*$', args.hostname) is None:
+               parser.error('The hostname has an invalid format.')
+
+       main(args)