git: 8538c69d84ff - main - Revert "libc/resolv: Reimplement the sortlist parser"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 29 Jun 2026 15:54:27 UTC
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 indent