# configuration variables
server = 'ns.ralfj.de'
-user = 'yourusername'
+domains = ['your.domain.ralfj.de'] # list of domains to update
password = 'yourpassword'
-domain = 'your.domain.ralfj.de'
# END of configuration variables
-# check if the domain is already mapped to our current IP
-myip = urllib2.urlopen('https://'+server+'/checkip').read().strip()
-currip = socket.gethostbyname(domain)
-if myip == currip:
- # nothing to do
- sys.exit(0)
+def update_domain(domain):
+ '''Update the given domain, using the global server, user, password. Returns True on success, False on failure.'''
+ # check if the domain is already mapped to our current IP
+ myip = urllib2.urlopen('https://'+server+'/checkip').read().strip()
+ domainip = socket.gethostbyname(domain)
+ if myip == domainip:
+ # nothing to do
+ return True
-# we need to update the IP
-result = urllib2.urlopen('https://'+server+'/update?user='+urllib.quote(user)+'&password='+urllib.quote(password)+'&domain='+urllib.quote(domain)+'&ip='+urllib.quote(myip)).read().strip()
-if 'good '+myip == result:
- # nothing to do, all went all right
- sys.exit(0)
+ # we need to update the IP
+ result = urllib2.urlopen('https://'+server+'/update?password='+urllib.quote(password)+'&domain='+urllib.quote(domain)+'&ip='+urllib.quote(myip)).read().strip()
+ if 'good '+myip == result:
+ # all went all right
+ return True
+ else:
+ # Something went wrong
+ print "Unexpected answer from server",server,"while updating",domain,"to",myip
+ print result
+ return False
-# there was an error :(
-print result
-sys.exit(1)
+exitcode = 0
+for domain in domains:
+ if not update_domain(domain):
+ exitcode = 1
+sys.exit(exitcode)
#include <boost/iostreams/stream.hpp>
using namespace boost;
+typedef property_tree::ptree::path_type path;
static void write(int fd, const char *str)
{
int main(int argc, const char ** argv)
{
static const regex regex_ip("\\d{1,3}.\\d{1,3}.\\d{1,3}.\\d{1,3}");
- static const regex regex_user("[a-zA-Z]+");
+ static const regex regex_password("[a-zA-Z0-9.:;,_-]+");
+ static const regex regex_domain("[a-zA-Z0-9.]+");
- if (argc != 5) {
- std::cerr << "Usage: " << argv[0] << " <username> <password> <domain> <IP address>" << std::endl;
+ if (argc != 4) {
+ std::cerr << "Usage: " << argv[0] << " <domain> <password> <IP address>" << std::endl;
return 1;
}
- /* Obtain and validate inpit */
- std::string user = argv[1];
+ /* Obtain input */
+ std::string domain = argv[1];
std::string password = argv[2];
- std::string domain = argv[3];
- std::string ip = argv[4];
+ std::string ip = argv[3];
+ /* Validate input */
if (!regex_match(ip, regex_ip)) {
std::cerr << "Invalid IP address " << ip << "." << std::endl;
exit(1);
}
- if (!regex_match(user, regex_user)) {
- std::cerr << "Invalid username " << user << "." << std::endl;
+ if (!regex_match(domain, regex_domain)) {
+ std::cerr << "Invalid domain " << domain << "." << std::endl;
+ exit(1);
+ }
+ if (!regex_match(password, regex_password)) {
+ std::cerr << "Invalid password " << password << "." << std::endl;
exit(1);
}
property_tree::ini_parser::read_ini(CONFIG_FILE, config);
std::string nsupdate = config.get<std::string>("nsupdate");
- /* Check username, password, domain */
- optional<std::string> correct_password = config.get_optional<std::string>(user+".password");
+ /* Given the domain, check whether the password matches */
+ optional<std::string> correct_password = config.get_optional<std::string>(path(domain+"/password", '/'));
if (!correct_password || *correct_password != password) {
- std::cerr << "Username or password incorrect." << std::endl;
- exit(1);
- }
- if (config.get<std::string>(user+".domain") != domain) {
- std::cerr << "Domain incorrect." << std::endl;
+ std::cerr << "Password incorrect." << std::endl;
exit(1);
}
}
if (child_pid == 0) {
/* We're in the child */
- /* Close write end, use read and as stdin */
+ /* Close write end, use read end as stdin */
close(pipe_ends[1]);
if (dup2(pipe_ends[0], fileno(stdin)) < 0) {
std::cerr << "There was an error redirecting stdin." << std::endl;
print ""
# get input
-if "user" not in form or "password" not in form or "domain" not in form or "ip" not in form:
- print "Mandatory argument missing: You must supply all of 'user', 'password', 'domain', 'ip'"
+if "password" not in form or "domain" not in form or "ip" not in form:
+ print "Mandatory argument missing: You must supply all of 'password', 'domain', 'ip'"
sys.exit()
ip = form["ip"].value
domain = form["domain"].value
-user = form["user"].value
password = form["password"].value
# run update program
-p = subprocess.Popen(["/var/lib/named/dyn-nsupdate", user, password, domain, ip], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+p = subprocess.Popen(["/var/lib/named/dyn-nsupdate", domain, password, ip], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = p.communicate()
-if stdout:
- print "Unexpected stdout from dyn-nsupdate:"
- print stdout
- sys.exit()
# check what it did
-if p.returncode == 1:
+if p.returncode or stderr or stdout:
# error :/
- print "There was an error while updating the DNS:"
- print stderr
+ print "There was an error while updating the DNS: Return code %d" % p.returncode
+ if stdout: print stdout
+ if stderr: print stderr
else:
- # all right!
- if p.returncode or stderr:
- print "Unexpected stderr from dyn-nsupdate:"
- print stderr
- sys.exit()
print "good",ip