(linenum→info "unix/slp.c:2238")

glibc/2.7/resolv/res_init.c

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