The branch main has been updated by des:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ffeb56905ed6a7ac759367096d6dc0596e82e03f

commit ffeb56905ed6a7ac759367096d6dc0596e82e03f
Author:     Dag-Erling Smørgrav <[email protected]>
AuthorDate: 2026-07-06 12:23:33 +0000
Commit:     Dag-Erling Smørgrav <[email protected]>
CommitDate: 2026-07-06 12:23:33 +0000

    libc/resolv: Refactor the configuration parser
    
    This was previously all a single loop in res_init(), apart from option
    parsing which we cleaned up in a previous commit.  Break it out into
    separate functions for reading the configuration line by line, setting
    the default domain, setting the search list, and adding a nameserver
    to the nameserver list.  Sprinkle bounds checks and code comments all
    around.
    
    The sortlist code, which has been disabled for the past 20 years, will
    be dealt with in a separate commit.
    
    MFC after:      1 week
    Reviewed by:    markj
    Differential Revision:  https://reviews.freebsd.org/D57924
---
 lib/libc/resolv/res_init.c | 649 ++++++++++++++++++++++++++-------------------
 1 file changed, 381 insertions(+), 268 deletions(-)

diff --git a/lib/libc/resolv/res_init.c b/lib/libc/resolv/res_init.c
index 4cddb3b0b72a..bd3fd866c189 100644
--- 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 @@ static u_int32_t net_mask(struct in_addr);
 
 #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 @@ res_ninit(res_state statp) {
 
 /*% 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 @@ __res_vinit(res_state statp, int preinit) {
                } },
 #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 @@ __res_vinit(res_state statp, int preinit) {
 #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')
+               while (res_space(*cp))
                        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')
-                       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, strchr(cp, '\0'));
        }
 
        /* guess default domain if not set */
@@ -485,7 +234,7 @@ __res_vinit(res_state statp, int preinit) {
                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,370 @@ __res_vinit(res_state statp, int preinit) {
        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 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;
+
+       /* 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.  Returns 1 if
+ * an entry was inserted, 0 otherwise.
+ */
+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;
+
+       /* 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)
 {
@@ -742,7 +855,8 @@ res_get_nibblesuffix2(res_state statp) {
 #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;
 
@@ -789,7 +903,6 @@ res_setservers(res_state statp, const union 
res_sockaddr_union *set, int cnt) {
                set++;
        }
        statp->nscount = nserv;
-       
 }
 
 int

Reply via email to