static void clean_interface(struct interface *iface)
{
- free(iface->dns);
+ free(iface->dns_addrs4);
+ free(iface->dns_addrs6);
free(iface->search);
free(iface->upstream);
free(iface->dhcpv4_router);
- free(iface->dhcpv4_dns);
free(iface->dhcpv6_raw);
free(iface->dhcpv4_ntp);
free(iface->dhcpv6_ntp);
iface->always_rewrite_dns = true;
blobmsg_for_each_attr(cur, c, rem) {
- struct in_addr addr4;
- struct in6_addr addr6;
+ struct in_addr addr4, *tmp4;
+ struct in6_addr addr6, *tmp6;
if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false))
continue;
continue;
}
- iface->dhcpv4_dns = realloc(iface->dhcpv4_dns,
- (++iface->dhcpv4_dns_cnt) * sizeof(*iface->dhcpv4_dns));
- if (!iface->dhcpv4_dns)
+ tmp4 = realloc(iface->dns_addrs4, (iface->dns_addrs4_cnt + 1) *
+ sizeof(*iface->dns_addrs4));
+ if (!tmp4)
goto err;
- iface->dhcpv4_dns[iface->dhcpv4_dns_cnt - 1] = addr4;
+ iface->dns_addrs4 = tmp4;
+ iface->dns_addrs4[iface->dns_addrs4_cnt++] = addr4;
+
} else if (inet_pton(AF_INET6, blobmsg_get_string(cur), &addr6) == 1) {
if (IN6_IS_ADDR_UNSPECIFIED(&addr6)) {
error("Invalid %s value configured for interface '%s'",
continue;
}
- iface->dns = realloc(iface->dns,
- (++iface->dns_cnt) * sizeof(*iface->dns));
- if (!iface->dns)
+ tmp6 = realloc(iface->dns_addrs6, (iface->dns_addrs6_cnt + 1) *
+ sizeof(*iface->dns_addrs6));
+ if (!tmp6)
goto err;
- iface->dns[iface->dns_cnt - 1] = addr6;
- } else
+ iface->dns_addrs6 = tmp6;
+ iface->dns_addrs6[iface->dns_addrs6_cnt++] = addr6;
+
+ } else {
error("Invalid %s value configured for interface '%s'",
iface_attrs[IFACE_ATTR_DNS].name, iface->name);
+ }
}
}
IOV_ROUTER,
IOV_ROUTER_ADDR,
IOV_DNSSERVER,
- IOV_DNSSERVER_ADDR,
+ IOV_DNSSERVER_ADDRS,
IOV_HOSTNAME,
IOV_HOSTNAME_NAME,
IOV_MTU,
[IOV_ROUTER] = { &reply_router, 0 },
[IOV_ROUTER_ADDR] = { NULL, 0 },
[IOV_DNSSERVER] = { &reply_dnsserver, 0 },
- [IOV_DNSSERVER_ADDR] = { NULL, 0 },
+ [IOV_DNSSERVER_ADDRS] = { NULL, 0 },
[IOV_HOSTNAME] = { &reply_hostname, 0 },
[IOV_HOSTNAME_NAME] = { NULL, 0 },
[IOV_MTU] = { &reply_mtu, 0 },
case DHCPV4_OPT_DNSSERVER:
iov[IOV_DNSSERVER].iov_len = sizeof(reply_dnsserver);
- if (iface->dhcpv4_dns_cnt) {
- reply_dnsserver.len = iface->dhcpv4_dns_cnt * sizeof(*iface->dhcpv4_dns);
- iov[IOV_DNSSERVER_ADDR].iov_base = iface->dhcpv4_dns;
+ if (iface->dns_addrs4_cnt) {
+ reply_dnsserver.len = iface->dns_addrs4_cnt * sizeof(*iface->dns_addrs4);
+ iov[IOV_DNSSERVER_ADDRS].iov_base = iface->dns_addrs4;
} else {
reply_dnsserver.len = sizeof(iface->dhcpv4_own_ip);
- iov[IOV_DNSSERVER_ADDR].iov_base = &iface->dhcpv4_own_ip;
+ iov[IOV_DNSSERVER_ADDRS].iov_base = &iface->dhcpv4_own_ip;
}
- iov[IOV_DNSSERVER_ADDR].iov_len = reply_dnsserver.len;
+ iov[IOV_DNSSERVER_ADDRS].iov_len = reply_dnsserver.len;
break;
case DHCPV4_OPT_HOSTNAME:
} refresh = {htons(DHCPV6_OPT_INFO_REFRESH), htons(sizeof(uint32_t)),
htonl(600)};
- struct in6_addr dns_addr, *dns_addr_ptr = iface->dns;
- size_t dns_cnt = iface->dns_cnt;
-
- if ((dns_cnt == 0) &&
- !odhcpd_get_interface_dns_addr(iface, &dns_addr)) {
- dns_addr_ptr = &dns_addr;
- dns_cnt = 1;
+ struct in6_addr *dns_addrs6 = NULL, dns_addr6;
+ size_t dns_addrs6_cnt = 0;
+
+ if (iface->dns_addrs6_cnt > 0) {
+ dns_addrs6 = iface->dns_addrs6;
+ dns_addrs6_cnt = iface->dns_addrs6_cnt;
+ } else if (!odhcpd_get_interface_dns_addr6(iface, &dns_addr6)) {
+ dns_addrs6 = &dns_addr6;
+ dns_addrs6_cnt = 1;
}
struct {
uint16_t type;
uint16_t len;
- } dns = {htons(DHCPV6_OPT_DNS_SERVERS), htons(dns_cnt * sizeof(*dns_addr_ptr))};
+ } dns_hdr = { htons(DHCPV6_OPT_DNS_SERVERS), htons(dns_addrs6_cnt * sizeof(*dns_addrs6)) };
/* SNTP */
struct in6_addr *sntp_addr_ptr = iface->dhcpv6_sntp;
[IOV_CLIENTID] = {&clientid, 0},
[IOV_MAXRT] = {&maxrt, sizeof(maxrt)},
[IOV_RAPID_COMMIT] = {&rapid_commit, 0},
- [IOV_DNS] = {&dns, (dns_cnt) ? sizeof(dns) : 0},
- [IOV_DNS_ADDR] = {dns_addr_ptr, dns_cnt * sizeof(*dns_addr_ptr)},
+ [IOV_DNS] = { &dns_hdr, (dns_addrs6_cnt) ? sizeof(dns_hdr) : 0},
+ [IOV_DNS_ADDR] = { dns_addrs6, dns_addrs6_cnt * sizeof(*dns_addrs6) },
[IOV_SEARCH] = {&search, (search_len) ? sizeof(search) : 0},
[IOV_SEARCH_DOMAIN] = {search_domain, search_len},
[IOV_PDBUF] = {pdbuf, 0},
int32_t ifaceidx = 0;
struct sockaddr_in6 target = {AF_INET6, htons(DHCPV6_CLIENT_PORT),
0, IN6ADDR_ANY_INIT, 0};
- int otype, olen;
+ uint16_t otype, olen;
uint8_t *odata, *end = data + len;
/* Relay DHCPv6 reply from server to client */
struct dhcpv6_relay_header *h = (void*)data;
return;
bool is_authenticated = false;
- struct in6_addr *dns_ptr = NULL;
- size_t dns_count = 0;
+ struct in6_addr *dns_addrs6 = NULL;
+ size_t dns_addrs6_cnt = 0;
/* If the payload is relay-reply we have to send to the server port */
if (payload_data[0] == DHCPV6_MSG_RELAY_REPL) {
end = payload_data + payload_len;
dhcpv6_for_each_option(&h[1], end, otype, olen, odata) {
- if (otype == DHCPV6_OPT_DNS_SERVERS && olen >= 16) {
- dns_ptr = (struct in6_addr*)odata;
- dns_count = olen / 16;
+ if (otype == DHCPV6_OPT_DNS_SERVERS && olen >= sizeof(struct in6_addr)) {
+ dns_addrs6 = (struct in6_addr*)odata;
+ dns_addrs6_cnt = olen / sizeof(struct in6_addr);
} else if (otype == DHCPV6_OPT_AUTH) {
is_authenticated = true;
}
}
/* Rewrite DNS servers if requested */
- if (iface->always_rewrite_dns && dns_ptr && dns_count > 0) {
+ if (iface->always_rewrite_dns && dns_addrs6 && dns_addrs6_cnt > 0) {
if (is_authenticated)
return; /* Impossible to rewrite */
- const struct in6_addr *rewrite = iface->dns;
+ const struct in6_addr *rewrite = iface->dns_addrs6;
struct in6_addr addr;
- size_t rewrite_cnt = iface->dns_cnt;
+ size_t rewrite_cnt = iface->dns_addrs6_cnt;
if (rewrite_cnt == 0) {
- if (odhcpd_get_interface_dns_addr(iface, &addr))
+ if (odhcpd_get_interface_dns_addr6(iface, &addr))
return; /* Unable to get interface address */
rewrite = &addr;
}
/* Copy over any other addresses */
- for (size_t i = 0; i < dns_count; ++i) {
+ for (size_t i = 0; i < dns_addrs6_cnt; ++i) {
size_t j = (i < rewrite_cnt) ? i : rewrite_cnt - 1;
- memcpy(&dns_ptr[i], &rewrite[j], sizeof(*rewrite));
+ memcpy(&dns_addrs6[i], &rewrite[j], sizeof(*rewrite));
}
}
* - use an IPv6 ULA address if the already selected IPv6 address is not an ULA address
* - use the IPv6 address with the longest preferred lifetime
*/
-int odhcpd_get_interface_dns_addr(struct interface *iface, struct in6_addr *addr)
+int odhcpd_get_interface_dns_addr6(struct interface *iface, struct in6_addr *dns_addr6)
{
time_t now = odhcpd_time();
ssize_t m = -1;
}
if (m >= 0) {
- *addr = iface->addr6[m].addr.in6;
+ *dns_addr6 = iface->addr6[m].addr.in6;
return 0;
}
- return odhcpd_get_interface_linklocal_addr(iface, addr);
+ return odhcpd_get_interface_linklocal_addr(iface, dns_addr6);
}
struct interface* odhcpd_get_interface_by_index(int ifindex)
struct odhcpd_ipaddr dhcpv4_own_ip;
struct in_addr *dhcpv4_router;
size_t dhcpv4_router_cnt;
- struct in_addr *dhcpv4_dns;
- size_t dhcpv4_dns_cnt;
bool dhcpv4_forcereconf;
// DNS
- struct in6_addr *dns;
- size_t dns_cnt;
+ struct in_addr *dns_addrs4; // IPv4 DNS server addresses to announce
+ size_t dns_addrs4_cnt; // Count of IPv4 DNS addresses
+ struct in6_addr *dns_addrs6; // IPv6 DNS server addresses to announce
+ size_t dns_addrs6_cnt; // Count of IPv6 DNS addresses
uint8_t *search;
size_t search_len;
ssize_t odhcpd_try_send_with_src(int socket, struct sockaddr_in6 *dest,
struct iovec *iov, size_t iov_len,
struct interface *iface);
-int odhcpd_get_interface_dns_addr(struct interface *iface,
- struct in6_addr *addr);
+int odhcpd_get_interface_dns_addr6(struct interface *iface,
+ struct in6_addr *dns_addr6);
int odhcpd_get_interface_linklocal_addr(struct interface *iface,
struct in6_addr *addr);
int odhcpd_get_interface_config(const char *ifname, const char *what);
/* DNS options */
if (iface->ra_dns) {
- struct in6_addr dns_pref, *dns_addr = NULL;
- size_t dns_cnt = 0, search_len = iface->search_len;
+ struct in6_addr *dns_addrs6 = NULL, dns_addr6;
+ size_t dns_addrs6_cnt = 0, search_len = iface->search_len;
uint8_t *search_domain = iface->search;
uint8_t search_buf[256];
/* DNS Recursive DNS aka RDNSS Type 25; RFC8106 */
- if (iface->dns_cnt > 0) {
- dns_addr = iface->dns;
- dns_cnt = iface->dns_cnt;
- } else if (!odhcpd_get_interface_dns_addr(iface, &dns_pref)) {
- dns_addr = &dns_pref;
- dns_cnt = 1;
+ if (iface->dns_addrs6_cnt > 0) {
+ dns_addrs6 = iface->dns_addrs6;
+ dns_addrs6_cnt = iface->dns_addrs6_cnt;
+ } else if (!odhcpd_get_interface_dns_addr6(iface, &dns_addr6)) {
+ dns_addrs6 = &dns_addr6;
+ dns_addrs6_cnt = 1;
}
- if (dns_cnt) {
- dns_sz = sizeof(*dns) + sizeof(struct in6_addr)*dns_cnt;
+ if (dns_addrs6_cnt) {
+ dns_sz = sizeof(*dns) + dns_addrs6_cnt * sizeof(*dns_addrs6);
dns = alloca(dns_sz);
memset(dns, 0, dns_sz);
dns->type = ND_OPT_RECURSIVE_DNS;
- dns->len = 1 + (2 * dns_cnt);
+ dns->len = 1 + (2 * dns_addrs6_cnt);
dns->lifetime = htonl(highest_found_lifetime);
- memcpy(dns->addr, dns_addr, sizeof(struct in6_addr)*dns_cnt);
+ memcpy(dns->addr, dns_addrs6, dns_addrs6_cnt * sizeof(*dns_addrs6));
}
/* DNS Search options aka DNSSL Type 31; RFC8106 */
/* Rewrite options */
uint8_t *end = data + len;
uint8_t *mac_ptr = NULL;
- struct in6_addr *dns_ptr = NULL;
- size_t dns_count = 0;
+ struct in6_addr *dns_addrs6 = NULL;
+ size_t dns_addrs6_cnt = 0;
// MTU option
struct nd_opt_mtu *mtu_opt = NULL;
uint32_t ingress_mtu_val = 0;
case ND_OPT_RECURSIVE_DNS:
if (opt->len > 1) {
- dns_ptr = (struct in6_addr *)&opt->data[6];
- dns_count = (opt->len - 1) / 2;
+ dns_addrs6 = (struct in6_addr *)&opt->data[6];
+ dns_addrs6_cnt = (opt->len - 1) / 2;
}
break;
}
/* If we have to rewrite DNS entries */
- if (c->always_rewrite_dns && dns_ptr && dns_count > 0) {
- const struct in6_addr *rewrite = c->dns;
+ if (c->always_rewrite_dns && dns_addrs6 && dns_addrs6_cnt > 0) {
+ const struct in6_addr *rewrite = c->dns_addrs6;
struct in6_addr addr;
- size_t rewrite_cnt = c->dns_cnt;
+ size_t rewrite_cnt = c->dns_addrs6_cnt;
if (rewrite_cnt == 0) {
- if (odhcpd_get_interface_dns_addr(c, &addr))
+ if (odhcpd_get_interface_dns_addr6(c, &addr))
continue; /* Unable to comply */
rewrite = &addr;
}
/* Copy over any other addresses */
- for (size_t i = 0; i < dns_count; ++i) {
+ for (size_t i = 0; i < dns_addrs6_cnt; ++i) {
size_t j = (i < rewrite_cnt) ? i : rewrite_cnt - 1;
- dns_ptr[i] = rewrite[j];
+ dns_addrs6[i] = rewrite[j];
}
}