From: Ralf Jung Date: Fri, 9 Aug 2013 20:03:13 +0000 (+0200) Subject: run nsupdate as child and send it the update commands X-Git-Url: https://git.ralfj.de/dyn-nsupdate.git/commitdiff_plain/48ce26b2492550b08316b63c42ac1afe63c8c12b run nsupdate as child and send it the update commands --- diff --git a/dyn-nsupdate.cpp b/dyn-nsupdate.cpp index cdd1dc4..4cb7ead 100644 --- a/dyn-nsupdate.cpp +++ b/dyn-nsupdate.cpp @@ -1,12 +1,25 @@ #include #include +#include #include #include #include +#include +#include using namespace boost; +static void write(int fd, const char *str) +{ + size_t len = strlen(str); + ssize_t written = write(fd, str, len); + if (written < 0 || (size_t)written != len) { + std::cerr << "Error writing pipe." << std::endl; + exit(1); + } +} + int main(int argc, const char ** argv) { static const regex regex_ip("\\d{1,3}.\\d{1,3}.\\d{1,3}.\\d{1,3}"); @@ -26,31 +39,78 @@ int main(int argc, const char ** argv) if (!regex_match(ip, regex_ip)) { std::cerr << "Invalid IP address " << ip << "." << std::endl; - return 1; + exit(1); } if (!regex_match(user, regex_user)) { std::cerr << "Invalid username " << user << "." << std::endl; - return 1; + exit(1); } /* read configuration */ property_tree::ptree config; property_tree::ini_parser::read_ini(CONFIG_FILE, config); + std::string nsupdate = config.get("nsupdate"); std::string keyfile = config.get("key"); /* Check username, password, domain */ optional correct_password = config.get_optional(user+".password"); if (!correct_password || *correct_password != password) { std::cerr << "Username or password incorrect." << std::endl; - return 1; + exit(1); } if (config.get(user+".domain") != domain) { std::cerr << "Domain incorrect." << std::endl; - return 1; + exit(1); } - std::cout << "It's all right, using key " << keyfile << std::endl; + /* preapre the pipe */ + int pipe_ends[] = {0,0}; + pipe(pipe_ends); + + /* Launch nsupdate */ + pid_t child_pid = fork(); + if (child_pid < 0) { + std::cerr << "Error while forking." << std::endl; + exit(1); + } + if (child_pid == 0) { + /* We're in the child */ + /* Close write end, use read and as stdin */ + close(pipe_ends[1]); + dup2(pipe_ends[0], fileno(stdin)); + /* exec nsupdate */ + execl(nsupdate.c_str(), nsupdate.c_str(), "-k", keyfile.c_str(), NULL); + /* There was an error */ + std::cerr << "There was an error executing nsupdate." << std::endl; + exit(1); + } + + /* Send it the command */ + write(pipe_ends[1], "server localhost\n"); + + write(pipe_ends[1], "update delete "); + write(pipe_ends[1], domain.c_str()); + write(pipe_ends[1], ".\n"); + write(pipe_ends[1], "update add "); + write(pipe_ends[1], domain.c_str()); + write(pipe_ends[1], ". 60 A "); + write(pipe_ends[1], ip.c_str()); + write(pipe_ends[1], "\n"); + + write(pipe_ends[1], "send\n"); + + /* Close both ends */ + close(pipe_ends[0]); + close(pipe_ends[1]); + + /* Wait for child to be gone */ + int child_status; + waitpid(child_pid, &child_status, 0); + if (child_status != 0) { + std::cerr << "There was an error in the child." << std::endl; + exit(1); + } return 0; }