Annotation of embedaddon/dhcp/minires/res_init.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) 1985, 1989, 1993
! 3: * The Regents of the University of California. All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: * 3. All advertising materials mentioning features or use of this software
! 14: * must display the following acknowledgement:
! 15: * This product includes software developed by the University of
! 16: * California, Berkeley and its contributors.
! 17: * 4. Neither the name of the University nor the names of its contributors
! 18: * may be used to endorse or promote products derived from this software
! 19: * without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 31: * SUCH DAMAGE.
! 32: */
! 33:
! 34: /*
! 35: * Portions Copyright (c) 1993 by Digital Equipment Corporation.
! 36: *
! 37: * Permission to use, copy, modify, and distribute this software for any
! 38: * purpose with or without fee is hereby granted, provided that the above
! 39: * copyright notice and this permission notice appear in all copies, and that
! 40: * the name of Digital Equipment Corporation not be used in advertising or
! 41: * publicity pertaining to distribution of the document or software without
! 42: * specific, written prior permission.
! 43: *
! 44: * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
! 45: * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
! 46: * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
! 47: * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
! 48: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
! 49: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
! 50: * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
! 51: * SOFTWARE.
! 52: */
! 53:
! 54: /*
! 55: * Portions Copyright (c) 2004,2007,2009 by Internet Systems Consortium, Inc. ("ISC")
! 56: * Portions Copyright (c) 1995-2003 by Internet Software Consortium
! 57: *
! 58: * Permission to use, copy, modify, and distribute this software for any
! 59: * purpose with or without fee is hereby granted, provided that the above
! 60: * copyright notice and this permission notice appear in all copies.
! 61: *
! 62: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
! 63: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 64: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
! 65: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 66: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 67: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 68: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 69: *
! 70: * Internet Systems Consortium, Inc.
! 71: * 950 Charter Street
! 72: * Redwood City, CA 94063
! 73: * <info@isc.org>
! 74: * https://www.isc.org/
! 75: */
! 76:
! 77: #if defined(LIBC_SCCS) && !defined(lint)
! 78: static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
! 79: static const char rcsid[] = "$Id: res_init.c,v 1.11.74.2 2009-07-24 22:04:52 sar Exp $";
! 80: #endif /* LIBC_SCCS and not lint */
! 81:
! 82: #include <sys/types.h>
! 83: #include <sys/param.h>
! 84: #include <sys/socket.h>
! 85: #include <sys/time.h>
! 86:
! 87: #include <netinet/in.h>
! 88: #include <arpa/inet.h>
! 89:
! 90: #include <ctype.h>
! 91: #include <stdio.h>
! 92: #include <stdlib.h>
! 93: #include <string.h>
! 94: #include <unistd.h>
! 95:
! 96: #include "minires/minires.h"
! 97: #include "arpa/nameser.h"
! 98:
! 99: /* Options. Should all be left alone. */
! 100: #define RESOLVSORT
! 101: #define RFC1535
! 102:
! 103: static void res_setoptions (res_state, const char *, const char *);
! 104:
! 105: #ifdef RESOLVSORT
! 106: static const char sort_mask[] = "/&";
! 107: #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
! 108: static u_int32_t net_mask (struct in_addr);
! 109: #endif
! 110:
! 111: #if !defined(isascii) /* XXX - could be a function */
! 112: # define isascii(c) (!(c & 0200))
! 113: #endif
! 114:
! 115: /*
! 116: * Resolver state default settings.
! 117: */
! 118:
! 119: /*
! 120: * Set up default settings. If the configuration file exist, the values
! 121: * there will have precedence. Otherwise, the server address is set to
! 122: * INADDR_ANY and the default domain name comes from the gethostname().
! 123: *
! 124: * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
! 125: * rather than INADDR_ANY ("0.0.0.0") as the default name server address
! 126: * since it was noted that INADDR_ANY actually meant ``the first interface
! 127: * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
! 128: * it had to be "up" in order for you to reach your own name server. It
! 129: * was later decided that since the recommended practice is to always
! 130: * install local static routes through 127.0.0.1 for all your network
! 131: * interfaces, that we could solve this problem without a code change.
! 132: *
! 133: * The configuration file should always be used, since it is the only way
! 134: * to specify a default domain. If you are running a server on your local
! 135: * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
! 136: * in the configuration file.
! 137: *
! 138: * Return 0 if completes successfully, -1 on error
! 139: */
! 140: extern int minires_vinit(res_state, int);
! 141:
! 142: #if defined (TRACING)
! 143: u_int trace_mr_res_randomid(u_int);
! 144: #endif
! 145:
! 146: int
! 147: res_ninit(res_state statp) {
! 148:
! 149: return (minires_vinit(statp, 0));
! 150: }
! 151:
! 152: /* This function has to be reachable by res_data.c but not publically. */
! 153: int
! 154: minires_vinit(res_state statp, int preinit) {
! 155: register FILE *fp;
! 156: char *cp;
! 157: register char **pp;
! 158: register int n;
! 159: char buf[BUFSIZ];
! 160: int nserv = 0; /* number of nameserver records read from file */
! 161: int haveenv = 0;
! 162: int havesearch = 0;
! 163: #ifdef RESOLVSORT
! 164: int nsort = 0;
! 165: char *net;
! 166: #endif
! 167: #ifndef RFC1535
! 168: int dots;
! 169: #endif
! 170:
! 171: if (!preinit) {
! 172: statp->retrans = RES_TIMEOUT;
! 173: statp->retry = RES_DFLRETRY;
! 174: statp->options = RES_DEFAULT;
! 175: statp->id = res_randomid();
! 176: #if defined (TRACING)
! 177: statp->id = trace_mr_res_randomid (statp -> id);
! 178: #endif
! 179: }
! 180:
! 181: #ifdef USELOOPBACK
! 182: statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
! 183: #else
! 184: statp->nsaddr.sin_addr.s_addr = INADDR_ANY;
! 185: #endif
! 186: statp->nsaddr.sin_family = AF_INET;
! 187: statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
! 188: statp->nscount = 1;
! 189: statp->ndots = 1;
! 190: statp->pfcode = 0;
! 191: statp->_sock = -1;
! 192: statp->_flags = 0;
! 193: statp->qhook = NULL;
! 194: statp->rhook = NULL;
! 195:
! 196: /* Allow user to override the local domain definition */
! 197: if ((cp = getenv("LOCALDOMAIN")) != NULL) {
! 198: (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
! 199: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
! 200: haveenv++;
! 201:
! 202: /*
! 203: * Set search list to be blank-separated strings
! 204: * from rest of env value. Permits users of LOCALDOMAIN
! 205: * to still have a search list, and anyone to set the
! 206: * one that they want to use as an individual (even more
! 207: * important now that the rfc1535 stuff restricts searches)
! 208: */
! 209: cp = statp->defdname;
! 210: pp = statp->dnsrch;
! 211: *pp++ = cp;
! 212: for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
! 213: if (*cp == '\n') /* silly backwards compat */
! 214: break;
! 215: else if (*cp == ' ' || *cp == '\t') {
! 216: *cp = 0;
! 217: n = 1;
! 218: } else if (n) {
! 219: *pp++ = cp;
! 220: n = 0;
! 221: havesearch = 1;
! 222: }
! 223: }
! 224: /* null terminate last domain if there are excess */
! 225: while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
! 226: cp++;
! 227: *cp = '\0';
! 228: *pp++ = 0;
! 229: }
! 230:
! 231: #define MATCH(line, name) \
! 232: (!strncmp(line, name, sizeof(name) - 1) && \
! 233: (line[sizeof(name) - 1] == ' ' || \
! 234: line[sizeof(name) - 1] == '\t'))
! 235:
! 236: if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
! 237: /* read the config file */
! 238: while (fgets(buf, sizeof(buf), fp) != NULL) {
! 239: /* skip comments */
! 240: if (*buf == ';' || *buf == '#')
! 241: continue;
! 242: /* read default domain name */
! 243: if (MATCH(buf, "domain")) {
! 244: if (haveenv) /* skip if have from environ */
! 245: continue;
! 246: cp = buf + sizeof("domain") - 1;
! 247: while (*cp == ' ' || *cp == '\t')
! 248: cp++;
! 249: if ((*cp == '\0') || (*cp == '\n'))
! 250: continue;
! 251: strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
! 252: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
! 253: if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
! 254: *cp = '\0';
! 255: havesearch = 0;
! 256: continue;
! 257: }
! 258: /* set search list */
! 259: if (MATCH(buf, "search")) {
! 260: if (haveenv) /* skip if have from environ */
! 261: continue;
! 262: cp = buf + sizeof("search") - 1;
! 263: while (*cp == ' ' || *cp == '\t')
! 264: cp++;
! 265: if ((*cp == '\0') || (*cp == '\n'))
! 266: continue;
! 267: strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
! 268: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
! 269: if ((cp = strchr(statp->defdname, '\n')) != NULL)
! 270: *cp = '\0';
! 271: /*
! 272: * Set search list to be blank-separated strings
! 273: * on rest of line.
! 274: */
! 275: cp = statp->defdname;
! 276: pp = statp->dnsrch;
! 277: *pp++ = cp;
! 278: for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
! 279: if (*cp == ' ' || *cp == '\t') {
! 280: *cp = 0;
! 281: n = 1;
! 282: } else if (n) {
! 283: *pp++ = cp;
! 284: n = 0;
! 285: }
! 286: }
! 287: /* null terminate last domain if there are excess */
! 288: while (*cp != '\0' && *cp != ' ' && *cp != '\t')
! 289: cp++;
! 290: *cp = '\0';
! 291: *pp++ = 0;
! 292: havesearch = 1;
! 293: continue;
! 294: }
! 295: /* read nameservers to query */
! 296: if (MATCH(buf, "nameserver") && nserv < MAXNS) {
! 297: struct in_addr a;
! 298:
! 299: cp = buf + sizeof("nameserver") - 1;
! 300: while (*cp == ' ' || *cp == '\t')
! 301: cp++;
! 302: if ((*cp != '\0') && (*cp != '\n') && inet_aton(cp, &a)) {
! 303: statp->nsaddr_list[nserv].sin_addr = a;
! 304: statp->nsaddr_list[nserv].sin_family = AF_INET;
! 305: statp->nsaddr_list[nserv].sin_port =
! 306: htons(NAMESERVER_PORT);
! 307: nserv++;
! 308: }
! 309: continue;
! 310: }
! 311: #ifdef RESOLVSORT
! 312: if (MATCH(buf, "sortlist")) {
! 313: struct in_addr a;
! 314:
! 315: cp = buf + sizeof("sortlist") - 1;
! 316: while (nsort < MAXRESOLVSORT) {
! 317: while (*cp == ' ' || *cp == '\t')
! 318: cp++;
! 319: if (*cp == '\0' || *cp == '\n' || *cp == ';')
! 320: break;
! 321: net = cp;
! 322: while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
! 323: isascii((int)*cp) && !isspace((int)*cp))
! 324: cp++;
! 325: n = *cp;
! 326: *cp = 0;
! 327: if (inet_aton(net, &a)) {
! 328: statp->sort_list[nsort].addr = a;
! 329: if (ISSORTMASK(n)) {
! 330: *cp++ = n;
! 331: net = cp;
! 332: while (*cp && *cp != ';' &&
! 333: isascii((int)*cp) && !isspace((int)*cp))
! 334: cp++;
! 335: n = *cp;
! 336: *cp = 0;
! 337: if (inet_aton(net, &a)) {
! 338: statp->sort_list[nsort].mask = a.s_addr;
! 339: } else {
! 340: statp->sort_list[nsort].mask =
! 341: net_mask(statp->sort_list[nsort].addr);
! 342: }
! 343: } else {
! 344: statp->sort_list[nsort].mask =
! 345: net_mask(statp->sort_list[nsort].addr);
! 346: }
! 347: nsort++;
! 348: }
! 349: *cp = n;
! 350: }
! 351: continue;
! 352: }
! 353: #endif
! 354: if (MATCH(buf, "options")) {
! 355: res_setoptions(statp, buf + sizeof("options") - 1, "conf");
! 356: continue;
! 357: }
! 358: }
! 359: if (nserv > 1)
! 360: statp->nscount = nserv;
! 361: #ifdef RESOLVSORT
! 362: statp->nsort = nsort;
! 363: #endif
! 364: (void) fclose(fp);
! 365: }
! 366: if (statp->defdname[0] == 0 &&
! 367: gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
! 368: (cp = strchr(buf, '.')) != NULL)
! 369: strcpy(statp->defdname, cp + 1);
! 370:
! 371: /* find components of local domain that might be searched */
! 372: if (havesearch == 0) {
! 373: pp = statp->dnsrch;
! 374: *pp++ = statp->defdname;
! 375: *pp = NULL;
! 376:
! 377: #ifndef RFC1535
! 378: dots = 0;
! 379: for (cp = statp->defdname; *cp; cp++)
! 380: dots += (*cp == '.');
! 381:
! 382: cp = statp->defdname;
! 383: while (pp < statp->dnsrch + MAXDFLSRCH) {
! 384: if (dots < LOCALDOMAINPARTS)
! 385: break;
! 386: cp = strchr(cp, '.') + 1; /* we know there is one */
! 387: *pp++ = cp;
! 388: dots--;
! 389: }
! 390: *pp = NULL;
! 391: if (statp->options & RES_DEBUG) {
! 392: printf(";; res_init()... default dnsrch list:\n");
! 393: for (pp = statp->dnsrch; *pp; pp++)
! 394: printf(";;\t%s\n", *pp);
! 395: printf(";;\t..END..\n");
! 396: }
! 397: #endif /* !RFC1535 */
! 398: }
! 399:
! 400: if ((cp = getenv("RES_OPTIONS")) != NULL)
! 401: res_setoptions(statp, cp, "env");
! 402: statp->options |= RES_INIT;
! 403: return (0);
! 404: }
! 405:
! 406: static void
! 407: res_setoptions(res_state statp, const char *options, const char *source) {
! 408: const char *cp = options;
! 409: int i;
! 410:
! 411: if (statp->options & RES_DEBUG)
! 412: printf(";; res_setoptions(\"%s\", \"%s\")...\n",
! 413: options, source);
! 414: while (*cp) {
! 415: /* skip leading and inner runs of spaces */
! 416: while (*cp == ' ' || *cp == '\t')
! 417: cp++;
! 418: /* search for and process individual options */
! 419: if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
! 420: i = atoi(cp + sizeof("ndots:") - 1);
! 421: if (i <= RES_MAXNDOTS)
! 422: statp->ndots = i;
! 423: else
! 424: statp->ndots = RES_MAXNDOTS;
! 425: if (statp->options & RES_DEBUG)
! 426: printf(";;\tndots=%d\n", statp->ndots);
! 427: } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
! 428: i = atoi(cp + sizeof("timeout:") - 1);
! 429: if (i <= RES_MAXRETRANS)
! 430: statp->retrans = i;
! 431: else
! 432: statp->retrans = RES_MAXRETRANS;
! 433: } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
! 434: i = atoi(cp + sizeof("attempts:") - 1);
! 435: if (i <= RES_MAXRETRY)
! 436: statp->retry = i;
! 437: else
! 438: statp->retry = RES_MAXRETRY;
! 439: } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
! 440: if (!(statp->options & RES_DEBUG)) {
! 441: printf(";; res_setoptions(\"%s\", \"%s\")..\n",
! 442: options, source);
! 443: statp->options |= RES_DEBUG;
! 444: }
! 445: printf(";;\tdebug\n");
! 446: } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
! 447: statp->options |= RES_USE_INET6;
! 448: } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
! 449: statp->options |= RES_ROTATE;
! 450: } else if (!strncmp(cp, "no-check-names",
! 451: sizeof("no-check-names") - 1)) {
! 452: statp->options |= RES_NOCHECKNAME;
! 453: } else {
! 454: /* XXX - print a warning here? */
! 455: }
! 456: /* skip to next run of spaces */
! 457: while (*cp && *cp != ' ' && *cp != '\t')
! 458: cp++;
! 459: }
! 460: }
! 461:
! 462: #ifdef RESOLVSORT
! 463: /* XXX - should really support CIDR which means explicit masks always. */
! 464: static u_int32_t
! 465: net_mask(in) /* XXX - should really use system's version of this */
! 466: struct in_addr in;
! 467: {
! 468: register u_int32_t i = ntohl(in.s_addr);
! 469:
! 470: if (IN_CLASSA(i))
! 471: return (htonl(IN_CLASSA_NET));
! 472: else if (IN_CLASSB(i))
! 473: return (htonl(IN_CLASSB_NET));
! 474: return (htonl(IN_CLASSC_NET));
! 475: }
! 476: #endif
! 477:
! 478: u_int
! 479: res_randomid(void) {
! 480: struct timeval now;
! 481:
! 482: gettimeofday(&now, NULL);
! 483: return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
! 484: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>