diff options
Diffstat (limited to 'resolv/res_init.c')
-rw-r--r-- | resolv/res_init.c | 436 |
1 files changed, 131 insertions, 305 deletions
diff --git a/resolv/res_init.c b/resolv/res_init.c index e5520ff65e..bf6cf7f7b1 100644 --- a/resolv/res_init.c +++ b/resolv/res_init.c @@ -1,6 +1,4 @@ /* - * ++Copyright++ 1985, 1989, 1993 - * - * Copyright (c) 1985, 1989, 1993 * The Regents of the University of California. All rights reserved. * @@ -27,7 +25,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - + */ + +/* * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any @@ -45,68 +45,55 @@ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. - * - - * --Copyright-- + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. */ #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; -static char rcsid[] = "$Id$"; +static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; +static const char rcsid[] = "$Id$"; #endif /* LIBC_SCCS and not lint */ #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> #include <sys/time.h> + #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> -#include <stdio.h> #include <ctype.h> #include <resolv.h> -#if defined(BSD) && (BSD >= 199103) -# include <unistd.h> -# include <stdlib.h> -# include <string.h> -#else -# include "../conf/portability.h" -#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> -/*-------------------------------------- info about "sortlist" -------------- - * Marc Majka 1994/04/16 - * Allan Nathanson 1994/10/29 (BIND 4.9.3.x) - * - * NetInfo resolver configuration directory support. - * - * Allow a NetInfo directory to be created in the hierarchy which - * contains the same information as the resolver configuration file. - * - * - The local domain name is stored as the value of the "domain" property. - * - The Internet address(es) of the name server(s) are stored as values - * of the "nameserver" property. - * - The name server addresses are stored as values of the "nameserver" - * property. - * - The search list for host-name lookup is stored as values of the - * "search" property. - * - The sortlist comprised of IP address netmask pairs are stored as - * values of the "sortlist" property. The IP address and optional netmask - * should be separated by a slash (/) or ampersand (&) character. - * - Internal resolver variables can be set from the value of the "options" - * property. - */ -#if defined(NeXT) -# include <netinfo/ni.h> -# define NI_PATH_RESCONF "/locations/resolver" -# define NI_TIMEOUT 10 -static int netinfo_res_init __P((int *haveenv, int *havesearch)); -#endif +/* Options. Should all be left alone. */ +#define RESOLVSORT +#define RFC1535 +#undef DEBUG -#if defined(USE_OPTIONS_H) -# include "../conf/options.h" -#endif +static void +res_setoptions (res_state statp, const char *options, const char *source) + internal_function; -static void res_setoptions __P((char *, char *)) internal_function; #ifdef RESOLVSORT static const char sort_mask[] = "/&"; @@ -122,12 +109,6 @@ static u_int32_t net_mask __P((struct in_addr)); * Resolver state default settings. */ -struct __res_state _res -# if defined(__BIND_RES_TEXT) - = { RES_TIMEOUT, } /* Motorola, et al. */ -# endif - ; - /* * Set up default settings. If the configuration file exist, the values * there will have precedence. Otherwise, the server address is set to @@ -138,7 +119,7 @@ struct __res_state _res * since it was noted that INADDR_ANY actually meant ``the first interface * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, * it had to be "up" in order for you to reach your own name server. It - * was later decided that since the recommended practice is to always + * was later decided that since the recommended practice is to always * install local static routes through 127.0.0.1 for all your network * interfaces, that we could solve this problem without a code change. * @@ -150,12 +131,19 @@ struct __res_state _res * Return 0 if completes successfully, -1 on error */ int -res_init() -{ +res_ninit(res_state statp) { + extern int __res_vinit(res_state, int); + + return (__res_vinit(statp, 0)); +} + +/* This function has to be reachable by res_data.c but not publically. */ +int +__res_vinit(res_state statp, int preinit) { register FILE *fp; register char *cp, **pp; register int n; - char buf[MAXDNAME]; + char buf[BUFSIZ]; int nserv = 0; /* number of nameserver records read from file */ int haveenv = 0; int havesearch = 0; @@ -167,54 +155,32 @@ res_init() int dots; #endif - /* - * These three fields used to be statically initialized. This made - * it hard to use this code in a shared library. It is necessary, - * now that we're doing dynamic initialization here, that we preserve - * the old semantics: if an application modifies one of these three - * fields of _res before res_init() is called, res_init() will not - * alter them. Of course, if an application is setting them to - * _zero_ before calling res_init(), hoping to override what used - * to be the static default, we can't detect it and unexpected results - * will follow. Zero for any of these fields would make no sense, - * so one can safely assume that the applications were already getting - * unexpected results. - * - * _res.options is tricky since some apps were known to diddle the bits - * before res_init() was first called. We can't replicate that semantic - * with dynamic initialization (they may have turned bits off that are - * set in RES_DEFAULT). Our solution is to declare such applications - * "broken". They could fool us by setting RES_INIT but none do (yet). - */ - if (!_res.retrans) - _res.retrans = RES_TIMEOUT; - if (!_res.retry) - _res.retry = 4; - if (!(_res.options & RES_INIT)) - _res.options = RES_DEFAULT; - - /* - * This one used to initialize implicitly to zero, so unless the app - * has set it to something in particular, we can randomize it now. - */ - if (!_res.id) - _res.id = res_randomid(); + if (!preinit) { + statp->retrans = RES_TIMEOUT; + statp->retry = RES_DFLRETRY; + statp->options = RES_DEFAULT; + statp->id = res_randomid(); + } #ifdef USELOOPBACK - _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); - _res.nscount = 1; + statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); #else - _res.nsaddr.sin_addr.s_addr = INADDR_ANY; - _res.nscount = 0; + statp->nsaddr.sin_addr.s_addr = INADDR_ANY; #endif - _res.nsaddr.sin_family = AF_INET; - _res.nsaddr.sin_port = htons(NAMESERVER_PORT); - _res.ndots = 1; - _res.pfcode = 0; + statp->nsaddr.sin_family = AF_INET; + statp->nsaddr.sin_port = htons(NAMESERVER_PORT); + statp->nscount = 1; + statp->ndots = 1; + statp->pfcode = 0; + statp->_sock = -1; + statp->_flags = 0; + statp->qhook = NULL; + statp->rhook = NULL; /* Allow user to override the local domain definition */ if ((cp = __secure_getenv("LOCALDOMAIN")) != NULL) { - (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); + (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); + statp->defdname[sizeof(statp->defdname) - 1] = '\0'; haveenv++; /* @@ -224,10 +190,10 @@ res_init() * one that they want to use as an individual (even more * important now that the rfc1535 stuff restricts searches) */ - cp = _res.defdname; - pp = _res.dnsrch; + cp = statp->defdname; + pp = statp->dnsrch; *pp++ = cp; - for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { + for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { if (*cp == '\n') /* silly backwards compat */ break; else if (*cp == ' ' || *cp == '\t') { @@ -251,9 +217,6 @@ res_init() (line[sizeof(name) - 1] == ' ' || \ line[sizeof(name) - 1] == '\t')) -#ifdef NeXT - if (netinfo_res_init(&haveenv, &havesearch) == 0) -#endif if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { /* read the config file */ while (fgets_unlocked(buf, sizeof(buf), fp) != NULL) { @@ -269,8 +232,9 @@ res_init() cp++; if ((*cp == '\0') || (*cp == '\n')) continue; - strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); - if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL) + 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; @@ -284,16 +248,18 @@ res_init() cp++; if ((*cp == '\0') || (*cp == '\n')) continue; - strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); - *__strchrnul (_res.defdname, '\n') = '\0'; + 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 = _res.defdname; - pp = _res.dnsrch; + cp = statp->defdname; + pp = statp->dnsrch; *pp++ = cp; - for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { + for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { if (*cp == ' ' || *cp == '\t') { *cp = 0; n = 1; @@ -318,9 +284,9 @@ res_init() while (*cp == ' ' || *cp == '\t') cp++; if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) { - _res.nsaddr_list[nserv].sin_addr = a; - _res.nsaddr_list[nserv].sin_family = AF_INET; - _res.nsaddr_list[nserv].sin_port = + 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++; } @@ -343,7 +309,7 @@ res_init() n = *cp; *cp = 0; if (inet_aton(net, &a)) { - _res.sort_list[nsort].addr = a; + statp->sort_list[nsort].addr = a; if (ISSORTMASK(n)) { *cp++ = n; net = cp; @@ -353,14 +319,14 @@ res_init() n = *cp; *cp = 0; if (inet_aton(net, &a)) { - _res.sort_list[nsort].mask = a.s_addr; + statp->sort_list[nsort].mask = a.s_addr; } else { - _res.sort_list[nsort].mask = - net_mask(_res.sort_list[nsort].addr); + statp->sort_list[nsort].mask = + net_mask(statp->sort_list[nsort].addr); } } else { - _res.sort_list[nsort].mask = - net_mask(_res.sort_list[nsort].addr); + statp->sort_list[nsort].mask = + net_mask(statp->sort_list[nsort].addr); } nsort++; } @@ -370,35 +336,35 @@ res_init() } #endif if (MATCH(buf, "options")) { - res_setoptions(buf + sizeof("options") - 1, "conf"); + res_setoptions(statp, buf + sizeof("options") - 1, "conf"); continue; } } - if (nserv > _res.nscount) - _res.nscount = nserv; + if (nserv > 1) + statp->nscount = nserv; #ifdef RESOLVSORT - _res.nsort = nsort; + statp->nsort = nsort; #endif (void) fclose(fp); } - if (_res.defdname[0] == 0 && - __gethostname(buf, sizeof(_res.defdname) - 1) == 0 && + if (statp->defdname[0] == 0 && + __gethostname(buf, sizeof(statp->defdname) - 1) == 0 && (cp = strchr(buf, '.')) != NULL) - strcpy(_res.defdname, cp + 1); + strcpy(statp->defdname, cp + 1); /* find components of local domain that might be searched */ if (havesearch == 0) { - pp = _res.dnsrch; - *pp++ = _res.defdname; + pp = statp->dnsrch; + *pp++ = statp->defdname; *pp = NULL; #ifndef RFC1535 dots = 0; - for (cp = _res.defdname; *cp; cp++) + for (cp = statp->defdname; *cp; cp++) dots += (*cp == '.'); - cp = _res.defdname; - while (pp < _res.dnsrch + MAXDFLSRCH) { + cp = statp->defdname; + while (pp < statp->dnsrch + MAXDFLSRCH) { if (dots < LOCALDOMAINPARTS) break; cp = __rawmemchr(cp, '.') + 1; /* we know there is one */ @@ -407,32 +373,31 @@ res_init() } *pp = NULL; #ifdef DEBUG - if (_res.options & RES_DEBUG) { + if (statp->options & RES_DEBUG) { printf(";; res_init()... default dnsrch list:\n"); - for (pp = _res.dnsrch; *pp; pp++) + for (pp = statp->dnsrch; *pp; pp++) printf(";;\t%s\n", *pp); printf(";;\t..END..\n"); } -#endif /* DEBUG */ +#endif #endif /* !RFC1535 */ } if ((cp = __secure_getenv("RES_OPTIONS")) != NULL) - res_setoptions(cp, "env"); - _res.options |= RES_INIT; + res_setoptions(statp, cp, "env"); + statp->options |= RES_INIT; return (0); } static void internal_function -res_setoptions(options, source) - char *options, *source; +res_setoptions(res_state statp, const char *options, const char *source) { - char *cp = options; + const char *cp = options; int i; #ifdef DEBUG - if (_res.options & RES_DEBUG) + if (statp->options & RES_DEBUG) printf(";; res_setoptions(\"%s\", \"%s\")...\n", options, source); #endif @@ -444,24 +409,41 @@ res_setoptions(options, source) if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { i = atoi(cp + sizeof("ndots:") - 1); if (i <= RES_MAXNDOTS) - _res.ndots = i; + statp->ndots = i; else - _res.ndots = RES_MAXNDOTS; + statp->ndots = RES_MAXNDOTS; #ifdef DEBUG - if (_res.options & RES_DEBUG) - printf(";;\tndots=%d\n", _res.ndots); + if (statp->options & RES_DEBUG) + printf(";;\tndots=%d\n", statp->ndots); #endif + } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) { + i = atoi(cp + sizeof("timeout:") - 1); + if (i <= RES_MAXRETRANS) + statp->retrans = i; + else + statp->retrans = RES_MAXRETRANS; + } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){ + i = atoi(cp + sizeof("attempts:") - 1); + if (i <= RES_MAXRETRY) + statp->retry = i; + else + statp->retry = RES_MAXRETRY; } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { #ifdef DEBUG - if (!(_res.options & RES_DEBUG)) { + if (!(statp->options & RES_DEBUG)) { printf(";; res_setoptions(\"%s\", \"%s\")..\n", options, source); - _res.options |= RES_DEBUG; + statp->options |= RES_DEBUG; } printf(";;\tdebug\n"); #endif } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) { - _res.options |= RES_USE_INET6; + statp->options |= RES_USE_INET6; + } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) { + statp->options |= RES_ROTATE; + } else if (!strncmp(cp, "no-check-names", + sizeof("no-check-names") - 1)) { + statp->options |= RES_NOCHECKNAME; } else { /* XXX - print a warning here? */ } @@ -487,164 +469,8 @@ net_mask(in) /* XXX - should really use system's version of this */ } #endif -#ifdef NeXT -static int -netinfo_res_init(haveenv, havesearch) - int *haveenv; - int *havesearch; -{ - register int n; - void *domain, *parent; - ni_id dir; - ni_status status; - ni_namelist nl; - int nserv = 0; -#ifdef RESOLVSORT - int nsort = 0; -#endif - - status = ni_open(NULL, ".", &domain); - if (status == NI_OK) { - ni_setreadtimeout(domain, NI_TIMEOUT); - ni_setabort(domain, 1); - - /* climb the NetInfo hierarchy to find a resolver directory */ - while (status == NI_OK) { - status = ni_pathsearch(domain, &dir, NI_PATH_RESCONF); - if (status == NI_OK) { - /* found a resolver directory */ - - if (*haveenv == 0) { - /* get the default domain name */ - status = ni_lookupprop(domain, &dir, "domain", &nl); - if (status == NI_OK && nl.ni_namelist_len > 0) { - (void)strncpy(_res.defdname, - nl.ni_namelist_val[0], - sizeof(_res.defdname) - 1); - _res.defdname[sizeof(_res.defdname) - 1] = '\0'; - ni_namelist_free(&nl); - *havesearch = 0; - } - - /* get search list */ - status = ni_lookupprop(domain, &dir, "search", &nl); - if (status == NI_OK && nl.ni_namelist_len > 0) { - (void)strncpy(_res.defdname, - nl.ni_namelist_val[0], - sizeof(_res.defdname) - 1); - _res.defdname[sizeof(_res.defdname) - 1] = '\0'; - /* copy */ - for (n = 0; - n < nl.ni_namelist_len && n < MAXDNSRCH; - n++) { - /* duplicate up to MAXDNSRCH servers */ - char *cp = nl.ni_namelist_val[n]; - _res.dnsrch[n] = - strcpy((char *)malloc(strlen(cp) + 1), cp); - } - ni_namelist_free(&nl); - *havesearch = 1; - } - } - - /* get list of nameservers */ - status = ni_lookupprop(domain, &dir, "nameserver", &nl); - if (status == NI_OK && nl.ni_namelist_len > 0) { - /* copy up to MAXNS servers */ - for (n = 0; - n < nl.ni_namelist_len && nserv < MAXNS; - n++) { - struct in_addr a; - - if (inet_aton(nl.ni_namelist_val[n], &a)) { - _res.nsaddr_list[nserv].sin_addr = a; - _res.nsaddr_list[nserv].sin_family = AF_INET; - _res.nsaddr_list[nserv].sin_port = - htons(NAMESERVER_PORT); - nserv++; - } - } - ni_namelist_free(&nl); - } - - if (nserv > _res.nscount) - _res.nscount = nserv; - -#ifdef RESOLVSORT - /* get sort order */ - status = ni_lookupprop(domain, &dir, "sortlist", &nl); - if (status == NI_OK && nl.ni_namelist_len > 0) { - - /* copy up to MAXRESOLVSORT address/netmask pairs */ - for (n = 0; - n < nl.ni_namelist_len && nsort < MAXRESOLVSORT; - n++) { - char ch; - char *cp; - const char *sp; - struct in_addr a; - - cp = NULL; - for (sp = sort_mask; *sp; sp++) { - char *cp1; - cp1 = strchr(nl.ni_namelist_val[n], *sp); - if (cp && cp1) - cp = (cp < cp1)? cp : cp1; - else if (cp1) - cp = cp1; - } - if (cp != NULL) { - ch = *cp; - *cp = '\0'; - break; - } - if (inet_aton(nl.ni_namelist_val[n], &a)) { - _res.sort_list[nsort].addr = a; - if (*cp && ISSORTMASK(ch)) { - *cp++ = ch; - if (inet_aton(cp, &a)) { - _res.sort_list[nsort].mask = a.s_addr; - } else { - _res.sort_list[nsort].mask = - net_mask(_res.sort_list[nsort].addr); - } - } else { - _res.sort_list[nsort].mask = - net_mask(_res.sort_list[nsort].addr); - } - nsort++; - } - } - ni_namelist_free(&nl); - } - - _res.nsort = nsort; -#endif - - /* get resolver options */ - status = ni_lookupprop(domain, &dir, "options", &nl); - if (status == NI_OK && nl.ni_namelist_len > 0) { - res_setoptions(nl.ni_namelist_val[0], "conf"); - ni_namelist_free(&nl); - } - - ni_free(domain); - return(1); /* using DNS configuration from NetInfo */ - } - - status = ni_open(domain, "..", &parent); - ni_free(domain); - if (status == NI_OK) - domain = parent; - } - } - return(0); /* if not using DNS configuration from NetInfo */ -} -#endif /* NeXT */ - u_int -res_randomid() -{ +res_randomid(void) { struct timeval now; __gettimeofday(&now, NULL); |