Now in both scripts only fqdn are allowed.
[toast/tdyndns.git] / bin / nsupdate_dyndns
1 #!/usr/bin/python
2 import re
3 import argparse
4 from subprocess import Popen, PIPE
5 import ipaddr
6
7
8 def ipfamily_by_ip(ip):
9         if isinstance(ip, ipaddr.IPv4Address):
10                 return 'A'
11         elif isinstance(ip, ipaddr.IPv6Address):
12                 return 'AAAA'
13         assert False
14
15
16 def nsupdate_add(fqdn, ttl, ip):
17         """
18         :param fqdn: Fully qualified domain name
19         :param ip_family: A or AAAA"""
20         command = "update add {fqdn} {ttl} IN {ip_family} {ip}\n\n".format(fqdn=fqdn, ttl=ttl, ip_family=ipfamily_by_ip(ip), ip=ip)
21         p = Popen(['nsupdate', '-l'], stdin=PIPE)
22         p.communicate(command)
23
24
25 def nsupdate_delete(fqdn, ip_family):
26         """
27         :param fqdn: Fully qualified domain name
28         :param ip_family: A or AAAA"""
29         command = "update delete {fqdn} {ip_family}\n\n".format(fqdn=fqdn, ip_family=ip_family)
30         p = Popen(['nsupdate', '-l'], stdin=PIPE)
31         p.communicate(command)
32
33
34 def main(args):
35         if args.delete:
36                 if args.ip is None:
37                         nsupdate_delete(args.fqdn, 'A')
38                         nsupdate_delete(args.fqdn, 'AAAA')
39                 else:
40                         nsupdate_delete(args.fqdn, ipfamily_by_ip(args.ip))
41         else:
42                 nsupdate_delete(args.fqdn, ipfamily_by_ip(args.ip))
43                 nsupdate_add(args.fqdn, args.ttl, args.ip)
44
45
46 if __name__ == '__main__':
47         parser = argparse.ArgumentParser(description='Add or delete a domain name from dyndns (simplifies call to nsupdate).')
48         parser.add_argument('-d', '--delete', action='store_true', help='delete instead of add')
49         parser.add_argument('-i', '--ip', help='IP address (either IPv4 or IPv6)')
50         # parser.add_argument('-t', '--ttl', type=int, default=600, help='TTL (default: 600)')
51         parser.add_argument('fqdn', help='fully qualified domain name to add or delete, e.g. myserver.dyn.example.com')
52         args = parser.parse_args()
53
54         args.ttl = 600 # <---- TODO
55
56         # check ip
57         if not args.delete and not args.ip:
58                 parser.error('The IP address is mandatory')
59         if args.ip:
60                 try:
61                         args.ip = ipaddr.IPAddress(args.ip) # throws an exception if the IP address is not valid
62                 except ValueError:
63                         parser.error('The IP address is not valid')
64
65         # check fqdn
66         if re.match(r'[-0-9a-z]+(\.[-0-9a-z]+)*$', args.fqdn) is None:
67                 parser.error('The fqdn has an invalid format.')
68
69         main(args)