]>
git.ipfire.org Git - oddments/ddns.git/blob - src/ddns/providers.py
21159727ad989ca297604ed1574af78901d6568d
2 ###############################################################################
4 # ddns - A dynamic DNS client for IPFire #
5 # Copyright (C) 2012 IPFire development team #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
26 # Import all possible exception types.
29 logger
= logging
.getLogger("ddns.providers")
32 class DDNSProvider(object):
34 # A short string that uniquely identifies
38 # The full name of the provider.
41 # A weburl to the homepage of the provider.
42 # (Where to register a new account?)
45 # A list of supported protocols.
46 "protocols" : ["ipv6", "ipv4"],
51 def __init__(self
, core
, **settings
):
54 # Copy a set of default settings and
55 # update them by those from the configuration file.
56 self
.settings
= self
.DEFAULT_SETTINGS
.copy()
57 self
.settings
.update(settings
)
60 return "<DDNS Provider %s (%s)>" % (self
.name
, self
.handle
)
62 def __cmp__(self
, other
):
63 return cmp(self
.hostname
, other
.hostname
)
68 Returns the name of the provider.
70 return self
.INFO
.get("name")
75 Returns the website URL of the provider
76 or None if that is not available.
78 return self
.INFO
.get("website", None)
83 Returns the handle of this provider.
85 return self
.INFO
.get("handle")
87 def get(self
, key
, default
=None):
89 Get a setting from the settings dictionary.
91 return self
.settings
.get(key
, default
)
96 Fast access to the hostname.
98 return self
.get("hostname")
103 Fast access to the username.
105 return self
.get("username")
110 Fast access to the password.
112 return self
.get("password")
116 return self
.INFO
.get("protocols")
119 # Check if we actually need to update this host.
120 if self
.is_uptodate(self
.protocols
):
121 logger
.info(_("%s is already up to date") % self
.hostname
)
124 # Execute the update.
128 raise NotImplementedError
130 def is_uptodate(self
, protos
):
132 Returns True if this host is already up to date
133 and does not need to change the IP address on the
137 addresses
= self
.core
.system
.resolve(self
.hostname
, proto
)
139 current_address
= self
.get_address(proto
)
141 if not current_address
in addresses
:
146 def send_request(self
, *args
, **kwargs
):
148 Proxy connection to the send request
151 return self
.core
.system
.send_request(*args
, **kwargs
)
153 def get_address(self
, proto
):
155 Proxy method to get the current IP address.
157 return self
.core
.system
.get_address(proto
)
160 class DDNSProviderDHS(DDNSProvider
):
162 "handle" : "dhs.org",
163 "name" : "DHS International",
164 "website" : "http://dhs.org/",
165 "protocols" : ["ipv4",]
168 # No information about the used update api provided on webpage,
169 # grabed from source code of ez-ipudate.
170 url
= "http://members.dhs.org/nic/hosts"
174 "username" : self
.username
,
175 "password" : self
.password
,
179 "domain" : self
.hostname
,
180 "ip" : self
.get_address("ipv4"),
182 "hostcmdstage" : "2",
186 # Send update to the server.
187 response
= self
.send_request(url
, username
=self
.username
, password
=self
.password
,
190 # Handle success messages.
191 if response
.code
== 200:
194 # Handle error codes.
195 elif response
.code
== "401":
196 raise DDNSAuthenticationError
198 # If we got here, some other update error happened.
199 raise DDNSUpdateError
202 class DDNSProviderDNSpark(DDNSProvider
):
204 "handle" : "dnspark.com",
206 "website" : "http://dnspark.com/",
207 "protocols" : ["ipv4",]
210 # Informations to the used api can be found here:
211 # https://dnspark.zendesk.com/entries/31229348-Dynamic-DNS-API-Documentation
212 url
= "https://control.dnspark.com/api/dynamic/update.php"
216 "username" : self
.username
,
217 "password" : self
.password
,
221 "domain" : self
.hostname
,
222 "ip" : self
.get_address("ipv4"),
225 # Send update to the server.
226 response
= self
.send_request(url
, username
=self
.username
, password
=self
.password
,
229 # Get the full response message.
230 output
= response
.read()
232 # Handle success messages.
233 if output
.startswith("ok") or output
.startswith("nochange"):
236 # Handle error codes.
237 if output
== "unauth":
238 raise DDNSAuthenticationError
239 elif output
== "abuse":
241 elif output
== "blocked":
242 raise DDNSBlockedError
243 elif output
== "nofqdn":
244 raise DDNSRequestError(_("No valid FQDN was given."))
245 elif output
== "nohost":
246 raise DDNSRequestError(_("Invalid hostname specified."))
247 elif output
== "notdyn":
248 raise DDNSRequestError(_("Hostname not marked as a dynamic host."))
249 elif output
== "invalid":
250 raise DDNSRequestError(_("Invalid IP address has been sent."))
252 # If we got here, some other update error happened.
253 raise DDNSUpdateError
256 class DDNSProviderLightningWireLabs(DDNSProvider
):
258 "handle" : "dns.lightningwirelabs.com",
259 "name" : "Lightning Wire Labs",
260 "website" : "http://dns.lightningwirelabs.com/",
261 "protocols" : ["ipv6", "ipv4",]
264 # Information about the format of the HTTPS request is to be found
265 # https://dns.lightningwirelabs.com/knowledge-base/api/ddns
266 url
= "https://dns.lightningwirelabs.com/update"
271 Fast access to the token.
273 return self
.get("token")
277 "hostname" : self
.hostname
,
280 # Check if we update an IPv6 address.
281 address6
= self
.get_address("ipv6")
283 data
["address6"] = address6
285 # Check if we update an IPv4 address.
286 address4
= self
.get_address("ipv4")
288 data
["address4"] = address4
290 # Raise an error if none address is given.
291 if not data
.has_key("address6") and not data
.has_key("address4"):
292 raise DDNSConfigurationError
294 # Check if a token has been set.
296 data
["token"] = self
.token
298 # Check for username and password.
299 elif self
.username
and self
.password
:
301 "username" : self
.username
,
302 "password" : self
.password
,
305 # Raise an error if no auth details are given.
307 raise DDNSConfigurationError
309 # Send update to the server.
310 response
= self
.send_request(self
.url
, data
=data
)
312 # Handle success messages.
313 if response
.code
== 200:
316 # Handle error codes.
317 if response
.code
== 403:
318 raise DDNSAuthenticationError
319 elif response
.code
== 400:
320 raise DDNSRequestError
322 # If we got here, some other update error happened.
323 raise DDNSUpdateError
326 class DDNSProviderNOIP(DDNSProvider
):
328 "handle" : "no-ip.com",
330 "website" : "http://www.no-ip.com/",
331 "protocols" : ["ipv4",]
334 # Information about the format of the HTTP request is to be found
335 # here: http://www.no-ip.com/integrate/request and
336 # here: http://www.no-ip.com/integrate/response
338 url
= "http://%(username)s:%(password)s@dynupdate.no-ip.com/nic/update"
342 "username" : self
.username
,
343 "password" : self
.password
,
347 "hostname" : self
.hostname
,
348 "address" : self
.get_address("ipv4"),
351 # Send update to the server.
352 response
= self
.send_request(url
, data
=data
)
354 # Get the full response message.
355 output
= response
.read()
357 # Handle success messages.
358 if output
.startswith("good") or output
.startswith("nochg"):
361 # Handle error codes.
362 if output
== "badauth":
363 raise DDNSAuthenticationError
364 elif output
== "aduse":
366 elif output
== "911":
367 raise DDNSInternalServerError
369 # If we got here, some other update error happened.
370 raise DDNSUpdateError
373 class DDNSProviderSelfhost(DDNSProvider
):
375 "handle" : "selfhost.de",
376 "name" : "Selfhost.de",
377 "website" : "http://www.selfhost.de/",
378 "protocols" : ["ipv4",],
381 url
= "https://carol.selfhost.de/update"
385 "username" : self
.username
,
386 "password" : self
.password
,
390 response
= self
.send_request(self
.url
, data
=data
)
392 match
= re
.search("status=20(0|4)", response
.read())
394 raise DDNSUpdateError