/* This function has to be reachable by res_data.c but not publically. */ int __res_vinit(res_state statp, int preinit) { FILE *fp; char *cp, **pp; int n; char buf[BUFSIZ]; int nserv = 0; /* number of nameservers read from file */ int have_serv6 = 0; int haveenv = 0; int havesearch = 0; #ifdef RESOLVSORT int nsort = 0; char *net; #endif #ifndef RFC1535 int dots; #endif #ifdef _LIBC statp->_u._ext.initstamp = __res_initstamp; #endif if (!preinit) { statp->retrans = RES_TIMEOUT; statp->retry = RES_DFLRETRY; statp->options = RES_DEFAULT; statp->id = res_randomid(); } statp->nscount = 0; statp->ndots = 1; statp->pfcode = 0; statp->_vcsock = -1; statp->_flags = 0; statp->qhook = NULL; statp->rhook = NULL; statp->_u._ext.nscount = 0; for (n = 0; n < MAXNS; n++) statp->_u._ext.nsaddrs[n] = NULL; /* Allow user to override the local domain definition */ if ((cp = 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++ = 0; } #define MATCH(line, name) \ (!strncmp(line, name, sizeof(name) - 1) && \ (line[sizeof(name) - 1] == ' ' || \ line[sizeof(name) - 1] == '\t')) if ((fp = fopen(_PATH_RESCONF, "rce")) != NULL) { /* No threads use this stream. */ __fsetlocking (fp, FSETLOCKING_BYCALLER); /* read the config file */ while (__fgets_unlocked(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++ = 0; havesearch = 1; continue; } /* read nameservers to query */ if (MATCH(buf, "nameserver") && nserv < MAXNS) { struct in_addr a; cp = buf + sizeof("nameserver") - 1; while (*cp == ' ' || *cp == '\t') cp++; if ((*cp != '\0') && (*cp != '\n') && __inet_aton(cp, &a)) { statp->nsaddr_list[nserv].sin_addr = a; statp->nsaddr_list[nserv].sin_family = AF_INET; statp->nsaddr_list[nserv].sin_port = htons(NAMESERVER_PORT); nserv++; #ifdef _LIBC } else { struct in6_addr a6; char *el; if ((el = strpbrk(cp, " \t\n")) != NULL) *el = '\0'; if ((el = strchr(cp, SCOPE_DELIMITER)) != NULL) *el = '\0'; if ((*cp != '\0') && (__inet_pton(AF_INET6, cp, &a6) > 0)) { struct sockaddr_in6 *sa6; sa6 = malloc(sizeof(*sa6)); if (sa6 != NULL) { sa6->sin6_family = AF_INET6; sa6->sin6_port = htons(NAMESERVER_PORT); sa6->sin6_flowinfo = 0; sa6->sin6_addr = a6; if (__glibc_likely (el == NULL)) sa6->sin6_scope_id = 0; else { int try_numericscope = 1; if (IN6_IS_ADDR_LINKLOCAL (&a6) || IN6_IS_ADDR_MC_LINKLOCAL (&a6)) { sa6->sin6_scope_id = __if_nametoindex (el + 1); if (sa6->sin6_scope_id != 0) try_numericscope = 0; } if (try_numericscope) { char *end; sa6->sin6_scope_id = (uint32_t) strtoul (el + 1, &end, 10); if (*end != '\0') sa6->sin6_scope_id = 0; } } statp->nsaddr_list[nserv].sin_family = 0; statp->_u._ext.nsaddrs[nserv] = sa6; statp->_u._ext.nssocks[nserv] = -1; have_serv6 = 1; nserv++; } } #endif } continue; } #ifdef RESOLVSORT if (MATCH(buf, "sortlist")) { struct in_addr a; 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(*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(*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); } nsort++; } *cp = n; } continue; } #endif if (MATCH(buf, "options")) { res_setoptions(statp, buf + sizeof("options") - 1, "conf"); continue; } } statp->nscount = nserv; #ifdef _LIBC if (have_serv6) { /* We try IPv6 servers again. */ statp->ipv6_unavail = false; } #endif #ifdef RESOLVSORT statp->nsort = nsort; #endif (void) fclose(fp); } if (__builtin_expect(statp->nscount == 0, 0)) { statp->nsaddr.sin_addr = __inet_makeaddr(IN_LOOPBACKNET, 1); statp->nsaddr.sin_family = AF_INET; statp->nsaddr.sin_port = htons(NAMESERVER_PORT); statp->nscount = 1; } if (statp->defdname[0] == 0 && __gethostname(buf, sizeof(statp->defdname) - 1) == 0 && (cp = strchr(buf, '.')) != NULL) strcpy(statp->defdname, cp + 1); /* find components of local domain that might be searched */ if (havesearch == 0) { pp = statp->dnsrch; *pp++ = statp->defdname; *pp = NULL; #ifndef RFC1535 dots = 0; for (cp = statp->defdname; *cp; cp++) dots += (*cp == '.'); cp = statp->defdname; while (pp < statp->dnsrch + MAXDFLSRCH) { if (dots < LOCALDOMAINPARTS) break; cp = __rawmemchr(cp, '.') + 1; /* we know there is one */ *pp++ = cp; dots--; } *pp = NULL; #ifdef DEBUG if (statp->options & RES_DEBUG) { printf(";; res_init()... default dnsrch list:\n"); for (pp = statp->dnsrch; *pp; pp++) printf(";;\t%s\n", *pp); printf(";;\t..END..\n"); } #endif #endif /* !RFC1535 */ } if ((cp = getenv("RES_OPTIONS")) != NULL) res_setoptions(statp, cp, "env"); statp->options |= RES_INIT; return (0); }
/* * Provide broken inet_pton() implementation by default for binary * compatibility. */ int inet_pton(int af, char *inp, void *outp) { return (__inet_pton(af, inp, outp, 1)); }