Annotation of src/external/bsd/libbind/dist/resolv/res_init.c, Revision 1.1.1.1.8.2
1.1.1.1.8.2! riz 1: /* $NetBSD: res_init.c,v 1.1.1.1 2009/04/12 15:33:56 christos Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1985, 1989, 1993
! 5: * The Regents of the University of California. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by the University of
! 18: * California, Berkeley and its contributors.
! 19: * 4. Neither the name of the University nor the names of its contributors
! 20: * may be used to endorse or promote products derived from this software
! 21: * without specific prior written permission.
! 22: *
! 23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 33: * SUCH DAMAGE.
! 34: */
! 35:
! 36: /*
! 37: * Portions Copyright (c) 1993 by Digital Equipment Corporation.
! 38: *
! 39: * Permission to use, copy, modify, and distribute this software for any
! 40: * purpose with or without fee is hereby granted, provided that the above
! 41: * copyright notice and this permission notice appear in all copies, and that
! 42: * the name of Digital Equipment Corporation not be used in advertising or
! 43: * publicity pertaining to distribution of the document or software without
! 44: * specific, written prior permission.
! 45: *
! 46: * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
! 47: * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
! 48: * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
! 49: * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
! 50: * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
! 51: * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
! 52: * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
! 53: * SOFTWARE.
! 54: */
! 55:
! 56: /*
! 57: * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
! 58: * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
! 59: *
! 60: * Permission to use, copy, modify, and distribute this software for any
! 61: * purpose with or without fee is hereby granted, provided that the above
! 62: * copyright notice and this permission notice appear in all copies.
! 63: *
! 64: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
! 65: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 66: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
! 67: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 68: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 69: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 70: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 71: */
! 72:
! 73: #if defined(LIBC_SCCS) && !defined(lint)
! 74: static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
! 75: static const char rcsid[] = "Id: res_init.c,v 1.26 2008/12/11 09:59:00 marka Exp";
! 76: #endif /* LIBC_SCCS and not lint */
! 77:
! 78: #include "port_before.h"
! 79:
! 80: #include <sys/types.h>
! 81: #include <sys/param.h>
! 82: #include <sys/socket.h>
! 83: #include <sys/time.h>
! 84:
! 85: #include <netinet/in.h>
! 86: #include <arpa/inet.h>
! 87: #include <arpa/nameser.h>
! 88:
! 89: #include <ctype.h>
! 90: #include <stdio.h>
! 91: #include <stdlib.h>
! 92: #include <string.h>
! 93: #include <unistd.h>
! 94: #include <netdb.h>
! 95:
! 96: #ifndef HAVE_MD5
! 97: # include "../dst/md5.h"
! 98: #else
! 99: # ifdef SOLARIS2
! 100: # include <sys/md5.h>
! 101: # endif
! 102: #endif
! 103: #ifndef _MD5_H_
! 104: # define _MD5_H_ 1 /*%< make sure we do not include rsaref md5.h file */
! 105: #endif
! 106:
! 107: #include "port_after.h"
! 108:
! 109: /* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
! 110: #include <resolv.h>
! 111:
! 112: #include "res_private.h"
! 113:
! 114: /*% Options. Should all be left alone. */
! 115: #define RESOLVSORT
! 116: #define DEBUG
! 117:
! 118: #ifdef SOLARIS2
! 119: #include <sys/systeminfo.h>
! 120: #endif
! 121:
! 122: static void res_setoptions __P((res_state, const char *, const char *));
! 123:
! 124: #ifdef RESOLVSORT
! 125: static const char sort_mask[] = "/&";
! 126: #define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
! 127: static u_int32_t net_mask __P((struct in_addr));
! 128: #endif
! 129:
! 130: #if !defined(isascii) /*%< XXX - could be a function */
! 131: # define isascii(c) (!(c & 0200))
! 132: #endif
! 133:
! 134: /*
! 135: * Resolver state default settings.
! 136: */
! 137:
! 138: /*%
! 139: * Set up default settings. If the configuration file exist, the values
! 140: * there will have precedence. Otherwise, the server address is set to
! 141: * INADDR_ANY and the default domain name comes from the gethostname().
! 142: *
! 143: * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
! 144: * rather than INADDR_ANY ("0.0.0.0") as the default name server address
! 145: * since it was noted that INADDR_ANY actually meant ``the first interface
! 146: * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
! 147: * it had to be "up" in order for you to reach your own name server. It
! 148: * was later decided that since the recommended practice is to always
! 149: * install local static routes through 127.0.0.1 for all your network
! 150: * interfaces, that we could solve this problem without a code change.
! 151: *
! 152: * The configuration file should always be used, since it is the only way
! 153: * to specify a default domain. If you are running a server on your local
! 154: * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
! 155: * in the configuration file.
! 156: *
! 157: * Return 0 if completes successfully, -1 on error
! 158: */
! 159: int
! 160: res_ninit(res_state statp) {
! 161: extern int __res_vinit(res_state, int);
! 162:
! 163: return (__res_vinit(statp, 0));
! 164: }
! 165:
! 166: /*% This function has to be reachable by res_data.c but not publically. */
! 167: int
! 168: __res_vinit(res_state statp, int preinit) {
! 169: register FILE *fp;
! 170: register char *cp, **pp;
! 171: register int n;
! 172: char buf[BUFSIZ];
! 173: int nserv = 0; /*%< number of nameserver records read from file */
! 174: int haveenv = 0;
! 175: int havesearch = 0;
! 176: #ifdef RESOLVSORT
! 177: int nsort = 0;
! 178: char *net;
! 179: #endif
! 180: int dots;
! 181: union res_sockaddr_union u[2];
! 182: int maxns = MAXNS;
! 183:
! 184: RES_SET_H_ERRNO(statp, 0);
! 185: if (statp->_u._ext.ext != NULL)
! 186: res_ndestroy(statp);
! 187:
! 188: if (!preinit) {
! 189: statp->retrans = RES_TIMEOUT;
! 190: statp->retry = RES_DFLRETRY;
! 191: statp->options = RES_DEFAULT;
! 192: res_rndinit(statp);
! 193: statp->id = res_nrandomid(statp);
! 194: }
! 195:
! 196: memset(u, 0, sizeof(u));
! 197: #ifdef USELOOPBACK
! 198: u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
! 199: #else
! 200: u[nserv].sin.sin_addr.s_addr = INADDR_ANY;
! 201: #endif
! 202: u[nserv].sin.sin_family = AF_INET;
! 203: u[nserv].sin.sin_port = htons(NAMESERVER_PORT);
! 204: #ifdef HAVE_SA_LEN
! 205: u[nserv].sin.sin_len = sizeof(struct sockaddr_in);
! 206: #endif
! 207: nserv++;
! 208: #ifdef HAS_INET6_STRUCTS
! 209: #ifdef USELOOPBACK
! 210: u[nserv].sin6.sin6_addr = in6addr_loopback;
! 211: #else
! 212: u[nserv].sin6.sin6_addr = in6addr_any;
! 213: #endif
! 214: u[nserv].sin6.sin6_family = AF_INET6;
! 215: u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT);
! 216: #ifdef HAVE_SA_LEN
! 217: u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6);
! 218: #endif
! 219: nserv++;
! 220: #endif
! 221: statp->nscount = 0;
! 222: statp->ndots = 1;
! 223: statp->pfcode = 0;
! 224: statp->_vcsock = -1;
! 225: statp->_flags = 0;
! 226: statp->qhook = NULL;
! 227: statp->rhook = NULL;
! 228: statp->_u._ext.nscount = 0;
! 229: statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext));
! 230: if (statp->_u._ext.ext != NULL) {
! 231: memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext));
! 232: statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr;
! 233: strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa");
! 234: strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int");
! 235: } else {
! 236: /*
! 237: * Historically res_init() rarely, if at all, failed.
! 238: * Examples and applications exist which do not check
! 239: * our return code. Furthermore several applications
! 240: * simply call us to get the systems domainname. So
! 241: * rather then immediately fail here we store the
! 242: * failure, which is returned later, in h_errno. And
! 243: * prevent the collection of 'nameserver' information
! 244: * by setting maxns to 0. Thus applications that fail
! 245: * to check our return code wont be able to make
! 246: * queries anyhow.
! 247: */
! 248: RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
! 249: maxns = 0;
! 250: }
! 251: #ifdef RESOLVSORT
! 252: statp->nsort = 0;
! 253: #endif
! 254: res_setservers(statp, u, nserv);
! 255:
! 256: #ifdef SOLARIS2
! 257: /*
! 258: * The old libresolv derived the defaultdomain from NIS/NIS+.
! 259: * We want to keep this behaviour
! 260: */
! 261: {
! 262: char buf[sizeof(statp->defdname)], *cp;
! 263: int ret;
! 264:
! 265: if ((ret = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf))) > 0 &&
! 266: (unsigned int)ret <= sizeof(buf)) {
! 267: if (buf[0] == '+')
! 268: buf[0] = '.';
! 269: cp = strchr(buf, '.');
! 270: cp = (cp == NULL) ? buf : (cp + 1);
! 271: strncpy(statp->defdname, cp,
! 272: sizeof(statp->defdname) - 1);
! 273: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
! 274: }
! 275: }
! 276: #endif /* SOLARIS2 */
! 277:
! 278: /* Allow user to override the local domain definition */
! 279: if ((cp = getenv("LOCALDOMAIN")) != NULL) {
! 280: (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
! 281: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
! 282: haveenv++;
! 283:
! 284: /*
! 285: * Set search list to be blank-separated strings
! 286: * from rest of env value. Permits users of LOCALDOMAIN
! 287: * to still have a search list, and anyone to set the
! 288: * one that they want to use as an individual (even more
! 289: * important now that the rfc1535 stuff restricts searches)
! 290: */
! 291: cp = statp->defdname;
! 292: pp = statp->dnsrch;
! 293: *pp++ = cp;
! 294: for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
! 295: if (*cp == '\n') /*%< silly backwards compat */
! 296: break;
! 297: else if (*cp == ' ' || *cp == '\t') {
! 298: *cp = 0;
! 299: n = 1;
! 300: } else if (n) {
! 301: *pp++ = cp;
! 302: n = 0;
! 303: havesearch = 1;
! 304: }
! 305: }
! 306: /* null terminate last domain if there are excess */
! 307: while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
! 308: cp++;
! 309: *cp = '\0';
! 310: *pp++ = 0;
! 311: }
! 312:
! 313: #define MATCH(line, name) \
! 314: (!strncmp(line, name, sizeof(name) - 1) && \
! 315: (line[sizeof(name) - 1] == ' ' || \
! 316: line[sizeof(name) - 1] == '\t'))
! 317:
! 318: nserv = 0;
! 319: if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
! 320: /* read the config file */
! 321: while (fgets(buf, sizeof(buf), fp) != NULL) {
! 322: /* skip comments */
! 323: if (*buf == ';' || *buf == '#')
! 324: continue;
! 325: /* read default domain name */
! 326: if (MATCH(buf, "domain")) {
! 327: if (haveenv) /*%< skip if have from environ */
! 328: continue;
! 329: cp = buf + sizeof("domain") - 1;
! 330: while (*cp == ' ' || *cp == '\t')
! 331: cp++;
! 332: if ((*cp == '\0') || (*cp == '\n'))
! 333: continue;
! 334: strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
! 335: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
! 336: if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
! 337: *cp = '\0';
! 338: havesearch = 0;
! 339: continue;
! 340: }
! 341: /* set search list */
! 342: if (MATCH(buf, "search")) {
! 343: if (haveenv) /*%< skip if have from environ */
! 344: continue;
! 345: cp = buf + sizeof("search") - 1;
! 346: while (*cp == ' ' || *cp == '\t')
! 347: cp++;
! 348: if ((*cp == '\0') || (*cp == '\n'))
! 349: continue;
! 350: strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
! 351: statp->defdname[sizeof(statp->defdname) - 1] = '\0';
! 352: if ((cp = strchr(statp->defdname, '\n')) != NULL)
! 353: *cp = '\0';
! 354: /*
! 355: * Set search list to be blank-separated strings
! 356: * on rest of line.
! 357: */
! 358: cp = statp->defdname;
! 359: pp = statp->dnsrch;
! 360: *pp++ = cp;
! 361: for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
! 362: if (*cp == ' ' || *cp == '\t') {
! 363: *cp = 0;
! 364: n = 1;
! 365: } else if (n) {
! 366: *pp++ = cp;
! 367: n = 0;
! 368: }
! 369: }
! 370: /* null terminate last domain if there are excess */
! 371: while (*cp != '\0' && *cp != ' ' && *cp != '\t')
! 372: cp++;
! 373: *cp = '\0';
! 374: *pp++ = 0;
! 375: havesearch = 1;
! 376: continue;
! 377: }
! 378: /* read nameservers to query */
! 379: if (MATCH(buf, "nameserver") && nserv < maxns) {
! 380: struct addrinfo hints, *ai;
! 381: char sbuf[NI_MAXSERV];
! 382: const size_t minsiz =
! 383: sizeof(statp->_u._ext.ext->nsaddrs[0]);
! 384:
! 385: cp = buf + sizeof("nameserver") - 1;
! 386: while (*cp == ' ' || *cp == '\t')
! 387: cp++;
! 388: cp[strcspn(cp, ";# \t\n")] = '\0';
! 389: if ((*cp != '\0') && (*cp != '\n')) {
! 390: memset(&hints, 0, sizeof(hints));
! 391: hints.ai_family = PF_UNSPEC;
! 392: hints.ai_socktype = SOCK_DGRAM; /*dummy*/
! 393: hints.ai_flags = AI_NUMERICHOST;
! 394: sprintf(sbuf, "%u", NAMESERVER_PORT);
! 395: if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 &&
! 396: ai->ai_addrlen <= minsiz) {
! 397: if (statp->_u._ext.ext != NULL) {
! 398: memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
! 399: ai->ai_addr, ai->ai_addrlen);
! 400: }
! 401: if (ai->ai_addrlen <=
! 402: sizeof(statp->nsaddr_list[nserv])) {
! 403: memcpy(&statp->nsaddr_list[nserv],
! 404: ai->ai_addr, ai->ai_addrlen);
! 405: } else
! 406: statp->nsaddr_list[nserv].sin_family = 0;
! 407: freeaddrinfo(ai);
! 408: nserv++;
! 409: }
! 410: }
! 411: continue;
! 412: }
! 413: #ifdef RESOLVSORT
! 414: if (MATCH(buf, "sortlist")) {
! 415: struct in_addr a;
! 416:
! 417: cp = buf + sizeof("sortlist") - 1;
! 418: while (nsort < MAXRESOLVSORT) {
! 419: while (*cp == ' ' || *cp == '\t')
! 420: cp++;
! 421: if (*cp == '\0' || *cp == '\n' || *cp == ';')
! 422: break;
! 423: net = cp;
! 424: while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
! 425: isascii(*cp) && !isspace((unsigned char)*cp))
! 426: cp++;
! 427: n = *cp;
! 428: *cp = 0;
! 429: if (inet_aton(net, &a)) {
! 430: statp->sort_list[nsort].addr = a;
! 431: if (ISSORTMASK(n)) {
! 432: *cp++ = n;
! 433: net = cp;
! 434: while (*cp && *cp != ';' &&
! 435: isascii(*cp) &&
! 436: !isspace((unsigned char)*cp))
! 437: cp++;
! 438: n = *cp;
! 439: *cp = 0;
! 440: if (inet_aton(net, &a)) {
! 441: statp->sort_list[nsort].mask = a.s_addr;
! 442: } else {
! 443: statp->sort_list[nsort].mask =
! 444: net_mask(statp->sort_list[nsort].addr);
! 445: }
! 446: } else {
! 447: statp->sort_list[nsort].mask =
! 448: net_mask(statp->sort_list[nsort].addr);
! 449: }
! 450: nsort++;
! 451: }
! 452: *cp = n;
! 453: }
! 454: continue;
! 455: }
! 456: #endif
! 457: if (MATCH(buf, "options")) {
! 458: res_setoptions(statp, buf + sizeof("options") - 1, "conf");
! 459: continue;
! 460: }
! 461: }
! 462: if (nserv > 0)
! 463: statp->nscount = nserv;
! 464: #ifdef RESOLVSORT
! 465: statp->nsort = nsort;
! 466: #endif
! 467: (void) fclose(fp);
! 468: }
! 469: /*
! 470: * Last chance to get a nameserver. This should not normally
! 471: * be necessary
! 472: */
! 473: #ifdef NO_RESOLV_CONF
! 474: if(nserv == 0)
! 475: nserv = get_nameservers(statp);
! 476: #endif
! 477:
! 478: if (statp->defdname[0] == 0 &&
! 479: gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
! 480: (cp = strchr(buf, '.')) != NULL)
! 481: strcpy(statp->defdname, cp + 1);
! 482:
! 483: /* find components of local domain that might be searched */
! 484: if (havesearch == 0) {
! 485: pp = statp->dnsrch;
! 486: *pp++ = statp->defdname;
! 487: *pp = NULL;
! 488:
! 489: dots = 0;
! 490: for (cp = statp->defdname; *cp; cp++)
! 491: dots += (*cp == '.');
! 492:
! 493: cp = statp->defdname;
! 494: while (pp < statp->dnsrch + MAXDFLSRCH) {
! 495: if (dots < LOCALDOMAINPARTS)
! 496: break;
! 497: cp = strchr(cp, '.') + 1; /*%< we know there is one */
! 498: *pp++ = cp;
! 499: dots--;
! 500: }
! 501: *pp = NULL;
! 502: #ifdef DEBUG
! 503: if (statp->options & RES_DEBUG) {
! 504: printf(";; res_init()... default dnsrch list:\n");
! 505: for (pp = statp->dnsrch; *pp; pp++)
! 506: printf(";;\t%s\n", *pp);
! 507: printf(";;\t..END..\n");
! 508: }
! 509: #endif
! 510: }
! 511:
! 512: if ((cp = getenv("RES_OPTIONS")) != NULL)
! 513: res_setoptions(statp, cp, "env");
! 514: statp->options |= RES_INIT;
! 515: return (statp->res_h_errno);
! 516: }
! 517:
! 518: static void
! 519: res_setoptions(res_state statp, const char *options, const char *source)
! 520: {
! 521: const char *cp = options;
! 522: int i;
! 523: struct __res_state_ext *ext = statp->_u._ext.ext;
! 524:
! 525: #ifdef DEBUG
! 526: if (statp->options & RES_DEBUG)
! 527: printf(";; res_setoptions(\"%s\", \"%s\")...\n",
! 528: options, source);
! 529: #endif
! 530: while (*cp) {
! 531: /* skip leading and inner runs of spaces */
! 532: while (*cp == ' ' || *cp == '\t')
! 533: cp++;
! 534: /* search for and process individual options */
! 535: if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
! 536: i = atoi(cp + sizeof("ndots:") - 1);
! 537: if (i <= RES_MAXNDOTS)
! 538: statp->ndots = i;
! 539: else
! 540: statp->ndots = RES_MAXNDOTS;
! 541: #ifdef DEBUG
! 542: if (statp->options & RES_DEBUG)
! 543: printf(";;\tndots=%d\n", statp->ndots);
! 544: #endif
! 545: } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
! 546: i = atoi(cp + sizeof("timeout:") - 1);
! 547: if (i <= RES_MAXRETRANS)
! 548: statp->retrans = i;
! 549: else
! 550: statp->retrans = RES_MAXRETRANS;
! 551: #ifdef DEBUG
! 552: if (statp->options & RES_DEBUG)
! 553: printf(";;\ttimeout=%d\n", statp->retrans);
! 554: #endif
! 555: #ifdef SOLARIS2
! 556: } else if (!strncmp(cp, "retrans:", sizeof("retrans:") - 1)) {
! 557: /*
! 558: * For backward compatibility, 'retrans' is
! 559: * supported as an alias for 'timeout', though
! 560: * without an imposed maximum.
! 561: */
! 562: statp->retrans = atoi(cp + sizeof("retrans:") - 1);
! 563: } else if (!strncmp(cp, "retry:", sizeof("retry:") - 1)){
! 564: /*
! 565: * For backward compatibility, 'retry' is
! 566: * supported as an alias for 'attempts', though
! 567: * without an imposed maximum.
! 568: */
! 569: statp->retry = atoi(cp + sizeof("retry:") - 1);
! 570: #endif /* SOLARIS2 */
! 571: } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
! 572: i = atoi(cp + sizeof("attempts:") - 1);
! 573: if (i <= RES_MAXRETRY)
! 574: statp->retry = i;
! 575: else
! 576: statp->retry = RES_MAXRETRY;
! 577: #ifdef DEBUG
! 578: if (statp->options & RES_DEBUG)
! 579: printf(";;\tattempts=%d\n", statp->retry);
! 580: #endif
! 581: } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
! 582: #ifdef DEBUG
! 583: if (!(statp->options & RES_DEBUG)) {
! 584: printf(";; res_setoptions(\"%s\", \"%s\")..\n",
! 585: options, source);
! 586: statp->options |= RES_DEBUG;
! 587: }
! 588: printf(";;\tdebug\n");
! 589: #endif
! 590: } else if (!strncmp(cp, "no_tld_query",
! 591: sizeof("no_tld_query") - 1) ||
! 592: !strncmp(cp, "no-tld-query",
! 593: sizeof("no-tld-query") - 1)) {
! 594: statp->options |= RES_NOTLDQUERY;
! 595: } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
! 596: statp->options |= RES_USE_INET6;
! 597: } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
! 598: statp->options |= RES_ROTATE;
! 599: } else if (!strncmp(cp, "no-check-names",
! 600: sizeof("no-check-names") - 1)) {
! 601: statp->options |= RES_NOCHECKNAME;
! 602: }
! 603: #ifdef RES_USE_EDNS0
! 604: else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
! 605: statp->options |= RES_USE_EDNS0;
! 606: }
! 607: #endif
! 608: else if (!strncmp(cp, "dname", sizeof("dname") - 1)) {
! 609: statp->options |= RES_USE_DNAME;
! 610: }
! 611: else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) {
! 612: if (ext == NULL)
! 613: goto skip;
! 614: cp += sizeof("nibble:") - 1;
! 615: i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1);
! 616: strncpy(ext->nsuffix, cp, i);
! 617: ext->nsuffix[i] = '\0';
! 618: }
! 619: else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) {
! 620: if (ext == NULL)
! 621: goto skip;
! 622: cp += sizeof("nibble2:") - 1;
! 623: i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1);
! 624: strncpy(ext->nsuffix2, cp, i);
! 625: ext->nsuffix2[i] = '\0';
! 626: }
! 627: else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) {
! 628: cp += sizeof("v6revmode:") - 1;
! 629: /* "nibble" and "bitstring" used to be valid */
! 630: if (!strncmp(cp, "single", sizeof("single") - 1)) {
! 631: statp->options |= RES_NO_NIBBLE2;
! 632: } else if (!strncmp(cp, "both", sizeof("both") - 1)) {
! 633: statp->options &=
! 634: ~RES_NO_NIBBLE2;
! 635: }
! 636: }
! 637: else {
! 638: /* XXX - print a warning here? */
! 639: }
! 640: skip:
! 641: /* skip to next run of spaces */
! 642: while (*cp && *cp != ' ' && *cp != '\t')
! 643: cp++;
! 644: }
! 645: }
! 646:
! 647: #ifdef RESOLVSORT
! 648: /* XXX - should really support CIDR which means explicit masks always. */
! 649: static u_int32_t
! 650: net_mask(in) /*!< XXX - should really use system's version of this */
! 651: struct in_addr in;
! 652: {
! 653: register u_int32_t i = ntohl(in.s_addr);
! 654:
! 655: if (IN_CLASSA(i))
! 656: return (htonl(IN_CLASSA_NET));
! 657: else if (IN_CLASSB(i))
! 658: return (htonl(IN_CLASSB_NET));
! 659: return (htonl(IN_CLASSC_NET));
! 660: }
! 661: #endif
! 662:
! 663: void
! 664: res_rndinit(res_state statp)
! 665: {
! 666: struct timeval now;
! 667: u_int32_t u32;
! 668: u_int16_t u16;
! 669:
! 670: gettimeofday(&now, NULL);
! 671: u32 = now.tv_sec;
! 672: memcpy(statp->_rnd, &u32, 4);
! 673: u32 = now.tv_usec;
! 674: memcpy(statp->_rnd + 4, &u32, 4);
! 675: u32 += now.tv_sec;
! 676: memcpy(statp->_rnd + 8, &u32, 4);
! 677: u16 = getpid();
! 678: memcpy(statp->_rnd + 12, &u16, 2);
! 679: }
! 680:
! 681: u_int
! 682: res_nrandomid(res_state statp) {
! 683: struct timeval now;
! 684: u_int16_t u16;
! 685: MD5_CTX ctx;
! 686:
! 687: gettimeofday(&now, NULL);
! 688: u16 = (u_int16_t) (now.tv_sec ^ now.tv_usec);
! 689: memcpy(statp->_rnd + 14, &u16, 2);
! 690: #ifndef HAVE_MD5
! 691: MD5_Init(&ctx);
! 692: MD5_Update(&ctx, statp->_rnd, 16);
! 693: MD5_Final(statp->_rnd, &ctx);
! 694: #else
! 695: MD5Init(&ctx);
! 696: MD5Update(&ctx, statp->_rnd, 16);
! 697: MD5Final(statp->_rnd, &ctx);
! 698: #endif
! 699: memcpy(&u16, statp->_rnd + 14, 2);
! 700: return ((u_int) u16);
! 701: }
! 702:
! 703: /*%
! 704: * This routine is for closing the socket if a virtual circuit is used and
! 705: * the program wants to close it. This provides support for endhostent()
! 706: * which expects to close the socket.
! 707: *
! 708: * This routine is not expected to be user visible.
! 709: */
! 710: void
! 711: res_nclose(res_state statp) {
! 712: int ns;
! 713:
! 714: if (statp->_vcsock >= 0) {
! 715: (void) close(statp->_vcsock);
! 716: statp->_vcsock = -1;
! 717: statp->_flags &= ~(RES_F_VC | RES_F_CONN);
! 718: }
! 719: for (ns = 0; ns < statp->_u._ext.nscount; ns++) {
! 720: if (statp->_u._ext.nssocks[ns] != -1) {
! 721: (void) close(statp->_u._ext.nssocks[ns]);
! 722: statp->_u._ext.nssocks[ns] = -1;
! 723: }
! 724: }
! 725: }
! 726:
! 727: void
! 728: res_ndestroy(res_state statp) {
! 729: res_nclose(statp);
! 730: if (statp->_u._ext.ext != NULL)
! 731: free(statp->_u._ext.ext);
! 732: statp->options &= ~RES_INIT;
! 733: statp->_u._ext.ext = NULL;
! 734: }
! 735:
! 736: const char *
! 737: res_get_nibblesuffix(res_state statp) {
! 738: if (statp->_u._ext.ext)
! 739: return (statp->_u._ext.ext->nsuffix);
! 740: return ("ip6.arpa");
! 741: }
! 742:
! 743: const char *
! 744: res_get_nibblesuffix2(res_state statp) {
! 745: if (statp->_u._ext.ext)
! 746: return (statp->_u._ext.ext->nsuffix2);
! 747: return ("ip6.int");
! 748: }
! 749:
! 750: void
! 751: res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) {
! 752: int i, nserv;
! 753: size_t size;
! 754:
! 755: /* close open servers */
! 756: res_nclose(statp);
! 757:
! 758: /* cause rtt times to be forgotten */
! 759: statp->_u._ext.nscount = 0;
! 760:
! 761: nserv = 0;
! 762: for (i = 0; i < cnt && nserv < MAXNS; i++) {
! 763: switch (set->sin.sin_family) {
! 764: case AF_INET:
! 765: size = sizeof(set->sin);
! 766: if (statp->_u._ext.ext)
! 767: memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
! 768: &set->sin, size);
! 769: if (size <= sizeof(statp->nsaddr_list[nserv]))
! 770: memcpy(&statp->nsaddr_list[nserv],
! 771: &set->sin, size);
! 772: else
! 773: statp->nsaddr_list[nserv].sin_family = 0;
! 774: nserv++;
! 775: break;
! 776:
! 777: #ifdef HAS_INET6_STRUCTS
! 778: case AF_INET6:
! 779: size = sizeof(set->sin6);
! 780: if (statp->_u._ext.ext)
! 781: memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
! 782: &set->sin6, size);
! 783: if (size <= sizeof(statp->nsaddr_list[nserv]))
! 784: memcpy(&statp->nsaddr_list[nserv],
! 785: &set->sin6, size);
! 786: else
! 787: statp->nsaddr_list[nserv].sin_family = 0;
! 788: nserv++;
! 789: break;
! 790: #endif
! 791:
! 792: default:
! 793: break;
! 794: }
! 795: set++;
! 796: }
! 797: statp->nscount = nserv;
! 798:
! 799: }
! 800:
! 801: int
! 802: res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) {
! 803: int i;
! 804: size_t size;
! 805: u_int16_t family;
! 806:
! 807: for (i = 0; i < statp->nscount && i < cnt; i++) {
! 808: if (statp->_u._ext.ext)
! 809: family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family;
! 810: else
! 811: family = statp->nsaddr_list[i].sin_family;
! 812:
! 813: switch (family) {
! 814: case AF_INET:
! 815: size = sizeof(set->sin);
! 816: if (statp->_u._ext.ext)
! 817: memcpy(&set->sin,
! 818: &statp->_u._ext.ext->nsaddrs[i],
! 819: size);
! 820: else
! 821: memcpy(&set->sin, &statp->nsaddr_list[i],
! 822: size);
! 823: break;
! 824:
! 825: #ifdef HAS_INET6_STRUCTS
! 826: case AF_INET6:
! 827: size = sizeof(set->sin6);
! 828: if (statp->_u._ext.ext)
! 829: memcpy(&set->sin6,
! 830: &statp->_u._ext.ext->nsaddrs[i],
! 831: size);
! 832: else
! 833: memcpy(&set->sin6, &statp->nsaddr_list[i],
! 834: size);
! 835: break;
! 836: #endif
! 837:
! 838: default:
! 839: set->sin.sin_family = 0;
! 840: break;
! 841: }
! 842: set++;
! 843: }
! 844: return (statp->nscount);
! 845: }
! 846:
! 847: /*! \file */
CVSweb <webmaster@jp.NetBSD.org>