diff options
author | pst <pst@FreeBSD.org> | 1994-09-25 02:12:49 +0000 |
---|---|---|
committer | pst <pst@FreeBSD.org> | 1994-09-25 02:12:49 +0000 |
commit | 4f0d0da86d54d2621713e7d8ccfd0507888f348b (patch) | |
tree | a71412a79b4754c5fb0d8868e5fb690fde4a7fbb /lib/libc/net/res_init.c | |
parent | 860a10b12f94d28edf8ffa8a4df515be3e1d5f29 (diff) | |
download | FreeBSD-src-4f0d0da86d54d2621713e7d8ccfd0507888f348b.zip FreeBSD-src-4f0d0da86d54d2621713e7d8ccfd0507888f348b.tar.gz |
get* rework and new bind code
Diffstat (limited to 'lib/libc/net/res_init.c')
-rw-r--r-- | lib/libc/net/res_init.c | 256 |
1 files changed, 229 insertions, 27 deletions
diff --git a/lib/libc/net/res_init.c b/lib/libc/net/res_init.c index 1e0fd05..e32f8d3 100644 --- a/lib/libc/net/res_init.c +++ b/lib/libc/net/res_init.c @@ -53,7 +53,7 @@ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; -static char rcsid[] = "$Id: res_init.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $"; +static char rcsid[] = "$Id: res_init.c,v 4.9.1.12 1994/06/11 22:05:04 vixie Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> @@ -61,30 +61,44 @@ static char rcsid[] = "$Id: res_init.c,v 4.9.1.1 1993/05/02 22:43:03 vixie Rel $ #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> + +#include <stdio.h> +#include <ctype.h> #include <resolv.h> #include <unistd.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> +static void res_setoptions __P((char *, char *)); + +#ifdef RESOLVSORT +static u_int32_t net_mask __P((struct in_addr)); +#endif + /* - * Resolver state default settings + * Resolver state default settings. */ -struct __res_state _res = { - RES_TIMEOUT, /* retransmition time interval */ - 4, /* number of times to retransmit */ - RES_DEFAULT, /* options flags */ - 1, /* number of name servers */ -}; +struct __res_state _res; /* * Set up default settings. If the configuration file exist, the values * there will have precedence. Otherwise, the server address is set to * INADDR_ANY and the default domain name comes from the gethostname(). * - * The configuration file should only be used if you want to redefine your - * domain or run without a server on your machine. + * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 + * rather than INADDR_ANY ("0.0.0.0") as the default name server address + * 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 + * install local static routes through 127.0.0.1 for all your network + * interfaces, that we could solve this problem without a code change. + * + * The configuration file should always be used, since it is the only way + * to specify a default domain. If you are running a server on your local + * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" + * in the configuration file. * * Return 0 if completes successfully, -1 on error */ @@ -92,11 +106,35 @@ res_init() { register FILE *fp; register char *cp, **pp; - register int n; + register int n, dots; 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 + + /* + * These four 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. + */ + if (!_res.retrans) + _res.retrans = RES_TIMEOUT; + if (!_res.retry) + _res.retry = 4; + if (!_res.options) + _res.options = RES_DEFAULT; #ifdef USELOOPBACK _res.nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); @@ -106,14 +144,41 @@ res_init() _res.nsaddr.sin_family = AF_INET; _res.nsaddr.sin_port = htons(NAMESERVER_PORT); _res.nscount = 1; + _res.ndots = 1; _res.pfcode = 0; /* Allow user to override the local domain definition */ if ((cp = getenv("LOCALDOMAIN")) != NULL) { - (void)strncpy(_res.defdname, cp, sizeof(_res.defdname)); - if ((cp = strpbrk(_res.defdname, " \t\n")) != NULL) - *cp = '\0'; + (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); 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 = _res.defdname; + pp = _res.dnsrch; + *pp++ = cp; + for (n = 0; *cp && pp < _res.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; } if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { @@ -158,7 +223,9 @@ res_init() cp = _res.defdname; pp = _res.dnsrch; *pp++ = cp; - for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { + for (n = 0; + *cp && pp < _res.dnsrch + MAXDNSRCH; + cp++) { if (*cp == ' ' || *cp == '\t') { *cp = 0; n = 1; @@ -192,32 +259,167 @@ res_init() } continue; } +#ifdef RESOLVSORT + if (!strncmp(buf, "sortlist", sizeof("sortlist") -1)) { + 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 && *cp != '/' && + isascii(*cp) && !isspace(*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &a)) { + _res.sort_list[nsort].addr = a; + if (n == '/') { + *cp++ = n; + net = cp; + while (*cp && isascii(*cp) && !isspace(*cp)) + cp++; + n = *cp; + *cp = 0; + if (inet_aton(net, &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++; + } + *cp++ = n; + } + continue; + } +#endif + if (!strncmp(buf, "options", sizeof("options") -1)) { + res_setoptions(buf + sizeof("options") - 1, "conf"); + continue; + } } if (nserv > 1) _res.nscount = nserv; +#ifdef RESOLVSORT + _res.nsort = nsort; +#endif (void) fclose(fp); - } + } /*if(fopen)*/ if (_res.defdname[0] == 0) { - if (gethostname(buf, sizeof(_res.defdname)) == 0 && - (cp = strchr(buf, '.'))) + if (gethostname(buf, sizeof(_res.defdname) - 1) == 0 && + (cp = strchr(buf, '.'))) { (void)strcpy(_res.defdname, cp + 1); + } } /* find components of local domain that might be searched */ if (havesearch == 0) { pp = _res.dnsrch; *pp++ = _res.defdname; - for (cp = _res.defdname, n = 0; *cp; cp++) - if (*cp == '.') - n++; + *pp = NULL; + +#ifndef RFC1535 + dots = 0; + for (cp = _res.defdname; *cp; cp++) + dots += (*cp == '.'); + cp = _res.defdname; - for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; - n--) { - cp = strchr(cp, '.'); - *pp++ = ++cp; + while (pp < _res.dnsrch + MAXDFLSRCH) { + if (dots < LOCALDOMAINPARTS) { + break; + } + cp = strchr(cp, '.') + 1; /* we know there is one */ + *pp++ = cp; + dots--; } - *pp++ = 0; + *pp = NULL; +#ifdef DEBUG + if (_res.options & RES_DEBUG) { + printf(";; res_init()... default dnsrch list:\n"); + for (pp = _res.dnsrch; *pp; pp++) { + printf(";;\t%s\n", *pp); + } + printf(";;\t..END..\n"); + } +#endif /*DEBUG*/ +#endif /*!RFC1535*/ + } + + if ((cp = getenv("RES_OPTIONS")) != NULL) { + res_setoptions(cp, "env"); } _res.options |= RES_INIT; return (0); } + + +static void +res_setoptions(options, source) + char *options, *source; +{ + char *cp = options; + int i; + +#ifdef DEBUG + if (_res.options & RES_DEBUG) { + printf(";; res_setoptions(\"%s\", \"%s\")...\n", + options, source); + } +#endif + while (*cp) { + /* skip leading and inner runs of spaces */ + while (*cp == ' ' || *cp == '\t') + cp++; + /* search for and process individual options */ + if (!strncmp(cp, "ndots:", sizeof("ndots:")-1)) { + i = atoi(cp + sizeof("ndots:") - 1); + if (i <= RES_MAXNDOTS) + _res.ndots = i; + else + _res.ndots = RES_MAXNDOTS; +#ifdef DEBUG + if (_res.options & RES_DEBUG) { + printf(";;\tndots=%d\n", _res.ndots); + } +#endif + } else if (!strncmp(cp, "debug", sizeof("debug")-1)) { +#ifdef DEBUG + if (!(_res.options & RES_DEBUG)) { + printf(";; res_setoptions(\"%s\", \"%s\")..\n", + options, source); + _res.options |= RES_DEBUG; + } + printf(";;\tdebug\n"); +#endif + } else { + /* XXX - print a warning here? */ + } + /* skip to next run of spaces */ + while (*cp && *cp != ' ' && *cp != '\t') + cp++; + } +} + +#ifdef RESOLVSORT +static u_int32_t +net_mask(in) /* XXX - should really use system's version of this */ + struct in_addr in; +{ + register u_int32_t i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (htonl(IN_CLASSA_NET)); + else if (IN_CLASSB(i)) + return (htonl(IN_CLASSB_NET)); + else + return (htonl(IN_CLASSC_NET)); +} +#endif |