From: David Härdeman Date: Thu, 20 Nov 2025 16:17:49 +0000 (+0100) Subject: odhcpd: rename iface->search -> iface->dns_search X-Git-Url: http://git.openwrt.org/?a=commitdiff_plain;h=0a54ce0d2b578f77aac40684766cd8d1b7c104cf;p=project%2Fodhcpd.git odhcpd: rename iface->search -> iface->dns_search And fix some bugs/nits in the process, e.g.: - realloc() not handled properly in config.c - replace a number of magic values - in router.c, the DNSSL options has 8 bytes of superfluous padding Signed-off-by: David Härdeman Link: https://github.com/openwrt/odhcpd/pull/320 Signed-off-by: Álvaro Fernández Rojas --- diff --git a/src/config.c b/src/config.c index b504878..30609a6 100644 --- a/src/config.c +++ b/src/config.c @@ -107,7 +107,7 @@ enum { 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, @@ -160,7 +160,7 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = { [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 }, @@ -344,7 +344,7 @@ static void clean_interface(struct interface *iface) { 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); @@ -1373,15 +1373,16 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr 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; @@ -1395,16 +1396,17 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr 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; } } diff --git a/src/dhcpv4.c b/src/dhcpv4.c index 98d1d7d..545c814 100644 --- a/src/dhcpv4.c +++ b/src/dhcpv4.c @@ -891,7 +891,7 @@ void dhcpv4_handle_msg(void *src_addr, void *data, size_t 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, @@ -948,7 +948,7 @@ void dhcpv4_handle_msg(void *src_addr, void *data, size_t len, 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, }; @@ -1193,15 +1193,15 @@ void dhcpv4_handle_msg(void *src_addr, void *data, size_t len, 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; diff --git a/src/dhcpv4.h b/src/dhcpv4.h index 330df61..045f78b 100644 --- a/src/dhcpv4.h +++ b/src/dhcpv4.h @@ -81,7 +81,7 @@ enum dhcpv4_opt { 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, diff --git a/src/dhcpv6.c b/src/dhcpv6.c index f4c30ae..06b7f59 100644 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -615,22 +615,23 @@ static void handle_client_request(void *addr, void *data, size_t len, } /* 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 { @@ -649,8 +650,8 @@ static void handle_client_request(void *addr, void *data, size_t len, [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}, diff --git a/src/odhcpd.h b/src/odhcpd.h index 9db8662..a74c295 100644 --- a/src/odhcpd.h +++ b/src/odhcpd.h @@ -456,8 +456,8 @@ struct interface { 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; diff --git a/src/router.c b/src/router.c index 957b61d..b882e01 100644 --- a/src/router.c +++ b/src/router.c @@ -412,11 +412,10 @@ struct nd_opt_dns_server { 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; @@ -834,9 +833,9 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr /* 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) { @@ -858,28 +857,26 @@ static int send_router_advert(struct interface *iface, const struct in6_addr *fr 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); } } diff --git a/src/statefiles.c b/src/statefiles.c index a5d4e3e..8862f1b 100644 --- a/src/statefiles.c +++ b/src/statefiles.c @@ -45,8 +45,8 @@ static void statefiles_write_host(const char *ipbuf, const char *hostname, struc { 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);