|
@@ -288,6 +288,26 @@ struct write_ctxt {
|
|
|
int buf_idx;
|
|
|
};
|
|
|
|
|
|
+static void dhcpv6_write_ia_addrhosts(struct in6_addr *addr, int prefix, _unused uint32_t pref,
|
|
|
+ _unused uint32_t valid, void *arg)
|
|
|
+{
|
|
|
+ struct write_ctxt *ctxt = (struct write_ctxt *)arg;
|
|
|
+ char ipbuf[INET6_ADDRSTRLEN];
|
|
|
+
|
|
|
+ if ((ctxt->c->flags & OAF_DHCPV6_NA) && ctxt->c->hostname &&
|
|
|
+ !(ctxt->c->flags & OAF_BROKEN_HOSTNAME)) {
|
|
|
+ inet_ntop(AF_INET6, addr, ipbuf, sizeof(ipbuf) - 1);
|
|
|
+ fputs(ipbuf, ctxt->fp);
|
|
|
+
|
|
|
+ char b[256];
|
|
|
+ if (dn_expand(ctxt->iface->search, ctxt->iface->search + ctxt->iface->search_len,
|
|
|
+ ctxt->iface->search, b, sizeof(b)) > 0)
|
|
|
+ fprintf(ctxt->fp, "\t%s.%s", ctxt->c->hostname, b);
|
|
|
+
|
|
|
+ fprintf(ctxt->fp, "\t%s\n", ctxt->c->hostname);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static void dhcpv6_write_ia_addr(struct in6_addr *addr, int prefix, _unused uint32_t pref,
|
|
|
_unused uint32_t valid, void *arg)
|
|
|
{
|
|
@@ -314,6 +334,98 @@ static void dhcpv6_write_ia_addr(struct in6_addr *addr, int prefix, _unused uint
|
|
|
"%s/%d ", ipbuf, prefix);
|
|
|
}
|
|
|
|
|
|
+static void dhcpv6_ia_write_hostsfile(time_t now)
|
|
|
+{
|
|
|
+ struct write_ctxt ctxt;
|
|
|
+
|
|
|
+ unsigned hostsfile_strlen = strlen(config.dhcp_hostsfile) + 1;
|
|
|
+ unsigned tmp_hostsfile_strlen = hostsfile_strlen + 1; /* space for . */
|
|
|
+ char *tmp_hostsfile = alloca(tmp_hostsfile_strlen);
|
|
|
+
|
|
|
+ char *dir_hostsfile;
|
|
|
+ char *base_hostsfile;
|
|
|
+ char *pdir_hostsfile;
|
|
|
+ char *pbase_hostsfile;
|
|
|
+
|
|
|
+ int fd, ret;
|
|
|
+
|
|
|
+ dir_hostsfile = strndup(config.dhcp_hostsfile, hostsfile_strlen);
|
|
|
+ base_hostsfile = strndup(config.dhcp_hostsfile, hostsfile_strlen);
|
|
|
+
|
|
|
+ pdir_hostsfile = dirname(dir_hostsfile);
|
|
|
+ pbase_hostsfile = basename(base_hostsfile);
|
|
|
+
|
|
|
+ snprintf(tmp_hostsfile, tmp_hostsfile_strlen, "%s/.%s", pdir_hostsfile, pbase_hostsfile);
|
|
|
+
|
|
|
+ free(dir_hostsfile);
|
|
|
+ free(base_hostsfile);
|
|
|
+
|
|
|
+ fd = open(tmp_hostsfile, O_CREAT | O_WRONLY | O_CLOEXEC, 0644);
|
|
|
+ if (fd < 0)
|
|
|
+ return;
|
|
|
+
|
|
|
+ ret = lockf(fd, F_LOCK, 0);
|
|
|
+ if (ret < 0) {
|
|
|
+ close(fd);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ftruncate(fd, 0) < 0) {}
|
|
|
+
|
|
|
+ ctxt.fp = fdopen(fd, "w");
|
|
|
+ if (!ctxt.fp) {
|
|
|
+ close(fd);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ avl_for_each_element(&interfaces, ctxt.iface, avl) {
|
|
|
+ if (ctxt.iface->dhcpv6 != MODE_SERVER &&
|
|
|
+ ctxt.iface->dhcpv4 != MODE_SERVER)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (ctxt.iface->dhcpv6 == MODE_SERVER) {
|
|
|
+ list_for_each_entry(ctxt.c, &ctxt.iface->ia_assignments, head) {
|
|
|
+ if (!(ctxt.c->flags & OAF_BOUND) || ctxt.c->managed_size < 0)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (INFINITE_VALID(ctxt.c->valid_until) || ctxt.c->valid_until > now)
|
|
|
+ dhcpv6_ia_enum_addrs(ctxt.iface, ctxt.c, now,
|
|
|
+ dhcpv6_write_ia_addrhosts, &ctxt);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ctxt.iface->dhcpv4 == MODE_SERVER) {
|
|
|
+ struct dhcp_assignment *c;
|
|
|
+
|
|
|
+ list_for_each_entry(c, &ctxt.iface->dhcpv4_assignments, head) {
|
|
|
+ if (!(c->flags & OAF_BOUND))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ char ipbuf[INET6_ADDRSTRLEN];
|
|
|
+ struct in_addr addr = {.s_addr = c->addr};
|
|
|
+ inet_ntop(AF_INET, &addr, ipbuf, sizeof(ipbuf) - 1);
|
|
|
+
|
|
|
+ if (c->hostname && !(c->flags & OAF_BROKEN_HOSTNAME)) {
|
|
|
+ fputs(ipbuf, ctxt.fp);
|
|
|
+
|
|
|
+ char b[256];
|
|
|
+
|
|
|
+ if (dn_expand(ctxt.iface->search,
|
|
|
+ ctxt.iface->search + ctxt.iface->search_len,
|
|
|
+ ctxt.iface->search, b, sizeof(b)) > 0)
|
|
|
+ fprintf(ctxt.fp, "\t%s.%s", c->hostname, b);
|
|
|
+
|
|
|
+ fprintf(ctxt.fp, "\t%s\n", c->hostname);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fclose(ctxt.fp);
|
|
|
+
|
|
|
+ rename(tmp_hostsfile, config.dhcp_hostsfile);
|
|
|
+}
|
|
|
+
|
|
|
void dhcpv6_ia_write_statefile(void)
|
|
|
{
|
|
|
struct write_ctxt ctxt;
|
|
@@ -457,9 +569,13 @@ void dhcpv6_ia_write_statefile(void)
|
|
|
uint8_t newmd5[16];
|
|
|
md5_end(newmd5, &ctxt.md5);
|
|
|
|
|
|
+ rename(tmp_statefile, config.dhcp_statefile);
|
|
|
+
|
|
|
if (memcmp(newmd5, statemd5, sizeof(newmd5))) {
|
|
|
memcpy(statemd5, newmd5, sizeof(statemd5));
|
|
|
- rename(tmp_statefile, config.dhcp_statefile);
|
|
|
+
|
|
|
+ if (config.dhcp_hostsfile)
|
|
|
+ dhcpv6_ia_write_hostsfile(now);
|
|
|
|
|
|
if (config.dhcp_cb) {
|
|
|
char *argv[2] = {config.dhcp_cb, NULL};
|
|
@@ -468,8 +584,6 @@ void dhcpv6_ia_write_statefile(void)
|
|
|
_exit(128);
|
|
|
}
|
|
|
}
|
|
|
- } else {
|
|
|
- unlink(tmp_statefile);
|
|
|
}
|
|
|
}
|
|
|
}
|