Page MenuHomeFreeBSD

D57924.diff
No OneTemporary

D57924.diff

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
@@ -97,6 +97,10 @@
#include "res_private.h"
+static void res_readconf(res_state, const char *, int);
+static void res_setdefdname(res_state, const char *, const char *);
+static void res_setdnsrch(res_state, const char *, const char *);
+static int res_setnsaddr(res_state, int, const char *, const char *);
static void res_setoptions(res_state, const char *, const char *);
#ifdef RESOLVSORT
@@ -107,6 +111,8 @@
#define res_space(ch) \
isspace((unsigned char)(ch))
+#define res_comment(ch) \
+ ((ch) == '#' || (ch) == ';')
#define res_match(str, end, word) \
(strncmp((str), (word), (end) - (str)) == 0 && \
(word)[(end) - (str)] == '\0')
@@ -136,7 +142,9 @@
/*% This function has to be reachable by res_data.c but not publicly. */
int
-__res_vinit(res_state statp, int preinit) {
+__res_vinit(res_state statp, int preinit)
+{
+ char buf[NI_MAXHOST];
union res_sockaddr_union u[] = {
{ .sin = {
.sin_family = AF_INET,
@@ -157,17 +165,7 @@
} },
#endif
};
- FILE *fp;
char *cp, **pp;
- int n;
- char buf[BUFSIZ];
- int nserv = 0; /*%< number of nameserver records read from file */
- int haveenv = 0;
- int havesearch = 0;
-#ifdef RESOLVSORT
- int nsort = 0;
- char *net;
-#endif
int dots;
int maxns = MAXNS;
@@ -219,263 +217,14 @@
#endif
res_setservers(statp, u, nitems(u));
+ /* read the configuration file */
+ res_readconf(statp, _PATH_RESCONF, maxns);
+
/* Allow user to override the local domain definition */
if ((cp = secure_getenv("LOCALDOMAIN")) != NULL) {
- (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
- statp->defdname[sizeof(statp->defdname) - 1] = '\0';
- haveenv++;
-
- /*
- * Set search list to be blank-separated strings
- * from rest of env value. Permits users of LOCALDOMAIN
- * to still have a search list, and anyone to set the
- * one that they want to use as an individual (even more
- * important now that the rfc1535 stuff restricts searches)
- */
- cp = statp->defdname;
- pp = statp->dnsrch;
- *pp++ = cp;
- for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
- if (*cp == '\n') /*%< silly backwards compat */
- break;
- else if (*cp == ' ' || *cp == '\t') {
- *cp = 0;
- n = 1;
- } else if (n) {
- *pp++ = cp;
- n = 0;
- havesearch = 1;
- }
- }
- /* null terminate last domain if there are excess */
- while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
- cp++;
- *cp = '\0';
- *pp++ = NULL;
- }
-
-#define MATCH(line, name) \
- (!strncmp(line, name, sizeof(name) - 1) && \
- (line[sizeof(name) - 1] == ' ' || \
- line[sizeof(name) - 1] == '\t'))
-
- if ((fp = fopen(_PATH_RESCONF, "re")) != NULL) {
- struct stat sb;
- struct timespec now;
-
- if (statp->_u._ext.ext != NULL) {
- if (_fstat(fileno(fp), &sb) == 0) {
- statp->_u._ext.ext->conf_mtim = sb.st_mtim;
- if (clock_gettime(CLOCK_MONOTONIC_FAST, &now) == 0) {
- statp->_u._ext.ext->conf_stat = now.tv_sec;
- }
- }
- }
-
- /* read the config file */
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- /* skip comments */
- if (*buf == ';' || *buf == '#')
- continue;
- /* read default domain name */
- if (MATCH(buf, "domain")) {
- if (haveenv) /*%< skip if have from environ */
- continue;
- cp = buf + sizeof("domain") - 1;
- while (*cp == ' ' || *cp == '\t')
- cp++;
- if ((*cp == '\0') || (*cp == '\n'))
- continue;
- strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
- statp->defdname[sizeof(statp->defdname) - 1] = '\0';
- if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
- *cp = '\0';
- havesearch = 0;
- continue;
- }
- /* set search list */
- if (MATCH(buf, "search")) {
- if (haveenv) /*%< skip if have from environ */
- continue;
- cp = buf + sizeof("search") - 1;
- while (*cp == ' ' || *cp == '\t')
- cp++;
- if ((*cp == '\0') || (*cp == '\n'))
- continue;
- strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
- statp->defdname[sizeof(statp->defdname) - 1] = '\0';
- if ((cp = strchr(statp->defdname, '\n')) != NULL)
- *cp = '\0';
- /*
- * Set search list to be blank-separated strings
- * on rest of line.
- */
- cp = statp->defdname;
- pp = statp->dnsrch;
- *pp++ = cp;
- for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
- if (*cp == ' ' || *cp == '\t') {
- *cp = 0;
- n = 1;
- } else if (n) {
- *pp++ = cp;
- n = 0;
- }
- }
- /* null terminate last domain if there are excess */
- while (*cp != '\0' && *cp != ' ' && *cp != '\t')
- cp++;
- *cp = '\0';
- *pp++ = NULL;
- havesearch = 1;
- continue;
- }
- /* read nameservers to query */
- if (MATCH(buf, "nameserver") && nserv < maxns) {
- struct addrinfo hints, *ai;
- char sbuf[NI_MAXSERV];
- const size_t minsiz =
- sizeof(statp->_u._ext.ext->nsaddrs[0]);
-
- cp = buf + sizeof("nameserver") - 1;
- while (*cp == ' ' || *cp == '\t')
+ while (res_space(*cp))
cp++;
- cp[strcspn(cp, ";# \t\n")] = '\0';
- if ((*cp != '\0') && (*cp != '\n')) {
- memset(&hints, 0, sizeof(hints));
- hints.ai_family = PF_UNSPEC;
- hints.ai_socktype = SOCK_DGRAM; /*dummy*/
- hints.ai_flags = AI_NUMERICHOST;
- sprintf(sbuf, "%u", NAMESERVER_PORT);
- if (getaddrinfo(cp, sbuf, &hints, &ai) == 0) {
- if (ai->ai_addrlen <= minsiz) {
- if (statp->_u._ext.ext != NULL) {
- memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
- ai->ai_addr, ai->ai_addrlen);
- }
- if (ai->ai_addrlen <=
- sizeof(statp->nsaddr_list[nserv])) {
- memcpy(&statp->nsaddr_list[nserv],
- ai->ai_addr, ai->ai_addrlen);
- } else
- statp->nsaddr_list[nserv].sin_family = 0;
- nserv++;
- }
- freeaddrinfo(ai);
- }
- }
- continue;
- }
-#ifdef RESOLVSORT
- if (MATCH(buf, "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 = buf + sizeof("sortlist") - 1;
- while (nsort < MAXRESOLVSORT) {
- while (*cp == ' ' || *cp == '\t')
- cp++;
- if (*cp == '\0' || *cp == '\n' || *cp == ';')
- 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;
- nsort++;
- }
- *cp = n;
- }
- continue;
- }
-#endif
- if (MATCH(buf, "options")) {
- res_setoptions(statp, buf + sizeof("options") - 1, "conf");
- continue;
- }
- }
- if (nserv > 0)
- statp->nscount = nserv;
-#ifdef RESOLVSORT
- statp->nsort = nsort;
-#endif
- (void) fclose(fp);
+ res_setdnsrch(statp, cp, NULL);
}
/* guess default domain if not set */
@@ -485,7 +234,7 @@
strcpy(statp->defdname, cp + 1);
/* find components of local domain that might be searched */
- if (havesearch == 0) {
+ if (statp->dnsrch[0] == NULL) {
pp = statp->dnsrch;
*pp++ = statp->defdname;
*pp = NULL;
@@ -521,6 +270,390 @@
return (statp->res_h_errno);
}
+/*%
+ * Read the resolver configuration file.
+ */
+static void
+res_readconf(res_state statp, const char *resconf, int maxns)
+{
+ struct stat sb;
+ struct timespec now;
+ FILE *fp;
+ char *line = NULL, *eol, *eow;
+ char *cp;
+ ssize_t len;
+ size_t sz = 0;
+ int nserv = 0;
+#ifdef RESOLVSORT
+ int n, nsort = 0;
+ char *net;
+#endif
+
+ if ((fp = fopen(resconf, "re")) == NULL)
+ return;
+ if (statp->_u._ext.ext != NULL) {
+ if (_fstat(fileno(fp), &sb) == 0) {
+ statp->_u._ext.ext->conf_mtim = sb.st_mtim;
+ if (clock_gettime(CLOCK_MONOTONIC_FAST, &now) == 0) {
+ statp->_u._ext.ext->conf_stat = now.tv_sec;
+ }
+ }
+ }
+
+ while ((len = getline(&line, &sz, fp)) != -1) {
+ /* search for comment or end of line */
+ eol = line;
+ while (eol < line + len && !res_comment(*eol))
+ eol++;
+
+ /* now backtrack over whitespace */
+ while (eol > line && res_space(eol[-1]))
+ eol--;
+ *eol = '\0';
+
+ /* skip blank line */
+ if (eol == line)
+ continue;
+
+ /* isolate the first word */
+ eow = line;
+ while (eow < eol && !res_space(*eow))
+ eow++;
+
+ /* read default domain name */
+ if (res_match(line, eow, "domain")) {
+ cp = eow;
+ while (cp < eol && res_space(*cp))
+ cp++;
+ res_setdefdname(statp, cp, eol);
+ continue;
+ }
+
+ /* set search list */
+ if (res_match(line, eow, "search")) {
+ cp = eow;
+ while (cp < eol && res_space(*cp))
+ cp++;
+ res_setdnsrch(statp, cp, eol);
+ continue;
+ }
+
+ /* read nameservers to query */
+ if (res_match(line, eow, "nameserver")) {
+ cp = eow;
+ while (cp < eol && res_space(*cp))
+ cp++;
+ if (cp == eol)
+ continue;
+ if (nserv < maxns) {
+ if (res_setnsaddr(statp, nserv, cp, eol))
+ nserv++;
+#ifdef DEBUG
+ } else {
+ printf(";; nameserver overflow: %.*s\n",
+ (int)(eol - cp), cp);
+#endif
+ }
+ continue;
+ }
+#ifdef RESOLVSORT
+ 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++;
+ if (*cp == '\0' || *cp == '\n' || *cp == ';')
+ 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;
+ nsort++;
+ }
+ *cp = n;
+ }
+ continue;
+ }
+#endif /* RESOLVSORT */
+ /* read resolver options */
+ if (res_match(line, eow, "options")) {
+ cp = eow;
+ while (res_space(*cp))
+ cp++;
+ res_setoptions(statp, cp, "conf");
+ continue;
+ }
+ }
+ free(line);
+ if (nserv > 0)
+ statp->nscount = nserv;
+#ifdef RESOLVSORT
+ statp->nsort = nsort;
+#endif
+ (void)fclose(fp);
+}
+
+/*%
+ * Set the default domain to the first word of the string. Assumes no
+ * leading space.
+ */
+static void
+res_setdefdname(res_state statp, const char *str, const char *end)
+{
+ const char *sp;
+
+ /* find end of string */
+ if (end == NULL) {
+ end = str;
+ while (*end != '\0')
+ end++;
+ }
+
+ /* find the first space */
+ sp = str;
+ while (sp < end && !res_space(*sp))
+ sp++;
+
+ /* check length of first word */
+ if (sp == str || sp - str >= sizeof(statp->defdname)) {
+ statp->defdname[0] = '\0';
+ statp->dnsrch[0] = NULL;
+ return;
+ }
+
+ /* copy the first word into defdname */
+ memcpy(statp->defdname, str, sp - str);
+ statp->defdname[sp - str] = '\0';
+ statp->dnsrch[0] = NULL;
+#ifdef DEBUG
+ printf(";; domain %s\n", statp->defdname);
+#endif
+}
+
+/*%
+ * Set the default domain to the first word of the string and split the
+ * string up into the search path. Assumes no leading space.
+ */
+static void
+res_setdnsrch(res_state statp, const char *str, const char *end)
+{
+ char *sp, *wp, *np;
+ int n;
+
+ /* find end of string */
+ if (end == NULL) {
+ end = str;
+ while (*end != '\0')
+ end++;
+ }
+
+ /* trim trailing space */
+ while (end > str && res_space(end[-1]))
+ end--;
+
+ /* check length of string */
+ if (end == str || end - str >= sizeof(statp->defdname)) {
+ statp->defdname[0] = '\0';
+ statp->dnsrch[0] = NULL;
+ return;
+ }
+
+ /* copy entire string into defdname */
+ memcpy(statp->defdname, str, end - str);
+ statp->defdname[end - str] = '\0';
+
+ /* split string into words */
+ for (wp = statp->defdname, n = 0;
+ *wp != '\0' && n < MAXDNSRCH;
+ wp = np) {
+ /* find the end of the word */
+ sp = wp;
+ while (*sp != '\0' && !res_space(*sp))
+ sp++;
+
+ /* find the start of the next word */
+ np = sp;
+ while (*np != '\0' && res_space(*np))
+ np++;
+
+ /* assign to the next slot */
+ if (sp > wp) {
+ statp->dnsrch[n] = wp;
+ *sp = '\0';
+#ifdef DEBUG
+ if (n == 0)
+ printf(";; domain %s\n;; search", statp->defdname);
+ printf(" %s", statp->dnsrch[n]);
+#endif
+ n++;
+ }
+ }
+#ifdef DEBUG
+ printf("\n");
+#endif
+
+ /* terminate the list */
+ statp->dnsrch[n] = NULL;
+}
+
+/*%
+ * Resolve the string and insert the result in the specified slot in the
+ * name server list. Assumes no leading or trailing space.
+ */
+static int
+res_setnsaddr(res_state statp, int i, const char *str, const char *end)
+{
+ char addr[48], port[8];
+ _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");
+ struct addrinfo hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_DGRAM,
+ .ai_flags = AI_NUMERICHOST,
+ };
+ struct addrinfo *ai;
+ int ret = 0;
+
+ /* find end of string */
+ if (end == NULL) {
+ end = str;
+ while (*end != '\0')
+ end++;
+ }
+
+ /* prepare port number */
+ snprintf(port, sizeof(port), "%u", NAMESERVER_PORT);
+
+ /* check length */
+ if (end - str >= sizeof(addr)) {
+#ifdef DEBUG
+ printf(";; nameserver too long: %.*s\n",
+ (int)(end - str), str);
+#endif
+ return (0);
+ }
+
+ /* resolve the address */
+ memcpy(addr, str, end - str);
+ addr[end - str] = '\0';
+ if (getaddrinfo(addr, port, &hints, &ai) != 0) {
+#ifdef DEBUG
+ printf(";; nameserver invalid: %s\n", addr);
+#endif
+ return (0);
+ }
+
+ /* copy the sockaddr */
+ if (ai->ai_addrlen <= sizeof(statp->_u._ext.ext->nsaddrs[0])) {
+ if (statp->_u._ext.ext != NULL) {
+ memcpy(&statp->_u._ext.ext->nsaddrs[i],
+ ai->ai_addr, ai->ai_addrlen);
+ ret = 1;
+ }
+ if (ai->ai_addrlen <= sizeof(statp->nsaddr_list[i])) {
+ memcpy(&statp->nsaddr_list[i],
+ ai->ai_addr, ai->ai_addrlen);
+ ret = 1;
+ } else {
+ statp->nsaddr_list[i].sin_family = 0;
+ }
+#ifdef DEBUG
+ printf(";; nameserver %s\n", addr);
+#endif
+ } else {
+#ifdef DEBUG
+ printf(";; sockaddr too big: %s\n", addr);
+#endif
+ }
+ freeaddrinfo(ai);
+ return (ret);
+}
+
+/*%
+ * Split the string up into words and interpret them as resolver options.
+ */
static void
res_setoptions(res_state statp, const char *options, const char *source)
{
@@ -737,7 +870,8 @@
#endif
void
-res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) {
+res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt)
+{
int i, nserv;
size_t size;
@@ -784,7 +918,6 @@
set++;
}
statp->nscount = nserv;
-
}
int

File Metadata

Mime Type
text/plain
Expires
Tue, Jun 30, 9:19 AM (12 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34455771
Default Alt Text
D57924.diff (17 KB)

Event Timeline