Date: Mon, 29 Jun 2026 15:54:27 +0000 From: Dag-Erling=?utf-8?Q? Sm=C3=B8rg?=rav <des@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 8538c69d84ff - main - Revert "libc/resolv: Reimplement the sortlist parser" Message-ID: <6a429533.3bb64.76d507e9@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=8538c69d84ff2ee4462d09ac21a69e8c907116f1 commit 8538c69d84ff2ee4462d09ac21a69e8c907116f1 Author: Dag-Erling Smørgrav <des@FreeBSD.org> AuthorDate: 2026-06-29 15:53:59 +0000 Commit: Dag-Erling Smørgrav <des@FreeBSD.org> CommitDate: 2026-06-29 15:53:59 +0000 Revert "libc/resolv: Reimplement the sortlist parser" This reverts commit 507ab02d751b4aaa7f35f30882299e9908448e53. --- lib/libc/resolv/Makefile.inc | 1 - lib/libc/resolv/res_init.c | 232 ++++++++++++++++++++----------------------- share/man/man5/resolver.5 | 33 +++--- 3 files changed, 123 insertions(+), 143 deletions(-) diff --git a/lib/libc/resolv/Makefile.inc b/lib/libc/resolv/Makefile.inc index ecb0c2462b08..be900e942435 100644 --- a/lib/libc/resolv/Makefile.inc +++ b/lib/libc/resolv/Makefile.inc @@ -7,5 +7,4 @@ SRCS+= herror.c h_errno.c mtctxres.c res_comp.c res_data.c res_debug.c \ SYM_MAPS+= ${LIBC_SRCTOP}/resolv/Symbol.map -CFLAGS+=-I${LIBC_SRCTOP}/net CFLAGS+=-I${SRCTOP}/lib/libmd diff --git a/lib/libc/resolv/res_init.c b/lib/libc/resolv/res_init.c index a0cd381d0f0f..c61b247b5199 100644 --- a/lib/libc/resolv/res_init.c +++ b/lib/libc/resolv/res_init.c @@ -95,7 +95,6 @@ /* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */ #include <resolv.h> -#include "res_config.h" #include "res_private.h" static void res_readconf(res_state, const char *, int); @@ -105,8 +104,10 @@ static int res_setnsaddr(res_state, int, const char *, const char *); static void res_setoptions(res_state, const char *, const char *); #ifdef RESOLVSORT -static int res_setsortlist(res_state, int, const char *, const char *); -#endif /* RESOLVSORT */ +static const char sort_mask[] = "/&"; +#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL) +static u_int32_t net_mask(struct in_addr); +#endif #define res_space(ch) \ isspace((unsigned char)(ch)) @@ -284,7 +285,8 @@ res_readconf(res_state statp, const char *resconf, int maxns) size_t sz = 0; int nserv = 0; #ifdef RESOLVSORT - int nsort = 0; + int n, nsort = 0; + char *net; #endif if ((fp = fopen(resconf, "re")) == NULL) @@ -355,28 +357,101 @@ res_readconf(res_state statp, const char *resconf, int maxns) continue; } #ifdef RESOLVSORT - /* read result sort order */ if (res_match(line, eow, "sortlist")) { + struct in_addr a; + struct in6_addr a6; + int m, i; + u_char *u; + struct __res_state_ext *ext = statp->_u._ext.ext; + + cp = line + sizeof("sortlist") - 1; while (nsort < MAXRESOLVSORT) { - cp = eow; - while (cp < eol && res_space(*cp)) + while (*cp == ' ' || *cp == '\t') cp++; - if (cp == eol) + if (*cp == '\0' || *cp == '\n' || *cp == ';') break; - eow = cp; - while (eow < eol && !res_space(*eow)) - eow++; - if (res_setsortlist(statp, nsort, cp, eow)) + net = cp; + while (*cp && !ISSORTMASK(*cp) && *cp != ';' && + isascii(*cp) && !isspace((unsigned char)*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + statp->sort_list[nsort].addr = a; + if (ISSORTMASK(n)) { + *cp++ = n; + net = cp; + while (*cp && *cp != ';' && + isascii(*cp) && + !isspace((unsigned char)*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + statp->sort_list[nsort].mask = a.s_addr; + } else { + statp->sort_list[nsort].mask = + net_mask(statp->sort_list[nsort].addr); + } + } else { + statp->sort_list[nsort].mask = + net_mask(statp->sort_list[nsort].addr); + } + ext->sort_list[nsort].af = AF_INET; + ext->sort_list[nsort].addr.ina = + statp->sort_list[nsort].addr; + ext->sort_list[nsort].mask.ina.s_addr = + statp->sort_list[nsort].mask; nsort++; + } + else if (inet_pton(AF_INET6, net, &a6) == 1) { + + ext->sort_list[nsort].af = AF_INET6; + ext->sort_list[nsort].addr.in6a = a6; + u = (u_char *)&ext->sort_list[nsort].mask.in6a; + *cp++ = n; + net = cp; + while (*cp && *cp != ';' && + isascii(*cp) && !isspace(*cp)) + cp++; + m = n; + n = *cp; + *cp = 0; + switch (m) { + case '/': + m = atoi(net); + break; + case '&': + if (inet_pton(AF_INET6, net, u) == 1) { + m = -1; + break; + } + /*FALLTHROUGH*/ + default: + m = sizeof(struct in6_addr) * CHAR_BIT; + break; + } + if (m >= 0) { + for (i = 0; i < sizeof(struct in6_addr); i++) { + if (m <= 0) { + *u = 0; + } else { + m -= CHAR_BIT; + *u = (u_char)~0; + if (m < 0) + *u <<= -m; + } + u++; + } + } + statp->sort_list[nsort].addr.s_addr = + (u_int32_t)0xffffffff; + statp->sort_list[nsort].mask = + (u_int32_t)0xffffffff; + nsort++; + } + *cp = n; } -#ifdef DEBUG - while (cp < eol && res_space(*cp)) - cp++; - if (cp < eol) { - printf(";; sortlist overflow: %.*s\n", - (int)(eol - cp), cp); - } -#endif continue; } #endif /* RESOLVSORT */ @@ -576,108 +651,6 @@ res_setnsaddr(res_state statp, int i, const char *str, const char *end) return (ret); } -#ifdef RESOLVSORT -/*% - * Set the sort order. Assumes no leading or trailing space. - */ -int -res_setsortlist(res_state statp, int i, const char *str, const char *end) -{ - struct __res_state_ext *ext = statp->_u._ext.ext; - char addr[48], mask[48], *dst, *numend; - _Static_assert(sizeof(addr) > INET6_ADDRSTRLEN, - "address buffer too small for AF_INET6"); - _Static_assert(sizeof(addr) > INET_ADDRSTRLEN, - "address buffer too small for AF_INET"); - _Static_assert(sizeof(mask) > INET6_ADDRSTRLEN, - "mask buffer too small for AF_INET6"); - _Static_assert(sizeof(mask) > INET_ADDRSTRLEN, - "mask buffer too small for AF_INET"); - struct in_addr a; - struct in6_addr a6; - uint8_t *u; - long num; - - /* copy the address */ - dst = addr; - while (str < end && !res_space(*str) && *str != '/') { - *dst++ = *str++; - if (dst == addr + sizeof(addr)) - return (0); - } - *dst = '\0'; - - /* copy the mask, if there is one */ - dst = mask; - if (str < end) { - if (*str++ != '/') - return (0); - if (end - str >= sizeof(mask)) - return (0); - memcpy(mask, str, end - str); - dst += end - str; - } - *dst = '\0'; - - /* IPv4 case */ - if (inet_pton(AF_INET, addr, &a) == 1) { - statp->sort_list[i].addr = a; - if (mask[0] != '\0') { - if ((num = strtol(mask, &numend, 10)) < 0 || - num > 32 || *numend != '\0') - return (0); - } else { - if (IN_CLASSA(ntohl(a.s_addr))) - num = 8; - else if (IN_CLASSB(ntohl(a.s_addr))) - num = 16; - else - num = 24; - } - statp->sort_list[i].mask = - htonl(0xffffffffU << (32 - num)); - ext->sort_list[i].af = AF_INET; - ext->sort_list[i].addr.ina = - statp->sort_list[i].addr; - ext->sort_list[i].mask.ina.s_addr = - statp->sort_list[i].mask; -#ifdef DEBUG - inet_ntop(AF_INET, &a, addr, sizeof(addr)); - printf(";; sortlist %s/%ld\n", addr, num); -#endif - return (1); - } - - /* IPv6 case */ - if (inet_pton(AF_INET6, addr, &a6) == 1) { - statp->sort_list[i].addr.s_addr = INADDR_NONE; - statp->sort_list[i].mask = INADDR_NONE; - ext->sort_list[i].af = AF_INET6; - ext->sort_list[i].addr.in6a = a6; - if (mask[0]) { - /* prefix length */ - if ((num = strtol(mask, &numend, 10)) < 0 || - num > 128 || *numend != '\0') - return (0); - } else { - num = 64; - } -#ifdef DEBUG - inet_ntop(AF_INET6, &a6, addr, sizeof(addr)); - printf(";; sortlist %s/%ld\n", addr, num); -#endif - a6 = (struct in6_addr)IN6ADDR_ANY_INIT; - for (u = a6.s6_addr8; num > 0; num -= 8) - *u++ = num > 8 ? 0xffU : 0xffU << (8 - num); - ext->sort_list[i].mask.in6a = a6; - return (1); - } - - /* invalid */ - return (0); -} -#endif /* RESOLVSORT */ - /*% * Split the string up into words and interpret them as resolver options. */ @@ -817,6 +790,21 @@ res_setoptions(res_state statp, const char *options, const char *source) } } +#ifdef RESOLVSORT +/* XXX - should really support CIDR which means explicit masks always. */ +static u_int32_t +net_mask(struct in_addr in) /*!< XXX - should really use system's version of this */ +{ + u_int32_t i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (htonl(IN_CLASSA_NET)); + else if (IN_CLASSB(i)) + return (htonl(IN_CLASSB_NET)); + return (htonl(IN_CLASSC_NET)); +} +#endif + void freebsd15_res_rndinit(res_state statp) { diff --git a/share/man/man5/resolver.5 b/share/man/man5/resolver.5 index 135e56287b5f..8af69fd2dac7 100644 --- a/share/man/man5/resolver.5 +++ b/share/man/man5/resolver.5 @@ -100,27 +100,20 @@ for one of the domains. .Pp The search list is currently limited to six domains with a total of 256 characters. -.It Cm sortlist Ar addr1 Ns Oo Li / Ns Ar plen1 Oc Op addr2 Ns Oo Li / Ns Ar plen2 Oc ... -Sort order for query results in the form of a list of -.Ar addr Ns Li / Ns Ar plen -entries, for instance: -.Bd -literal -sortlist 198.51.100.0/24 203.0.113.0/24 2001:db8::/32 -.Ed -.Pp -If the prefix length is omitted, it defaults to historical class-based -addressing for IPv4 and to 64 for IPv6. -.Pp -Query results that match one of the sort list entries are sorted -accordingly and ahead of query results that don't. -If multiple results match a single sort list entry, the order is -unspecified. +.It Sy sortlist +Sortlist allows addresses returned by the resolver to be sorted. +A sortlist is specified by IP address netmask pairs. +If the netmask is not specified, +it defaults to the historical Class A/B/C netmask of the net; +this usage is deprecated. +The IP address +and network pairs are separated by slashes. +Up to 10 pairs may +be specified. +E.g., .Pp -If multiple -.Cm sortlist -lines are encountered, entries are appended to the list in the order -in which they were encountered, up to a maximum of ten. -.It Cm options +.Dl "sortlist 10.9.1.0/255.255.240.0 10.9.0.0/255.255.0.0" +.It Cm options Ar option1 Op Ar option2 ... Options allows certain internal resolver variables to be modified. The following options are supported: .Bl -tag -width indenthome | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a429533.3bb64.76d507e9>
