]>
git.ipfire.org Git - oddments/ddns.git/blob - src/ddns/providers.py
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 ###############################################################################
22 # Import all possible exception types.
25 class DDNSProvider(object):
27 # A short string that uniquely identifies
31 # The full name of the provider.
34 # A weburl to the homepage of the provider.
35 # (Where to register a new account?)
38 # A list of supported protocols.
39 "protocols" : ["ipv6", "ipv4"],
44 def __init__(self
, core
, **settings
):
47 # Copy a set of default settings and
48 # update them by those from the configuration file.
49 self
.settings
= self
.DEFAULT_SETTINGS
.copy()
50 self
.settings
.update(settings
)
53 return "<DDNS Provider %s (%s)>" % (self
.name
, self
.handle
)
55 def __cmp__(self
, other
):
56 return cmp(self
.hostname
, other
.hostname
)
61 Returns the name of the provider.
63 return self
.INFO
.get("name")
68 Returns the website URL of the provider
69 or None if that is not available.
71 return self
.INFO
.get("website", None)
76 Returns the handle of this provider.
78 return self
.INFO
.get("handle")
80 def get(self
, key
, default
=None):
82 Get a setting from the settings dictionary.
84 return self
.settings
.get(key
, default
)
89 Fast access to the hostname.
91 return self
.get("hostname")
96 Fast access to the username.
98 return self
.get("username")
103 Fast access to the password.
105 return self
.get("password")
111 raise NotImplementedError
113 def send_request(self
, *args
, **kwargs
):
115 Proxy connection to the send request
118 return self
.core
.system
.send_request(*args
, **kwargs
)
120 def get_address(self
, proto
):
122 Proxy method to get the current IP address.
124 return self
.core
.system
.get_address(proto
)
127 class DDNSProviderDHS(DDNSProvider
):
129 "handle" : "dhs.org",
130 "name" : "DHS International",
131 "website" : "http://dhs.org/",
132 "protocols" : ["ipv4",]
135 # No information about the used update api provided on webpage,
136 # grabed from source code of ez-ipudate.
137 url
= "http://members.dhs.org/nic/hosts"
141 "username" : self
.username
,
142 "password" : self
.password
,
146 "domain" : self
.hostname
,
147 "ip" : self
.get_address("ipv4"),
149 "hostcmdstage" : "2",
153 # Send update to the server.
154 response
= self
.send_request(url
, username
=self
.username
, password
=self
.password
,
157 # Handle success messages.
158 if response
.code
== 200:
161 # Handle error codes.
162 elif response
.code
== "401":
163 raise DDNSAuthenticationError
165 # If we got here, some other update error happened.
166 raise DDNSUpdateError
169 class DDNSProviderDNSpark(DDNSProvider
):
171 "handle" : "dnspark.com",
173 "website" : "http://dnspark.com/",
174 "protocols" : ["ipv4",]
177 # Informations to the used api can be found here:
178 # https://dnspark.zendesk.com/entries/31229348-Dynamic-DNS-API-Documentation
179 url
= "https://control.dnspark.com/api/dynamic/update.php"
183 "username" : self
.username
,
184 "password" : self
.password
,
188 "domain" : self
.hostname
,
189 "ip" : self
.get_address("ipv4"),
192 # Send update to the server.
193 response
= self
.send_request(url
, username
=self
.username
, password
=self
.password
,
196 # Get the full response message.
197 output
= response
.read()
199 # Handle success messages.
200 if output
.startswith("ok") or output
.startswith("nochange"):
203 # Handle error codes.
204 if output
== "unauth":
205 raise DDNSAuthenticationError
206 elif output
== "abuse":
208 elif output
== "blocked":
209 raise DDNSBlockedError
210 elif output
== "nofqdn":
211 raise DDNSRequestError(_("No valid FQDN was given."))
212 elif output
== "nohost":
213 raise DDNSRequestError(_("Invalid hostname specified."))
214 elif output
== "notdyn":
215 raise DDNSRequestError(_("Hostname not marked as a dynamic host."))
216 elif output
== "invalid":
217 raise DDNSRequestError(_("Invalid IP address has been sent."))
219 # If we got here, some other update error happened.
220 raise DDNSUpdateError
223 class DDNSProviderLightningWireLabs(DDNSProvider
):
225 "handle" : "dns.lightningwirelabs.com",
226 "name" : "Lightning Wire Labs",
227 "website" : "http://dns.lightningwirelabs.com/",
228 "protocols" : ["ipv6", "ipv4",]
231 # Information about the format of the HTTPS request is to be found
232 # https://dns.lightningwirelabs.com/knowledge-base/api/ddns
233 url
= "https://dns.lightningwirelabs.com/update"
238 Fast access to the token.
240 return self
.get("token")
244 "hostname" : self
.hostname
,
247 # Check if we update an IPv6 address.
248 address6
= self
.get_address("ipv6")
250 data
["address6"] = address6
252 # Check if we update an IPv4 address.
253 address4
= self
.get_address("ipv4")
255 data
["address4"] = address4
257 # Raise an error if none address is given.
258 if not data
.has_key("address6") and not data
.has_key("address4"):
259 raise DDNSConfigurationError
261 # Check if a token has been set.
263 data
["token"] = self
.token
265 # Check for username and password.
266 elif self
.username
and self
.password
:
268 "username" : self
.username
,
269 "password" : self
.password
,
272 # Raise an error if no auth details are given.
274 raise DDNSConfigurationError
276 # Send update to the server.
277 response
= self
.send_request(url
, data
=data
)
279 # Handle success messages.
280 if response
.code
== 200:
283 # Handle error codes.
284 if response
.code
== "403":
285 raise DDNSAuthenticationError
286 elif response
.code
== "400":
287 raise DDNSRequestError
289 # If we got here, some other update error happened.
290 raise DDNSUpdateError
293 class DDNSProviderNOIP(DDNSProvider
):
295 "handle" : "no-ip.com",
297 "website" : "http://www.no-ip.com/",
298 "protocols" : ["ipv4",]
301 # Information about the format of the HTTP request is to be found
302 # here: http://www.no-ip.com/integrate/request and
303 # here: http://www.no-ip.com/integrate/response
305 url
= "http://%(username)s:%(password)s@dynupdate.no-ip.com/nic/update"
309 "username" : self
.username
,
310 "password" : self
.password
,
314 "hostname" : self
.hostname
,
315 "address" : self
.get_address("ipv4"),
318 # Send update to the server.
319 response
= self
.send_request(url
, data
=data
)
321 # Get the full response message.
322 output
= response
.read()
324 # Handle success messages.
325 if output
.startswith("good") or output
.startswith("nochg"):
328 # Handle error codes.
329 if output
== "badauth":
330 raise DDNSAuthenticationError
331 elif output
== "aduse":
333 elif output
== "911":
334 raise DDNSInternalServerError
336 # If we got here, some other update error happened.
337 raise DDNSUpdateError
340 class DDNSProviderSelfhost(DDNSProvider
):
342 "handle" : "selfhost.de",
343 "name" : "Selfhost.de",
344 "website" : "http://www.selfhost.de/",
345 "protocols" : ["ipv4",],
348 url
= "https://carol.selfhost.de/update"
352 "username" : self
.username
,
353 "password" : self
.password
,
357 response
= self
.send_request(self
.url
, data
=data
)
359 match
= re
.search("status=20(0|4)", response
.read())
361 raise DDNSUpdateError