diff options
author | Mikael Magnusson <mikma@users.sourceforge.net> | 2021-08-15 11:51:22 +0200 |
---|---|---|
committer | Mikael Magnusson <mikma@users.sourceforge.net> | 2021-09-21 22:37:08 +0200 |
commit | 8d777d12186bb6d5dc4c39e5ccbe50a164ea547c (patch) | |
tree | 593cee5bd1a6cb7c485bcafab343c04e51e77563 /src/dnsupdate.c | |
parent | 01b4e6046f10e21809c3f380f2d33bf3fe59698d (diff) |
WIP dnsupdatednsupdate
Diffstat (limited to 'src/dnsupdate.c')
-rw-r--r-- | src/dnsupdate.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/src/dnsupdate.c b/src/dnsupdate.c new file mode 100644 index 0000000..e8550a6 --- /dev/null +++ b/src/dnsupdate.c @@ -0,0 +1,217 @@ +#include <arpa/inet.h> +#include <fcntl.h> +#include <syslog.h> +#include <unistd.h> +#include <libubox/uloop.h> +#include "odhcpd.h" + +#define READ_END 0 +#define WRITE_END 1 + +static void update_cb(struct uloop_fd *u, unsigned int events); +static void update_proc_cb(struct uloop_process *c, int ret); +static void update_time_cb(struct uloop_timeout *t); + +static int dns_start(); +static int dns_update_init(); +static ssize_t dns_write(const char *buf, size_t count); + +static struct uloop_fd update_in = { .fd = -1, .cb = update_cb }; +static struct uloop_fd update_err = { .fd = -1, .cb = update_cb }; +static struct uloop_process update_proc = { .cb = update_proc_cb }; +static int update_pipes[3][2] = {{-1, -1}, {-1, -1}, {-1, -1}}; +static struct uloop_timeout update_time = { .cb = update_time_cb }; + +static void update_time_cb(struct uloop_timeout *t) +{ + const char CMD_QUIT[] = "quit\n"; + syslog(LOG_ERR, "update_time"); + if (update_pipes[1][WRITE_END] < 0) { + return; + } + dns_write(CMD_QUIT, sizeof(CMD_QUIT)); +} + +static void update_cb(struct uloop_fd *u, unsigned int events) +{ + syslog(LOG_ERR, "update_cb: %d %d", u->fd, events); + +// if (events & ULOOP_READ) { + char buf[512]; + int len = 0; + if ((len = read(u->fd, buf, sizeof(buf)-1)) > 0) { + buf[len] = 0; + syslog(LOG_ERR, "update_cb: read '%s'", buf); + } +// } + syslog(LOG_ERR, "update_cb: read done"); +} + + +static void update_proc_cb(struct uloop_process *c, int ret) +{ + syslog(LOG_ERR, "update_cb: process exit: %d", ret); + uloop_timeout_cancel(&update_time); + c->pid = 0; + uloop_fd_delete(&update_in); + update_in.fd = -1; + uloop_fd_delete(&update_err); + update_err.fd = -1; + close(update_pipes[0][READ_END]); + close(update_pipes[1][WRITE_END]); + close(update_pipes[2][READ_END]); + update_pipes[0][READ_END] = -1; + update_pipes[1][WRITE_END] = -1; + update_pipes[2][READ_END] = -1; +} + +static ssize_t dns_write(const char *buf, size_t count) +{ + if (update_pipes[1][WRITE_END] < 0) { + if (dns_start() < 0) + return -1; + } + + uloop_timeout_set(&update_time, 10 * 1000); + return write(update_pipes[1][WRITE_END], buf, count); +} + +int dns_update_rr(const char *hostname, int family, const void *addr) +{ + if (!config.nsupdate_domain) { + return 0; + } + + if (!hostname) { + syslog(LOG_ERR, "update_cb: no hostname"); + return 0; + } + + dns_update_init(); + + char tmp_addr[INET6_ADDRSTRLEN]; + inet_ntop(family, addr, tmp_addr, sizeof(tmp_addr)); + + char buf[512]=""; + int res = snprintf(buf, sizeof(buf), "add %s.%s. 3600 %s %s\n", hostname, config.nsupdate_domain, family==AF_INET6?"AAAA":"A", tmp_addr); + // build_nsupdate(name, 'dhcid', build_dhcid(TYPE_HWID, mac)) + // build_nsupdate(name, 'dhcid', build_dhcid(TYPE_DUID, duid)) + + syslog(LOG_ERR, "dns_update_rr: buf=%s", buf); + + if (res > 0 && res < (int)sizeof(buf)) { + res = dns_write(buf, strlen(buf)); + syslog(LOG_ERR, "dns_update_rr: write %d %zd", res, strlen(buf)); + syslog(LOG_ERR, "dns_update_rr: hostname=%s addr=%s", hostname, tmp_addr); + } + return 0; +} + +int dns_update_finish() +{ + const char CMD[] = "send\n"; + int res = dns_write(CMD, strlen(CMD)); + syslog(LOG_ERR, "dns_update_finish: write %d %zd", res, strlen(CMD)); + return res; +} + +int dns_reload() +{ + return 0; +} + +static int dns_update_init() +{ + struct { + const char *name; + const char *value; + } params[] = { + { "key", config.nsupdate_key }, + { "server", config.nsupdate_server }, + { "zone", config.nsupdate_zone }, + { NULL, NULL }, + }; + + for (int i = 0; params[i].name; i++) { + + if (!params[i].value) + continue; + + char buf[512]; + int len = snprintf(buf, sizeof(buf), "%s %s\n", + params[i].name, params[i].value); + + if (len < 0 || len > (int)sizeof(buf)) + continue; + + syslog(LOG_ERR, "dns_reload: %s=%s", params[i].name, params[i].value); + int res = dns_write(buf, len); + syslog(LOG_ERR, "dns_reload: write %d %d", res, len); + } + + return 0; +} + +int dns_init() +{ + syslog(LOG_ERR, "dns_init"); + return -1; +} + +static int dns_start() +{ + /* if (update_pipes[0] > -1) */ + /* close(update_pipes[0]); */ + + /* if (update_pipes[1] > -1) */ + /* close(update_pipes[1]); */ + + for (int i = 0; i < 3; i++) { + if (pipe2(update_pipes[i], 0) < 0) { + syslog(LOG_ERR, "dns_init: pipe2 failed"); + return -1; + } + } + + int pid = fork(); + + switch (pid) { + case 0: + /* child */ + syslog(LOG_ERR, "dns_init: child"); + dup2(update_pipes[0][WRITE_END], STDOUT_FILENO); + dup2(update_pipes[1][READ_END], STDIN_FILENO); + dup2(update_pipes[2][WRITE_END], STDERR_FILENO); + close(update_pipes[0][READ_END]); + close(update_pipes[1][WRITE_END]); + close(update_pipes[2][READ_END]); + + char *argv[2] = {"/root/knsupdate.sh", NULL}; + execv(argv[0], argv); + syslog(LOG_ERR, "dns_init: exec error?"); + return 0; + case -1: + /* error returned in parent. */ + syslog(LOG_ERR, "dns_init: failed"); + return -1; + default: + /* parent */ + break; + } + + syslog(LOG_ERR, "dns_init: parent '%d'", pid); + update_in.fd = update_pipes[0][READ_END]; + update_err.fd = update_pipes[2][READ_END]; + close(update_pipes[0][WRITE_END]); + close(update_pipes[1][READ_END]); + close(update_pipes[2][WRITE_END]); + update_pipes[0][WRITE_END] = -1; + update_pipes[1][READ_END] = -1; + update_pipes[2][WRITE_END] = -1; + uloop_fd_add(&update_in, ULOOP_READ | ULOOP_BLOCKING); + uloop_fd_add(&update_err, ULOOP_READ | ULOOP_BLOCKING); + update_proc.pid = pid; + uloop_process_add(&update_proc); + //dns_reload(); + return 0; +} |