2 """Dynamic DNS script. Expects URLs from routers in the form
3 https://info.colgarra.priv.at/dyndns/dyndns.py?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 IpError(DynDnsError):
70 returncode = 'badip' # not documented at dyn.com
72 class IpMissing(IpError):
75 class IpInvalid(IpError):
81 raise UsernameMissing()
83 user_info = pwd.getpwnam(username)
85 raise UsernameInvalid()
86 if user_info.pw_uid < 1000:
87 raise UsernameInvalid()
91 raise PasswordMissing()
92 if password != PASSWORD:
97 raise HostnameMissing()
98 if re.match(r'[-0-9a-z]+(\.[-0-9a-z]+)*$', hostname) is None:
99 raise HostnameInvalid()
102 hostname = hostname.strip()
103 if hostname.endswith(ZONE):
104 hostname = hostname[:-len(ZONE)]
110 ip = ipaddr.IPAddress(myip) # throws an exception if the IP address is not valid
113 if isinstance(ip, ipaddr.IPv4Address):
115 elif isinstance(ip, ipaddr.IPv6Address):
118 raise IpInvalid() # should never happen
121 print "Content-Type: text/html"
123 call(['sudo', '/usr/local/bin/nsupdate_dyndns', hostname, myip, iptype])
125 # Note: we should return 'nochg' in case the IP has not changed, however we don't know yet.
128 except DynDnsError as error:
129 print "Content-Type: text/html"
132 print error.returncode