Esempio n. 1
0
/* 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);
}
Esempio n. 2
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));
}