Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162638732
D57925.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D57925.diff
View Options
diff --git a/lib/libc/resolv/Makefile.inc b/lib/libc/resolv/Makefile.inc
--- a/lib/libc/resolv/Makefile.inc
+++ b/lib/libc/resolv/Makefile.inc
@@ -7,4 +7,5 @@
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
--- a/lib/libc/resolv/res_init.c
+++ b/lib/libc/resolv/res_init.c
@@ -95,6 +95,7 @@
/* 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);
@@ -104,10 +105,8 @@
static void res_setoptions(res_state, const char *, const char *);
#ifdef RESOLVSORT
-static const char sort_mask[] = "/&";
-#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
-static u_int32_t net_mask(struct in_addr);
-#endif
+static int res_setsortlist(res_state, int, const char *, const char *);
+#endif /* RESOLVSORT */
#define res_space(ch) \
isspace((unsigned char)(ch))
@@ -285,8 +284,7 @@
size_t sz = 0;
int nserv = 0;
#ifdef RESOLVSORT
- int n, nsort = 0;
- char *net;
+ int nsort = 0;
#endif
if ((fp = fopen(resconf, "re")) == NULL)
@@ -357,101 +355,28 @@
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) {
- while (*cp == ' ' || *cp == '\t')
+ cp = eow;
+ while (cp < eol && res_space(*cp))
cp++;
- if (*cp == '\0' || *cp == '\n' || *cp == ';')
+ if (cp == eol)
break;
- 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;
+ eow = cp;
+ while (eow < eol && !res_space(*eow))
+ eow++;
+ if (res_setsortlist(statp, nsort, cp, eow))
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 */
@@ -631,6 +556,122 @@
return (ret);
}
+#ifdef RESOLVSORT
+/*%
+ * Parse a sortlist entry and insert it into the specified slot in the
+ * sortlist. Assumes no leading or trailing space. Returns 1 if an entry
+ * was inserted, 0 otherwise.
+ */
+static 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 (strchr(mask, '.') &&
+ inet_pton(AF_INET, mask, &a) == 1) {
+ statp->sort_list[i].mask = a.s_addr;
+ } else if (*mask != '\0') {
+ if ((num = strtol(mask, &numend, 10)) < 0 ||
+ num > 32 || *numend != '\0')
+ return (0);
+ statp->sort_list[i].mask =
+ num == 0 ? 0 :
+ htonl(0xffffffffU << (32 - num));
+ } else if (IN_CLASSA(ntohl(a.s_addr))) {
+ statp->sort_list[i].mask =
+ htonl(IN_CLASSA_NET);
+ } else if (IN_CLASSB(ntohl(a.s_addr))) {
+ statp->sort_list[i].mask =
+ htonl(IN_CLASSB_NET);
+ } else if (IN_CLASSC(ntohl(a.s_addr))) {
+ statp->sort_list[i].mask =
+ htonl(IN_CLASSC_NET);
+ } else {
+ statp->sort_list[i].mask =
+ htonl(IN_NETMASK_DEFAULT);
+ }
+ 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, &statp->sort_list[i].addr,
+ addr, sizeof(addr));
+ a.s_addr = statp->sort_list[i].mask;
+ inet_ntop(AF_INET, &a, mask, sizeof(mask));
+ printf(";; sortlist %s/%s\n", addr, mask);
+#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.
*/
@@ -775,21 +816,6 @@
}
}
-#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
--- a/share/man/man5/resolver.5
+++ b/share/man/man5/resolver.5
@@ -100,20 +100,30 @@
.Pp
The search list is currently limited to six domains
with a total of 256 characters.
-.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.,
+.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 mask
+or
+.Ar addr Ns Li / Ns Ar plen
+entries, for instance:
+.Bd -literal
+sortlist 198.51.100.0/24 203.0.113.0/255.255.255.0 2001:db8::/32
+.Ed
+.Pp
+Masks are only supported for IPv4.
+If the mask or 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.
.Pp
-.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 ...
+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
Options allows certain internal resolver variables to be modified.
The following options are supported:
.Bl -tag -width indent
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 16, 7:28 AM (2 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35129407
Default Alt Text
D57925.diff (9 KB)
Attached To
Mode
D57925: libc/resolv: Reimplement the sortlist parser
Attached
Detach File
Event Timeline
Log In to Comment