2 """Dynamic DNS script. Expects URLs from routers in the form
3 http://dyndns.colgarra.priv.at/nic/update?hostname=<domain>&myip=<ipaddr>
8 from subprocess import call
22 # Base class for our exceptions
23 class DynDnsError(Exception):
26 class HostnameError(DynDnsError):
27 returncode = 'notfqdn'
29 class HostnameMissing(HostnameError):
32 class PasswordWrong(HostnameError):
35 class MyipError(DynDnsError):
36 returncode = 'badip' # not documented at dyn.com
38 class MyipMissing(MyipError):
41 class MyipInvalid(MyipError):
44 class OfflineInvalid(DynDnsError):
45 returncode = 'badparam' # not documented at dyn.com
47 class NsupdateError(DynDnsError):
51 fields = cgi.FieldStorage()
53 # the following fields are supported by most dyndns providers
54 # if a parameter is not provided, the .getvalue method returns None
55 hostname = fields.getvalue('hostname')
56 myip = fields.getvalue('myip')
57 wildcard = fields.getvalue('wildcard')
58 mx = fields.getvalue('mx')
59 backmx = fields.getvalue('backmx')
60 offline = fields.getvalue('offline')
61 system = fields.getvalue('system')
62 url = fields.getvalue('url')
68 raise HostnameMissing()
69 if re.match(r'[-0-9a-z]+(\.[-0-9a-z]+)*$', hostname) is None:
70 raise HostnameInvalid()
73 hostname = hostname.strip()
76 if offline is None or offline.lower() == 'no':
78 elif offline.lower() == 'yes':
81 raise OfflineInvalid()
86 # try HTTP_X_FORWARDED_FOR
87 myip = os.environ.get('HTTP_X_FORWARDED_FOR')
88 if not myip: # empty string if not present
90 myip = os.environ.get('REMOTE_ADDR')
91 if not myip: # empty string if not present
95 ipaddr.IPAddress(myip) # throws an exception if the IP address is not valid
100 call_params = ['sudo', 'tdyndns_update']
102 call_params.append('--delete')
104 call_params.extend(['--ip', myip])
105 call_params.append(hostname)
106 retcode = call(call_params)
108 raise NsupdateError()
111 print "Content-Type: text/html"
114 # Note: we should return 'nochg' in case the IP has not changed, however we don't know yet.
117 except DynDnsError as error:
118 print "Content-Type: text/html"
119 print "Status: 200 OK"
121 print error.returncode