From a892c5946a07cb8f94ce1c39918859c37cfaeb21 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Mon, 7 Jul 2014 18:25:14 +0000 Subject: [PATCH] Add support for the BIND nsupdate utility --- ddns.conf.sample | 9 ++++++ src/ddns/providers.py | 67 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/ddns.conf.sample b/ddns.conf.sample index 29b1ef1..3dd54c9 100644 --- a/ddns.conf.sample +++ b/ddns.conf.sample @@ -20,6 +20,15 @@ # username = user # password = pass +# [test.bind.nsupdate] +# provider = nsupdate +# +# (optional) +# server = 1.2.3.4 +# key = name +# secret = XYZ +# ttl = 60 + # [test.dhs.org] # provider = dhs.org # username = user diff --git a/src/ddns/providers.py b/src/ddns/providers.py index ed893a4..bc16c4c 100644 --- a/src/ddns/providers.py +++ b/src/ddns/providers.py @@ -20,6 +20,7 @@ ############################################################################### import logging +import subprocess import urllib2 import xml.dom.minidom @@ -253,6 +254,72 @@ class DDNSProviderAllInkl(DDNSProvider): raise DDNSUpdateError +class DDNSProviderBindNsupdate(DDNSProvider): + handle = "nsupdate" + name = "BIND nsupdate utility" + website = "http://en.wikipedia.org/wiki/Nsupdate" + + DEFAULT_TTL = 60 + + def update(self): + scriptlet = self.__make_scriptlet() + + # -v enables TCP hence we transfer keys and other data that may + # exceed the size of one packet. + # -t sets the timeout + command = ["nsupdate", "-v", "-t", "60"] + + p = subprocess.Popen(command, shell=True, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, + ) + stdout, stderr = p.communicate(scriptlet) + + if p.returncode == 0: + return + + raise DDNSError("nsupdate terminated with error code: %s\n %s" % (p.returncode, stderr)) + + def __make_scriptlet(self): + scriptlet = [] + + # Set a different server the update is sent to. + server = self.get("server", None) + if server: + scriptlet.append("server %s" % server) + + key = self.get("key", None) + if key: + secret = self.get("secret") + + scriptlet.append("key %s %s" % (key, secret)) + + ttl = self.get("ttl", self.DEFAULT_TTL) + + # Perform an update for each supported protocol. + for rrtype, proto in (("AAAA", "ipv6"), ("A", "ipv4")): + address = self.get_address(proto) + if not address: + continue + + scriptlet.append("update delete %s. %s" % (self.hostname, rrtype)) + scriptlet.append("update add %s. %s %s %s" % \ + (self.hostname, ttl, rrtype, address)) + + # Send the actions to the server. + scriptlet.append("send") + scriptlet.append("quit") + + logger.debug(_("Scriptlet:")) + for line in scriptlet: + # Masquerade the line with the secret key. + if line.startswith("key"): + line = "key **** ****" + + logger.debug(" %s" % line) + + return "\n".join(scriptlet) + + class DDNSProviderDHS(DDNSProvider): handle = "dhs.org" name = "DHS International" -- 2.39.2