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");
54 /* Check username, password, domain */
55 optional<std::string> correct_password = config.get_optional<std::string>(user+".password");
56 if (!correct_password || *correct_password != password) {
57 std::cerr << "Username or password incorrect." << std::endl;
60 if (config.get<std::string>(user+".domain") != domain) {
61 std::cerr << "Domain incorrect." << std::endl;
65 /* preapre the pipe */
67 if (pipe(pipe_ends) < 0) {
68 std::cerr << "Error opening pipe." << std::endl;
73 pid_t child_pid = fork();
75 std::cerr << "Error while forking." << std::endl;
79 /* We're in the child */
80 /* Close write end, use read and as stdin */
82 if (dup2(pipe_ends[0], fileno(stdin)) < 0) {
83 std::cerr << "There was an error redirecting stdin." << std::endl;
87 execl(nsupdate.c_str(), nsupdate.c_str(), "-l", (char *)NULL);
88 /* There was an error */
89 std::cerr << "There was an error executing nsupdate." << std::endl;
93 /* Send it the command */
94 write(pipe_ends[1], "update delete ");
95 write(pipe_ends[1], domain.c_str());
96 write(pipe_ends[1], ". A\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;