Back to index

glibc  2.9
res_init.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1985, 1989, 1993
00003  *    The Regents of the University of California.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 4. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
00032  *
00033  * Permission to use, copy, modify, and distribute this software for any
00034  * purpose with or without fee is hereby granted, provided that the above
00035  * copyright notice and this permission notice appear in all copies, and that
00036  * the name of Digital Equipment Corporation not be used in advertising or
00037  * publicity pertaining to distribution of the document or software without
00038  * specific, written prior permission.
00039  *
00040  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
00041  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
00042  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
00043  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
00044  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00045  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00046  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00047  * SOFTWARE.
00048  */
00049 
00050 /*
00051  * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
00052  *
00053  * Permission to use, copy, modify, and distribute this software for any
00054  * purpose with or without fee is hereby granted, provided that the above
00055  * copyright notice and this permission notice appear in all copies.
00056  *
00057  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
00058  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
00059  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
00060  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
00061  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00062  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00063  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00064  * SOFTWARE.
00065  */
00066 
00067 #if defined(LIBC_SCCS) && !defined(lint)
00068 static const char sccsid[] = "@(#)res_init.c     8.1 (Berkeley) 6/7/93";
00069 static const char rcsid[] = "$BINDId: res_init.c,v 8.16 2000/05/09 07:10:12 vixie Exp $";
00070 #endif /* LIBC_SCCS and not lint */
00071 
00072 #include <ctype.h>
00073 #include <netdb.h>
00074 #include <resolv.h>
00075 #include <stdio.h>
00076 #include <stdio_ext.h>
00077 #include <stdlib.h>
00078 #include <string.h>
00079 #include <unistd.h>
00080 #include <arpa/inet.h>
00081 #include <arpa/nameser.h>
00082 #include <net/if.h>
00083 #include <netinet/in.h>
00084 #include <sys/param.h>
00085 #include <sys/socket.h>
00086 #include <sys/time.h>
00087 #include <sys/types.h>
00088 
00089 #include <not-cancel.h>
00090 
00091 /* Options.  Should all be left alone. */
00092 #define RESOLVSORT
00093 #define RFC1535
00094 /* #undef DEBUG */
00095 
00096 static void res_setoptions (res_state, const char *, const char *)
00097      internal_function;
00098 
00099 #ifdef RESOLVSORT
00100 static const char sort_mask_chars[] = "/&";
00101 #define ISSORTMASK(ch) (strchr(sort_mask_chars, ch) != NULL)
00102 static u_int32_t net_mask (struct in_addr) __THROW;
00103 #endif
00104 
00105 #if !defined(isascii)       /* XXX - could be a function */
00106 # define isascii(c) (!(c & 0200))
00107 #endif
00108 
00109 #ifdef _LIBC
00110 unsigned long long int __res_initstamp attribute_hidden;
00111 #endif
00112 
00113 /*
00114  * Resolver state default settings.
00115  */
00116 
00117 /*
00118  * Set up default settings.  If the configuration file exist, the values
00119  * there will have precedence.  Otherwise, the server address is set to
00120  * INADDR_ANY and the default domain name comes from the gethostname().
00121  *
00122  * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
00123  * rather than INADDR_ANY ("0.0.0.0") as the default name server address
00124  * since it was noted that INADDR_ANY actually meant ``the first interface
00125  * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
00126  * it had to be "up" in order for you to reach your own name server.  It
00127  * was later decided that since the recommended practice is to always
00128  * install local static routes through 127.0.0.1 for all your network
00129  * interfaces, that we could solve this problem without a code change.
00130  *
00131  * The configuration file should always be used, since it is the only way
00132  * to specify a default domain.  If you are running a server on your local
00133  * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
00134  * in the configuration file.
00135  *
00136  * Return 0 if completes successfully, -1 on error
00137  */
00138 int
00139 res_ninit(res_state statp) {
00140        extern int __res_vinit(res_state, int);
00141 
00142        return (__res_vinit(statp, 0));
00143 }
00144 #ifdef _LIBC
00145 libc_hidden_def (__res_ninit)
00146 #endif
00147 
00148 /* This function has to be reachable by res_data.c but not publically. */
00149 int
00150 __res_vinit(res_state statp, int preinit) {
00151        register FILE *fp;
00152        register char *cp, **pp;
00153        register int n;
00154        char buf[BUFSIZ];
00155        int nserv = 0;    /* number of nameserver records read from file */
00156 #ifdef _LIBC
00157        int nservall = 0; /* number of NS records read, nserv IPv4 only */
00158 #endif
00159        int haveenv = 0;
00160        int havesearch = 0;
00161 #ifdef RESOLVSORT
00162        int nsort = 0;
00163        char *net;
00164 #endif
00165 #ifndef RFC1535
00166        int dots;
00167 #endif
00168 #ifdef _LIBC
00169        statp->_u._ext.initstamp = __res_initstamp;
00170 #endif
00171 
00172        if (!preinit) {
00173               statp->retrans = RES_TIMEOUT;
00174               statp->retry = RES_DFLRETRY;
00175               statp->options = RES_DEFAULT;
00176               statp->id = res_randomid();
00177        }
00178 
00179 #ifdef USELOOPBACK
00180        statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
00181 #else
00182        statp->nsaddr.sin_addr.s_addr = INADDR_ANY;
00183 #endif
00184        statp->nsaddr.sin_family = AF_INET;
00185        statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
00186        statp->nscount = 1;
00187        statp->ndots = 1;
00188        statp->pfcode = 0;
00189        statp->_vcsock = -1;
00190        statp->_flags = 0;
00191        statp->qhook = NULL;
00192        statp->rhook = NULL;
00193        statp->_u._ext.nsinit = 0;
00194        statp->_u._ext.nscount = 0;
00195 #ifdef _LIBC
00196        statp->_u._ext.nscount6 = 0;
00197        for (n = 0; n < MAXNS; n++) {
00198               statp->_u._ext.nsaddrs[n] = NULL;
00199               statp->_u._ext.nsmap[n] = MAXNS;
00200        }
00201 #endif
00202 
00203        /* Allow user to override the local domain definition */
00204        if ((cp = getenv("LOCALDOMAIN")) != NULL) {
00205               (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
00206               statp->defdname[sizeof(statp->defdname) - 1] = '\0';
00207               haveenv++;
00208 
00209               /*
00210                * Set search list to be blank-separated strings
00211                * from rest of env value.  Permits users of LOCALDOMAIN
00212                * to still have a search list, and anyone to set the
00213                * one that they want to use as an individual (even more
00214                * important now that the rfc1535 stuff restricts searches)
00215                */
00216               cp = statp->defdname;
00217               pp = statp->dnsrch;
00218               *pp++ = cp;
00219               for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
00220                      if (*cp == '\n')     /* silly backwards compat */
00221                             break;
00222                      else if (*cp == ' ' || *cp == '\t') {
00223                             *cp = 0;
00224                             n = 1;
00225                      } else if (n) {
00226                             *pp++ = cp;
00227                             n = 0;
00228                             havesearch = 1;
00229                      }
00230               }
00231               /* null terminate last domain if there are excess */
00232               while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
00233                      cp++;
00234               *cp = '\0';
00235               *pp++ = 0;
00236        }
00237 
00238 #define       MATCH(line, name) \
00239        (!strncmp(line, name, sizeof(name) - 1) && \
00240        (line[sizeof(name) - 1] == ' ' || \
00241         line[sizeof(name) - 1] == '\t'))
00242 
00243        if ((fp = fopen(_PATH_RESCONF, "rc")) != NULL) {
00244            /* No threads use this stream.  */
00245            __fsetlocking (fp, FSETLOCKING_BYCALLER);
00246            /* read the config file */
00247            while (fgets_unlocked(buf, sizeof(buf), fp) != NULL) {
00248               /* skip comments */
00249               if (*buf == ';' || *buf == '#')
00250                      continue;
00251               /* read default domain name */
00252               if (MATCH(buf, "domain")) {
00253                   if (haveenv)     /* skip if have from environ */
00254                          continue;
00255                   cp = buf + sizeof("domain") - 1;
00256                   while (*cp == ' ' || *cp == '\t')
00257                          cp++;
00258                   if ((*cp == '\0') || (*cp == '\n'))
00259                          continue;
00260                   strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
00261                   statp->defdname[sizeof(statp->defdname) - 1] = '\0';
00262                   if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
00263                          *cp = '\0';
00264                   havesearch = 0;
00265                   continue;
00266               }
00267               /* set search list */
00268               if (MATCH(buf, "search")) {
00269                   if (haveenv)     /* skip if have from environ */
00270                          continue;
00271                   cp = buf + sizeof("search") - 1;
00272                   while (*cp == ' ' || *cp == '\t')
00273                          cp++;
00274                   if ((*cp == '\0') || (*cp == '\n'))
00275                          continue;
00276                   strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
00277                   statp->defdname[sizeof(statp->defdname) - 1] = '\0';
00278                   if ((cp = strchr(statp->defdname, '\n')) != NULL)
00279                          *cp = '\0';
00280                   /*
00281                    * Set search list to be blank-separated strings
00282                    * on rest of line.
00283                    */
00284                   cp = statp->defdname;
00285                   pp = statp->dnsrch;
00286                   *pp++ = cp;
00287                   for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
00288                          if (*cp == ' ' || *cp == '\t') {
00289                                 *cp = 0;
00290                                 n = 1;
00291                          } else if (n) {
00292                                 *pp++ = cp;
00293                                 n = 0;
00294                          }
00295                   }
00296                   /* null terminate last domain if there are excess */
00297                   while (*cp != '\0' && *cp != ' ' && *cp != '\t')
00298                          cp++;
00299                   *cp = '\0';
00300                   *pp++ = 0;
00301                   havesearch = 1;
00302                   continue;
00303               }
00304               /* read nameservers to query */
00305 #ifdef _LIBC
00306               if (MATCH(buf, "nameserver") && nservall < MAXNS) {
00307 #else
00308               if (MATCH(buf, "nameserver") && nserv < MAXNS) {
00309 #endif
00310                   struct in_addr a;
00311 
00312                   cp = buf + sizeof("nameserver") - 1;
00313                   while (*cp == ' ' || *cp == '\t')
00314                      cp++;
00315                   if ((*cp != '\0') && (*cp != '\n')
00316                      && __inet_aton(cp, &a)) {
00317                      statp->nsaddr_list[nserv].sin_addr = a;
00318                      statp->nsaddr_list[nserv].sin_family = AF_INET;
00319                      statp->nsaddr_list[nserv].sin_port =
00320                             htons(NAMESERVER_PORT);
00321                      nserv++;
00322 #ifdef _LIBC
00323                      nservall++;
00324                     } else {
00325                         struct in6_addr a6;
00326                         char *el;
00327 
00328                         if ((el = strchr(cp, '\n')) != NULL)
00329                             *el = '\0';
00330                      if ((el = strchr(cp, SCOPE_DELIMITER)) != NULL)
00331                          *el = '\0';
00332                         if ((*cp != '\0') &&
00333                             (inet_pton(AF_INET6, cp, &a6) > 0)) {
00334                             struct sockaddr_in6 *sa6;
00335 
00336                             sa6 = malloc(sizeof(*sa6));
00337                             if (sa6 != NULL) {
00338                                 sa6->sin6_family = AF_INET6;
00339                                 sa6->sin6_port = htons(NAMESERVER_PORT);
00340                             sa6->sin6_flowinfo = 0;
00341                                 sa6->sin6_addr = a6;
00342 
00343                             if (__builtin_expect (el == NULL, 1))
00344                                 sa6->sin6_scope_id = 0;
00345                             else {
00346                                 int try_numericscope = 1;
00347                                 if (IN6_IS_ADDR_LINKLOCAL (&a6)
00348                                    || IN6_IS_ADDR_MC_LINKLOCAL (&a6)) {
00349                                    sa6->sin6_scope_id
00350                                      = if_nametoindex (el + 1);
00351                                    if (sa6->sin6_scope_id != 0)
00352                                        try_numericscope = 0;
00353                                 }
00354 
00355                                 if (try_numericscope) {
00356                                    char *end;
00357                                    sa6->sin6_scope_id
00358                                      = (uint32_t) strtoul (el + 1, &end,
00359                                                         10);
00360                                    if (*end != '\0')
00361                                        sa6->sin6_scope_id = 0;
00362                                 }
00363                             }
00364 
00365                             statp->_u._ext.nsaddrs[nservall] = sa6;
00366                             statp->_u._ext.nssocks[nservall] = -1;
00367                             statp->_u._ext.nsmap[nservall] = MAXNS + 1;
00368                                 nservall++;
00369                             }
00370                         }
00371 #endif
00372                   }
00373                   continue;
00374               }
00375 #ifdef RESOLVSORT
00376               if (MATCH(buf, "sortlist")) {
00377                   struct in_addr a;
00378 
00379                   cp = buf + sizeof("sortlist") - 1;
00380                   while (nsort < MAXRESOLVSORT) {
00381                      while (*cp == ' ' || *cp == '\t')
00382                          cp++;
00383                      if (*cp == '\0' || *cp == '\n' || *cp == ';')
00384                          break;
00385                      net = cp;
00386                      while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
00387                             isascii(*cp) && !isspace(*cp))
00388                             cp++;
00389                      n = *cp;
00390                      *cp = 0;
00391                      if (__inet_aton(net, &a)) {
00392                          statp->sort_list[nsort].addr = a;
00393                          if (ISSORTMASK(n)) {
00394                             *cp++ = n;
00395                             net = cp;
00396                             while (*cp && *cp != ';' &&
00397                                    isascii(*cp) && !isspace(*cp))
00398                                 cp++;
00399                             n = *cp;
00400                             *cp = 0;
00401                             if (__inet_aton(net, &a)) {
00402                                 statp->sort_list[nsort].mask = a.s_addr;
00403                             } else {
00404                                 statp->sort_list[nsort].mask =
00405                                    net_mask(statp->sort_list[nsort].addr);
00406                             }
00407                          } else {
00408                             statp->sort_list[nsort].mask =
00409                                 net_mask(statp->sort_list[nsort].addr);
00410                          }
00411                          nsort++;
00412                      }
00413                      *cp = n;
00414                   }
00415                   continue;
00416               }
00417 #endif
00418               if (MATCH(buf, "options")) {
00419                   res_setoptions(statp, buf + sizeof("options") - 1, "conf");
00420                   continue;
00421               }
00422            }
00423            if (nserv > 1)
00424               statp->nscount = nserv;
00425 #ifdef _LIBC
00426            if (nservall - nserv > 0) {
00427               statp->_u._ext.nscount6 = nservall - nserv;
00428               /* We try IPv6 servers again.  */
00429               statp->ipv6_unavail = false;
00430            }
00431 #endif
00432 #ifdef RESOLVSORT
00433            statp->nsort = nsort;
00434 #endif
00435            (void) fclose(fp);
00436        }
00437        if (statp->defdname[0] == 0 &&
00438            __gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
00439            (cp = strchr(buf, '.')) != NULL)
00440               strcpy(statp->defdname, cp + 1);
00441 
00442        /* find components of local domain that might be searched */
00443        if (havesearch == 0) {
00444               pp = statp->dnsrch;
00445               *pp++ = statp->defdname;
00446               *pp = NULL;
00447 
00448 #ifndef RFC1535
00449               dots = 0;
00450               for (cp = statp->defdname; *cp; cp++)
00451                      dots += (*cp == '.');
00452 
00453               cp = statp->defdname;
00454               while (pp < statp->dnsrch + MAXDFLSRCH) {
00455                      if (dots < LOCALDOMAINPARTS)
00456                             break;
00457                      cp = __rawmemchr(cp, '.') + 1;    /* we know there is one */
00458                      *pp++ = cp;
00459                      dots--;
00460               }
00461               *pp = NULL;
00462 #ifdef DEBUG
00463               if (statp->options & RES_DEBUG) {
00464                      printf(";; res_init()... default dnsrch list:\n");
00465                      for (pp = statp->dnsrch; *pp; pp++)
00466                             printf(";;\t%s\n", *pp);
00467                      printf(";;\t..END..\n");
00468               }
00469 #endif
00470 #endif /* !RFC1535 */
00471        }
00472 
00473        if ((cp = getenv("RES_OPTIONS")) != NULL)
00474               res_setoptions(statp, cp, "env");
00475        statp->options |= RES_INIT;
00476        return (0);
00477 }
00478 
00479 static void
00480 internal_function
00481 res_setoptions(res_state statp, const char *options, const char *source) {
00482        const char *cp = options;
00483        int i;
00484 
00485 #ifdef DEBUG
00486        if (statp->options & RES_DEBUG)
00487               printf(";; res_setoptions(\"%s\", \"%s\")...\n",
00488                      options, source);
00489 #endif
00490        while (*cp) {
00491               /* skip leading and inner runs of spaces */
00492               while (*cp == ' ' || *cp == '\t')
00493                      cp++;
00494               /* search for and process individual options */
00495               if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
00496                      i = atoi(cp + sizeof("ndots:") - 1);
00497                      if (i <= RES_MAXNDOTS)
00498                             statp->ndots = i;
00499                      else
00500                             statp->ndots = RES_MAXNDOTS;
00501 #ifdef DEBUG
00502                      if (statp->options & RES_DEBUG)
00503                             printf(";;\tndots=%d\n", statp->ndots);
00504 #endif
00505               } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
00506                      i = atoi(cp + sizeof("timeout:") - 1);
00507                      if (i <= RES_MAXRETRANS)
00508                             statp->retrans = i;
00509                      else
00510                             statp->retrans = RES_MAXRETRANS;
00511               } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
00512                      i = atoi(cp + sizeof("attempts:") - 1);
00513                      if (i <= RES_MAXRETRY)
00514                             statp->retry = i;
00515                      else
00516                             statp->retry = RES_MAXRETRY;
00517               } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
00518 #ifdef DEBUG
00519                      if (!(statp->options & RES_DEBUG)) {
00520                             printf(";; res_setoptions(\"%s\", \"%s\")..\n",
00521                                    options, source);
00522                             statp->options |= RES_DEBUG;
00523                      }
00524                      printf(";;\tdebug\n");
00525 #endif
00526               } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
00527                      statp->options |= RES_USE_INET6;
00528               } else if (!strncmp(cp, "ip6-bytestring",
00529                                 sizeof("ip6-bytestring") - 1)) {
00530                      statp->options |= RES_USEBSTRING;
00531               } else if (!strncmp(cp, "no-ip6-dotint",
00532                                 sizeof("no-ip6-dotint") - 1)) {
00533                      statp->options |= RES_NOIP6DOTINT;
00534               } else if (!strncmp(cp, "ip6-dotint",
00535                                 sizeof("ip6-dotint") - 1)) {
00536                      statp->options &= ~RES_NOIP6DOTINT;
00537               } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
00538                      statp->options |= RES_ROTATE;
00539               } else if (!strncmp(cp, "no-check-names",
00540                                 sizeof("no-check-names") - 1)) {
00541                      statp->options |= RES_NOCHECKNAME;
00542                 } else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
00543                      statp->options |= RES_USE_EDNS0;
00544               } else {
00545                      /* XXX - print a warning here? */
00546               }
00547               /* skip to next run of spaces */
00548               while (*cp && *cp != ' ' && *cp != '\t')
00549                      cp++;
00550        }
00551 }
00552 
00553 #ifdef RESOLVSORT
00554 /* XXX - should really support CIDR which means explicit masks always. */
00555 static u_int32_t
00556 net_mask(in)         /* XXX - should really use system's version of this */
00557        struct in_addr in;
00558 {
00559        register u_int32_t i = ntohl(in.s_addr);
00560 
00561        if (IN_CLASSA(i))
00562               return (htonl(IN_CLASSA_NET));
00563        else if (IN_CLASSB(i))
00564               return (htonl(IN_CLASSB_NET));
00565        return (htonl(IN_CLASSC_NET));
00566 }
00567 #endif
00568 
00569 u_int
00570 res_randomid(void) {
00571        return 0xffff & __getpid();
00572 }
00573 #ifdef _LIBC
00574 libc_hidden_def (__res_randomid)
00575 #endif
00576 
00577 
00578 /*
00579  * This routine is for closing the socket if a virtual circuit is used and
00580  * the program wants to close it.  This provides support for endhostent()
00581  * which expects to close the socket.
00582  *
00583  * This routine is not expected to be user visible.
00584  */
00585 void
00586 __res_iclose(res_state statp, bool free_addr) {
00587        int ns;
00588 
00589        if (statp->_vcsock >= 0) {
00590               close_not_cancel_no_status(statp->_vcsock);
00591               statp->_vcsock = -1;
00592               statp->_flags &= ~(RES_F_VC | RES_F_CONN);
00593        }
00594 #ifdef _LIBC
00595        for (ns = 0; ns < MAXNS; ns++)
00596 #else
00597        for (ns = 0; ns < statp->_u._ext.nscount; ns++)
00598 #endif
00599               if (statp->_u._ext.nsaddrs[ns]) {
00600                      if (statp->_u._ext.nssocks[ns] != -1) {
00601                             close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
00602                             statp->_u._ext.nssocks[ns] = -1;
00603                      }
00604                      if (free_addr) {
00605                             free (statp->_u._ext.nsaddrs[ns]);
00606                             statp->_u._ext.nsaddrs[ns] = NULL;
00607                      }
00608               }
00609        statp->_u._ext.nsinit = 0;
00610 }
00611 libc_hidden_def (__res_iclose)
00612 
00613 void
00614 res_nclose(res_state statp)
00615 {
00616   __res_iclose (statp, true);
00617 }
00618 #ifdef _LIBC
00619 libc_hidden_def (__res_nclose)
00620 #endif
00621 
00622 #ifdef _LIBC
00623 # ifdef _LIBC_REENTRANT
00624 /* This is called when a thread is exiting to free resources held in _res.  */
00625 static void __attribute__ ((section ("__libc_thread_freeres_fn")))
00626 res_thread_freeres (void)
00627 {
00628   if (_res.nscount == 0)
00629     /* Never called res_ninit.  */
00630     return;
00631 
00632   __res_iclose (&_res, true);             /* Close any VC sockets.  */
00633 
00634   /* Make sure we do a full re-initialization the next time.  */
00635   _res.options = 0;
00636 }
00637 text_set_element (__libc_thread_subfreeres, res_thread_freeres);
00638 text_set_element (__libc_subfreeres, res_thread_freeres);
00639 # endif
00640 #endif