5 #include <boost/regex.hpp>
6 #include <boost/property_tree/ptree.hpp>
7 #include <boost/property_tree/ini_parser.hpp>
8 #include <boost/iostreams/device/file_descriptor.hpp>
9 #include <boost/iostreams/stream.hpp>
11 using namespace boost;
13 static void write(int fd, const char *str)
15 size_t len = strlen(str);
16 ssize_t written = write(fd, str, len);
17 if (written < 0 || (size_t)written != len) {
18 std::cerr << "Error writing pipe." << std::endl;
23 int main(int argc, const char ** argv)
25 static const regex regex_ip("\\d{1,3}.\\d{1,3}.\\d{1,3}.\\d{1,3}");
26 static const regex regex_user("[a-zA-Z]+");
30 std::cerr << "Usage: " << argv[0] << " <username> <password> <domain> <IP address>" << std::endl;
34 /* Obtain and validate inpit */
35 std::string user = argv[1];
36 std::string password = argv[2];
37 std::string domain = argv[3];
38 std::string ip = argv[4];
40 if (!regex_match(ip, regex_ip)) {
41 std::cerr << "Invalid IP address " << ip << "." << std::endl;
44 if (!regex_match(user, regex_user)) {
45 std::cerr << "Invalid username " << user << "." << std::endl;
49 /* read configuration */
50 property_tree::ptree config;
51 property_tree::ini_parser::read_ini(CONFIG_FILE, config);
52 std::string nsupdate = config.get<std::string>("nsupdate");
53 std::string keyfile = config.get<std::string>("key");
55 /* Check username, password, domain */
56 optional<std::string> correct_password = config.get_optional<std::string>(user+".password");
57 if (!correct_password || *correct_password != password) {
58 std::cerr << "Username or password incorrect." << std::endl;
61 if (config.get<std::string>(user+".domain") != domain) {
62 std::cerr << "Domain incorrect." << std::endl;
66 /* preapre the pipe */
67 int pipe_ends[] = {0,0};
71 pid_t child_pid = fork();
73 std::cerr << "Error while forking." << std::endl;
77 /* We're in the child */
78 /* Close write end, use read and as stdin */
80 if (dup2(pipe_ends[0], fileno(stdin)) < 0) {
81 std::cerr << "There was an error redirecting stdin." << std::endl;
85 execl(nsupdate.c_str(), nsupdate.c_str(), "-k", keyfile.c_str(), (char *)NULL);
86 /* There was an error */
87 std::cerr << "There was an error executing nsupdate." << std::endl;
91 /* Send it the command */
92 write(pipe_ends[1], "server localhost\n");
94 write(pipe_ends[1], "update delete ");
95 write(pipe_ends[1], domain.c_str());
96 write(pipe_ends[1], ".\n");
98 write(pipe_ends[1], "update add ");
99 write(pipe_ends[1], domain.c_str());
100 write(pipe_ends[1], ". 60 A ");
101 write(pipe_ends[1], ip.c_str());
102 write(pipe_ends[1], "\n");
104 write(pipe_ends[1], "send\n");
106 /* Close both ends */
110 /* Wait for child to be gone */
112 waitpid(child_pid, &child_status, 0);
113 if (child_status != 0) {
114 std::cerr << "There was an error in the child." << std::endl;