IFACE_ATTR_DNS,
IFACE_ATTR_DNR,
IFACE_ATTR_DNS_SERVICE,
- IFACE_ATTR_DOMAIN,
+ IFACE_ATTR_DNS_DOMAIN_SEARCH,
IFACE_ATTR_DHCPV4_FORCERECONF,
IFACE_ATTR_DHCPV6_RAW,
IFACE_ATTR_DHCPV6_ASSIGNALL,
[IFACE_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY },
[IFACE_ATTR_DNR] = { .name = "dnr", .type = BLOBMSG_TYPE_ARRAY },
[IFACE_ATTR_DNS_SERVICE] = { .name = "dns_service", .type = BLOBMSG_TYPE_BOOL },
- [IFACE_ATTR_DOMAIN] = { .name = "domain", .type = BLOBMSG_TYPE_ARRAY },
+ [IFACE_ATTR_DNS_DOMAIN_SEARCH] = { .name = "domain", .type = BLOBMSG_TYPE_ARRAY },
[IFACE_ATTR_DHCPV4_FORCERECONF] = { .name = "dhcpv4_forcereconf", .type = BLOBMSG_TYPE_BOOL },
[IFACE_ATTR_DHCPV6_RAW] = { .name = "dhcpv6_raw", .type = BLOBMSG_TYPE_STRING },
[IFACE_ATTR_DHCPV6_ASSIGNALL] = { .name ="dhcpv6_assignall", .type = BLOBMSG_TYPE_BOOL },
{
free(iface->dns_addrs4);
free(iface->dns_addrs6);
- free(iface->search);
+ free(iface->dns_search);
free(iface->upstream);
free(iface->dhcpv4_router);
free(iface->dhcpv6_raw);
if ((c = tb[IFACE_ATTR_DNS_SERVICE]))
iface->dns_service = blobmsg_get_bool(c);
- if ((c = tb[IFACE_ATTR_DOMAIN])) {
+ if ((c = tb[IFACE_ATTR_DNS_DOMAIN_SEARCH])) {
struct blob_attr *cur;
unsigned rem;
blobmsg_for_each_attr(cur, c, rem) {
- uint8_t buf[256];
- char *domain = blobmsg_get_string(cur);
- size_t domainlen = strlen(domain);
+ uint8_t buf[DNS_MAX_NAME_LEN];
+ char *domain;
+ size_t domainlen;
int len;
+ uint8_t *tmp;
if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING || !blobmsg_check_attr(cur, false))
continue;
len = dn_comp(domain, buf, sizeof(buf), NULL, NULL);
if (len <= 0) {
error("Invalid %s value configured for interface '%s'",
- iface_attrs[IFACE_ATTR_DOMAIN].name, iface->name);
+ iface_attrs[IFACE_ATTR_DNS_DOMAIN_SEARCH].name, iface->name);
continue;
}
- iface->search = realloc(iface->search, iface->search_len + len);
- if (!iface->search)
+ tmp = realloc(iface->dns_search, iface->dns_search_len + len);
+ if (!tmp)
goto err;
- memcpy(&iface->search[iface->search_len], buf, len);
- iface->search_len += len;
+ iface->dns_search = tmp;
+ memcpy(&iface->dns_search[iface->dns_search_len], buf, len);
+ iface->dns_search_len += len;
}
}
.len = sizeof(reply_auth_body),
};
struct dhcpv4_option reply_srch_domain = {
- .code = DHCPV4_OPT_SEARCH_DOMAIN,
+ .code = DHCPV4_OPT_DNS_DOMAIN_SEARCH,
};
struct dhcpv4_option_u8 reply_fr_nonce_cap = {
.code = DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE,
DHCPV4_OPT_REBIND,
DHCPV4_OPT_CLIENTID, // Must be in reply if present in req, RFC6842, §3
DHCPV4_OPT_AUTHENTICATION,
- DHCPV4_OPT_SEARCH_DOMAIN,
+ DHCPV4_OPT_DNS_DOMAIN_SEARCH,
DHCPV4_OPT_CAPTIVE_PORTAL,
DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE,
};
iov[IOV_AUTH_BODY].iov_len = sizeof(reply_auth_body);
break;
- case DHCPV4_OPT_SEARCH_DOMAIN:
- if (iov[IOV_SRCH_DOMAIN].iov_len || iface->search_len > UINT8_MAX)
+ case DHCPV4_OPT_DNS_DOMAIN_SEARCH:
+ if (iov[IOV_SRCH_DOMAIN].iov_len || iface->dns_search_len > UINT8_MAX)
break;
- if (iface->search) {
- reply_srch_domain.len = iface->search_len;
+ if (iface->dns_search) {
+ reply_srch_domain.len = iface->dns_search_len;
iov[IOV_SRCH_DOMAIN].iov_len = sizeof(reply_srch_domain);
- iov[IOV_SRCH_DOMAIN_NAME].iov_base = iface->search;
- iov[IOV_SRCH_DOMAIN_NAME].iov_len = iface->search_len;
+ iov[IOV_SRCH_DOMAIN_NAME].iov_base = iface->dns_search;
+ iov[IOV_SRCH_DOMAIN_NAME].iov_len = iface->dns_search_len;
} else if (!res_init() && _res.dnsrch[0] && _res.dnsrch[0][0]) {
int len;
DHCPV4_OPT_USER_CLASS = 77,
DHCPV4_OPT_AUTHENTICATION = 90,
DHCPV4_OPT_CAPTIVE_PORTAL = 114, // RFC8910
- DHCPV4_OPT_SEARCH_DOMAIN = 119,
+ DHCPV4_OPT_DNS_DOMAIN_SEARCH = 119,
DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE = 145,
DHCPV4_OPT_DNR = 162,
DHCPV4_OPT_END = 255,
}
/* DNS Search options */
- uint8_t search_buf[256], *search_domain = iface->search;
- size_t search_len = iface->search_len;
+ uint8_t dns_search_buf[DNS_MAX_NAME_LEN];
+ uint8_t *dns_search = iface->dns_search;
+ size_t dns_search_len = iface->dns_search_len;
- if (!search_domain && !res_init() && _res.dnsrch[0] && _res.dnsrch[0][0]) {
- int len = dn_comp(_res.dnsrch[0], search_buf,
- sizeof(search_buf), NULL, NULL);
+ if (!dns_search && !res_init() && _res.dnsrch[0] && _res.dnsrch[0][0]) {
+ int len = dn_comp(_res.dnsrch[0], dns_search_buf,
+ sizeof(dns_search_buf), NULL, NULL);
if (len > 0) {
- search_domain = search_buf;
- search_len = len;
+ dns_search = dns_search_buf;
+ dns_search_len = len;
}
}
struct {
uint16_t type;
uint16_t len;
- } search = {htons(DHCPV6_OPT_DNS_DOMAIN), htons(search_len)};
+ } dns_search_hdr = { htons(DHCPV6_OPT_DNS_DOMAIN), htons(dns_search_len) };
struct _o_packed dhcpv4o6_server {
[IOV_RAPID_COMMIT] = {&rapid_commit, 0},
[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_SEARCH] = { &dns_search_hdr, (dns_search_len) ? sizeof(dns_search_hdr) : 0 },
+ [IOV_SEARCH_DOMAIN] = { dns_search, dns_search_len },
[IOV_PDBUF] = {pdbuf, 0},
[IOV_DHCPV6_RAW] = {iface->dhcpv6_raw, iface->dhcpv6_raw_len},
[IOV_NTP] = {&ntp, (ntp_cnt) ? sizeof(ntp) : 0},
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;
+ uint8_t *dns_search; // DNS domain search list to announce (concatenated)
+ size_t dns_search_len; // Length of the DNS domain search list (bytes)
// DHCPV6
void *dhcpv6_raw;
struct nd_opt_search_list {
uint8_t type;
uint8_t len;
- uint8_t pad;
- uint8_t pad2;
+ uint16_t reserved;
uint32_t lifetime;
uint8_t name[];
-};
+} _o_packed;
struct nd_opt_route_info {
uint8_t type;
/* DNS options */
if (iface->ra_dns) {
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];
+ size_t dns_addrs6_cnt = 0, dns_search_len = iface->dns_search_len;
+ uint8_t *dns_search = iface->dns_search;
+ uint8_t dns_search_buf[DNS_MAX_NAME_LEN];
/* DNS Recursive DNS aka RDNSS Type 25; RFC8106 */
if (iface->dns_addrs6_cnt > 0) {
memcpy(dns->addr, dns_addrs6, dns_addrs6_cnt * sizeof(*dns_addrs6));
}
- /* DNS Search options aka DNSSL Type 31; RFC8106 */
- if (!search_domain && !res_init() && _res.dnsrch[0] && _res.dnsrch[0][0]) {
- int len = dn_comp(_res.dnsrch[0], search_buf,
- sizeof(search_buf), NULL, NULL);
+ /* DNS Search List option aka DNSSL Type 31; RFC8106, §5.2 */
+ if (!dns_search && !res_init() && _res.dnsrch[0] && _res.dnsrch[0][0]) {
+ int len = dn_comp(_res.dnsrch[0], dns_search_buf,
+ sizeof(dns_search_buf), NULL, NULL);
if (len > 0) {
- search_domain = search_buf;
- search_len = len;
+ dns_search = dns_search_buf;
+ dns_search_len = len;
}
}
- if (search_len > 0) {
- size_t search_padded = ((search_len + 7) & (~7)) + 8;
-
- search_sz = sizeof(*search) + search_padded;
-
+ if (dns_search_len > 0) {
+ search_sz = sizeof(*search) + ((dns_search_len + 7) & (~7));
search = alloca(search_sz);
- memset(search, 0, search_sz);
- search->type = ND_OPT_DNS_SEARCH;
- search->len = search_len ? ((sizeof(*search) + search_padded) / 8) : 0;
- search->lifetime = htonl(highest_found_lifetime);
- memcpy(search->name, search_domain, search_len);
- memset(&search->name[search_len], 0, search_padded - search_len);
+ *search = (struct nd_opt_search_list) {
+ .type = ND_OPT_DNS_SEARCH,
+ .len = search_sz / 8,
+ .reserved = 0,
+ .lifetime = htonl(highest_found_lifetime),
+ };
+ memcpy(search->name, dns_search, dns_search_len);
}
}
{
char exp_dn[DNS_MAX_NAME_LEN];
- if (dn_expand(ctxt->iface->search, ctxt->iface->search + ctxt->iface->search_len,
- ctxt->iface->search, exp_dn, sizeof(exp_dn)) > 0)
+ if (dn_expand(ctxt->iface->dns_search, ctxt->iface->dns_search + ctxt->iface->dns_search_len,
+ ctxt->iface->dns_search, exp_dn, sizeof(exp_dn)) > 0)
fprintf(ctxt->fp, "%s\t%s.%s\t%s\n", ipbuf, hostname, exp_dn, hostname);
else
fprintf(ctxt->fp, "%s\t%s\n", ipbuf, hostname);