]>
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")
108 raise NotImplementedError
110 def send_request(self
, *args
, **kwargs
):
112 Proxy connection to the send request
115 return self
.core
.system
.send_request(*args
, **kwargs
)
117 def get_address(self
, proto
):
119 Proxy method to get the current IP address.
121 return self
.core
.system
.get_address(proto
)
124 class DDNSProviderDHS(DDNSProvider
):
126 "handle" : "dhs.org",
127 "name" : "DHS International",
128 "website" : "http://dhs.org/",
129 "protocols" : ["ipv4",]
132 # No information about the used update api provided on webpage,
133 # grabed from source code of ez-ipudate.
134 url
= "http://members.dhs.org/nic/hosts"
138 "username" : self
.username
,
139 "password" : self
.password
,
143 "domain" : self
.hostname
,
144 "ip" : self
.get_address("ipv4"),
146 "hostcmdstage" : "2",
150 # Send update to the server.
151 response
= self
.send_request(url
, username
=self
.username
, password
=self
.password
,
154 # Handle success messages.
155 if response
.code
== 200:
158 # Handle error codes.
159 elif response
.code
== "401":
160 raise DDNSAuthenticationError
162 # If we got here, some other update error happened.
163 raise DDNSUpdateError
166 class DDNSProviderDNSpark(DDNSProvider
):
168 "handle" : "dnspark.com",
170 "website" : "http://dnspark.com/",
171 "protocols" : ["ipv4",]
174 # Informations to the used api can be found here:
175 # https://dnspark.zendesk.com/entries/31229348-Dynamic-DNS-API-Documentation
176 url
= "https://control.dnspark.com/api/dynamic/update.php"
180 "username" : self
.username
,
181 "password" : self
.password
,
185 "domain" : self
.hostname
,
186 "ip" : self
.get_address("ipv4"),
189 # Send update to the server.
190 response
= self
.send_request(url
, username
=self
.username
, password
=self
.password
,
193 # Get the full response message.
194 output
= response
.read()
196 # Handle success messages.
197 if output
.startswith("ok") or output
.startswith("nochange"):
200 # Handle error codes.
201 if output
== "unauth":
202 raise DDNSAuthenticationError
203 elif output
== "abuse":
205 elif output
== "blocked":
206 raise DDNSBlockedError
207 elif output
== "nofqdn":
208 raise DDNSRequestError(_("No valid FQDN was given."))
209 elif output
== "nohost":
210 raise DDNSRequestError(_("Invalid hostname specified."))
211 elif output
== "notdyn":
212 raise DDNSRequestError(_("Hostname not marked as a dynamic host."))
213 elif output
== "invalid":
214 raise DDNSRequestError(_("Invalid IP address has been sent."))
216 # If we got here, some other update error happened.
217 raise DDNSUpdateError
220 class DDNSProviderLightningWireLabs(DDNSProvider
):
222 "handle" : "dns.lightningwirelabs.com",
223 "name" : "Lightning Wire Labs",
224 "website" : "http://dns.lightningwirelabs.com/",
225 "protocols" : ["ipv6", "ipv4",]
228 # Information about the format of the HTTPS request is to be found
229 # https://dns.lightningwirelabs.com/knowledge-base/api/ddns
230 url
= "https://dns.lightningwirelabs.com/update"
235 Fast access to the token.
237 return self
.get("token")
241 "hostname" : self
.hostname
,
244 # Check if we update an IPv6 address.
245 address6
= self
.get_address("ipv6")
247 data
["address6"] = address6
249 # Check if we update an IPv4 address.
250 address4
= self
.get_address("ipv4")
252 data
["address4"] = address4
254 # Raise an error if none address is given.
255 if not data
.has_key("address6") and not data
.has_key("address4"):
256 raise DDNSConfigurationError
258 # Check if a token has been set.
260 data
["token"] = self
.token
262 # Check for username and password.
263 elif self
.username
and self
.password
:
265 "username" : self
.username
,
266 "password" : self
.password
,
269 # Raise an error if no auth details are given.
271 raise DDNSConfigurationError
273 # Send update to the server.
274 response
= self
.send_request(url
, data
=data
)
276 # Handle success messages.
277 if response
.code
== 200:
280 # Handle error codes.
281 if response
.code
== "403":
282 raise DDNSAuthenticationError
283 elif response
.code
== "400":
284 raise DDNSRequestError
286 # If we got here, some other update error happened.
287 raise DDNSUpdateError
290 class DDNSProviderNOIP(DDNSProvider
):
292 "handle" : "no-ip.com",
294 "website" : "http://www.no-ip.com/",
295 "protocols" : ["ipv4",]
298 # Information about the format of the HTTP request is to be found
299 # here: http://www.no-ip.com/integrate/request and
300 # here: http://www.no-ip.com/integrate/response
302 url
= "http://%(username)s:%(password)s@dynupdate.no-ip.com/nic/update"
306 "username" : self
.username
,
307 "password" : self
.password
,
311 "hostname" : self
.hostname
,
312 "address" : self
.get_address("ipv4"),
315 # Send update to the server.
316 response
= self
.send_request(url
, data
=data
)
318 # Get the full response message.
319 output
= response
.read()
321 # Handle success messages.
322 if output
.startswith("good") or output
.startswith("nochg"):
325 # Handle error codes.
326 if output
== "badauth":
327 raise DDNSAuthenticationError
328 elif output
== "aduse":
330 elif output
== "911":
331 raise DDNSInternalServerError
333 # If we got here, some other update error happened.
334 raise DDNSUpdateError
337 class DDNSProviderSelfhost(DDNSProvider
):
339 "handle" : "selfhost.de",
340 "name" : "Selfhost.de",
341 "website" : "http://www.selfhost.de/",
342 "protocols" : ["ipv4",],
345 url
= "https://carol.selfhost.de/update"
349 "username" : self
.username
,
350 "password" : self
.password
,
354 response
= self
.send_request(self
.url
, data
=data
)
356 match
= re
.search("status=20(0|4)", response
.read())
358 raise DDNSUpdateError