2 """Dynamic DNS script. Expects URLs from routers in the form
3 http://dyndns.colgarra.priv.at/nic/update??username=<username>&password=<pass>&hostname=<domain>&myip=<ipaddr>
9 from subprocess import call
14 PASSWORD = 'hygCithOrs5'
15 ZONE = '.dyn.colgarra.priv.at'
25 fields = cgi.FieldStorage()
27 # the following fields are supported by most dyndns providers
28 # if a parameter is not provided, the .getvalue method returns None
29 username = fields.getvalue('username')
30 password = fields.getvalue('password')
31 hostname = fields.getvalue('hostname')
32 myip = fields.getvalue('myip')
33 wildcard = fields.getvalue('wildcard')
34 mx = fields.getvalue('mx')
35 backmx = fields.getvalue('backmx')
36 offline = fields.getvalue('offline')
37 system = fields.getvalue('system')
38 url = fields.getvalue('url')
41 # Base class for our exceptions
42 class DynDnsError(Exception):
45 class AuthError(DynDnsError):
46 returncode = 'badauth'
48 class UsernameMissing(AuthError):
51 class UsernameInvalid(AuthError):
54 class PasswordMissing(AuthError):
57 class PasswordWrong(AuthError):
60 class HostnameError(DynDnsError):
61 returncode = 'notfqdn'
63 class HostnameMissing(HostnameError):
66 class PasswordWrong(HostnameError):
69 class MyipError(DynDnsError):
70 returncode = 'badip' # not documented at dyn.com
72 class MyipMissing(MyipError):
75 class MyipInvalid(MyipError):
78 class OfflineInvalid(DynDnsError):
79 returncode = 'badparam' # not documented at dyn.com
84 raise UsernameMissing()
86 user_info = pwd.getpwnam(username)
88 raise UsernameInvalid()
89 if user_info.pw_uid < 1000:
90 raise UsernameInvalid()
94 raise PasswordMissing()
95 if password != PASSWORD:
100 raise HostnameMissing()
101 if re.match(r'[-0-9a-z]+(\.[-0-9a-z]+)*$', hostname) is None:
102 raise HostnameInvalid()
105 hostname = hostname.strip()
106 if hostname.endswith(ZONE):
107 hostname = hostname[:-len(ZONE)]
110 if offline is None or offline.lower() == 'no':
112 elif offline.lower() == 'yes':
115 raise OfflineInvalid()
122 ip = ipaddr.IPAddress(myip) # throws an exception if the IP address is not valid
125 if isinstance(ip, ipaddr.IPv4Address):
127 elif isinstance(ip, ipaddr.IPv6Address):
130 raise MyipInvalid() # should never happen
134 call(['sudo', '/usr/local/bin/nsupdate_dyndns_del', hostname, 'A'])
135 call(['sudo', '/usr/local/bin/nsupdate_dyndns_del', hostname, 'AAAA'])
137 call(['sudo', '/usr/local/bin/nsupdate_dyndns', hostname, myip, iptype])
140 print "Content-Type: text/html"
143 # Note: we should return 'nochg' in case the IP has not changed, however we don't know yet.
146 except DynDnsError as error:
147 print "Content-Type: text/html"
150 print error.returncode