Blame resolv/res_init.c

Packit Service 82fcde
/* Resolver state initialization and resolv.conf parsing.
Packit Service 82fcde
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Copyright (c) 1985, 1989, 1993
Packit Service 82fcde
 *    The Regents of the University of California.  All rights reserved.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Redistribution and use in source and binary forms, with or without
Packit Service 82fcde
 * modification, are permitted provided that the following conditions
Packit Service 82fcde
 * are met:
Packit Service 82fcde
 * 1. Redistributions of source code must retain the above copyright
Packit Service 82fcde
 *    notice, this list of conditions and the following disclaimer.
Packit Service 82fcde
 * 2. Redistributions in binary form must reproduce the above copyright
Packit Service 82fcde
 *    notice, this list of conditions and the following disclaimer in the
Packit Service 82fcde
 *    documentation and/or other materials provided with the distribution.
Packit Service 82fcde
 * 4. Neither the name of the University nor the names of its contributors
Packit Service 82fcde
 *    may be used to endorse or promote products derived from this software
Packit Service 82fcde
 *    without specific prior written permission.
Packit Service 82fcde
 *
Packit Service 82fcde
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
Packit Service 82fcde
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit Service 82fcde
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit Service 82fcde
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
Packit Service 82fcde
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit Service 82fcde
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit Service 82fcde
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit Service 82fcde
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit Service 82fcde
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit Service 82fcde
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit Service 82fcde
 * SUCH DAMAGE.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Portions Copyright (c) 1993 by Digital Equipment Corporation.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Permission to use, copy, modify, and distribute this software for any
Packit Service 82fcde
 * purpose with or without fee is hereby granted, provided that the above
Packit Service 82fcde
 * copyright notice and this permission notice appear in all copies, and that
Packit Service 82fcde
 * the name of Digital Equipment Corporation not be used in advertising or
Packit Service 82fcde
 * publicity pertaining to distribution of the document or software without
Packit Service 82fcde
 * specific, written prior permission.
Packit Service 82fcde
 *
Packit Service 82fcde
 * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
Packit Service 82fcde
 * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
Packit Service 82fcde
 * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
Packit Service 82fcde
 * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
Packit Service 82fcde
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
Packit Service 82fcde
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
Packit Service 82fcde
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit Service 82fcde
 * SOFTWARE.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Permission to use, copy, modify, and distribute this software for any
Packit Service 82fcde
 * purpose with or without fee is hereby granted, provided that the above
Packit Service 82fcde
 * copyright notice and this permission notice appear in all copies.
Packit Service 82fcde
 *
Packit Service 82fcde
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
Packit Service 82fcde
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
Packit Service 82fcde
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
Packit Service 82fcde
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
Packit Service 82fcde
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
Packit Service 82fcde
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
Packit Service 82fcde
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
Packit Service 82fcde
 * SOFTWARE.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
#include <ctype.h>
Packit Service 82fcde
#include <netdb.h>
Packit Service 82fcde
#include <resolv/resolv-internal.h>
Packit Service 82fcde
#include <res_hconf.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdio_ext.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <arpa/inet.h>
Packit Service 82fcde
#include <arpa/nameser.h>
Packit Service 82fcde
#include <net/if.h>
Packit Service 82fcde
#include <netinet/in.h>
Packit Service 82fcde
#include <sys/param.h>
Packit Service 82fcde
#include <sys/socket.h>
Packit Service 82fcde
#include <sys/time.h>
Packit Service 82fcde
#include <sys/types.h>
Packit Service 82fcde
#include <inet/net-internal.h>
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <resolv_conf.h>
Packit Service 82fcde
Packit Service 82fcde
static uint32_t net_mask (struct in_addr);
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
res_ninit (res_state statp)
Packit Service 82fcde
{
Packit Service 82fcde
  return __res_vinit (statp, 0);
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (__res_ninit)
Packit Service 82fcde
Packit Service 82fcde
/* Return true if CH separates the netmask in the "sortlist"
Packit Service 82fcde
   directive.  */
Packit Service 82fcde
static inline bool
Packit Service 82fcde
is_sort_mask (char ch)
Packit Service 82fcde
{
Packit Service 82fcde
  return ch == '/' || ch == '&';
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Array of name server addresses.  */
Packit Service 82fcde
#define DYNARRAY_STRUCT nameserver_list
Packit Service 82fcde
#define DYNARRAY_ELEMENT const struct sockaddr *
Packit Service 82fcde
#define DYNARRAY_ELEMENT_FREE(e) free ((struct sockaddr *) *(e))
Packit Service 82fcde
#define DYNARRAY_INITIAL_SIZE 3
Packit Service 82fcde
#define DYNARRAY_PREFIX nameserver_list_
Packit Service 82fcde
#include <malloc/dynarray-skeleton.c>
Packit Service 82fcde
Packit Service 82fcde
/* Array of strings for the search array.  The backing store is
Packit Service 82fcde
   managed separately.  */
Packit Service 82fcde
#define DYNARRAY_STRUCT search_list
Packit Service 82fcde
#define DYNARRAY_ELEMENT const char *
Packit Service 82fcde
#define DYNARRAY_INITIAL_SIZE 6
Packit Service 82fcde
#define DYNARRAY_PREFIX search_list_
Packit Service 82fcde
#include <malloc/dynarray-skeleton.c>
Packit Service 82fcde
Packit Service 82fcde
/* Array of name server addresses.  */
Packit Service 82fcde
#define DYNARRAY_STRUCT sort_list
Packit Service 82fcde
#define DYNARRAY_ELEMENT struct resolv_sortlist_entry
Packit Service 82fcde
#define DYNARRAY_INITIAL_SIZE 0
Packit Service 82fcde
#define DYNARRAY_PREFIX sort_list_
Packit Service 82fcde
#include <malloc/dynarray-skeleton.c>
Packit Service 82fcde
Packit Service 82fcde
/* resolv.conf parser state and results.  */
Packit Service 82fcde
struct resolv_conf_parser
Packit Service 82fcde
{
Packit Service 82fcde
  char *buffer;            /* Temporary buffer for reading lines.  */
Packit Service 82fcde
Packit Service 82fcde
  struct nameserver_list nameserver_list; /* Nameserver addresses.  */
Packit Service 82fcde
Packit Service 82fcde
  char *search_list_store; /* Backing storage for search list entries.  */
Packit Service 82fcde
  struct search_list search_list; /* Points into search_list_store.  */
Packit Service 82fcde
Packit Service 82fcde
  struct sort_list sort_list;   /* Address preference sorting list.  */
Packit Service 82fcde
Packit Service 82fcde
  /* Configuration template.  The non-array elements are filled in
Packit Service 82fcde
     directly.  The array elements are updated prior to the call to
Packit Service 82fcde
     __resolv_conf_attach.  */
Packit Service 82fcde
  struct resolv_conf template;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* Return true if *PREINIT contains actual preinitialization.  */
Packit Service 82fcde
static bool
Packit Service 82fcde
has_preinit_values (const struct __res_state *preinit)
Packit Service 82fcde
{
Packit Service 82fcde
  return (preinit->retrans != 0 && preinit->retrans != RES_TIMEOUT)
Packit Service 82fcde
    || (preinit->retry != 0 && preinit->retry != RES_DFLRETRY)
Packit Service 82fcde
    || (preinit->options != 0
Packit Service 82fcde
        && (preinit->options & ~RES_INIT) != RES_DEFAULT);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
resolv_conf_parser_init (struct resolv_conf_parser *parser,
Packit Service 82fcde
                         const struct __res_state *preinit)
Packit Service 82fcde
{
Packit Service 82fcde
  parser->buffer = NULL;
Packit Service 82fcde
  parser->search_list_store = NULL;
Packit Service 82fcde
  nameserver_list_init (&parser->nameserver_list);
Packit Service 82fcde
  search_list_init (&parser->search_list);
Packit Service 82fcde
  sort_list_init (&parser->sort_list);
Packit Service 82fcde
Packit Service 82fcde
  if (preinit != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      parser->template.retrans = preinit->retrans;
Packit Service 82fcde
      parser->template.retry = preinit->retry;
Packit Service 82fcde
      parser->template.options = preinit->options | RES_INIT;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      parser->template.retrans = RES_TIMEOUT;
Packit Service 82fcde
      parser->template.retry = RES_DFLRETRY;
Packit Service 82fcde
      parser->template.options = RES_DEFAULT | RES_INIT;
Packit Service 82fcde
    }
Packit Service 82fcde
  parser->template.ndots = 1;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
resolv_conf_parser_free (struct resolv_conf_parser *parser)
Packit Service 82fcde
{
Packit Service 82fcde
  free (parser->buffer);
Packit Service 82fcde
  free (parser->search_list_store);
Packit Service 82fcde
  nameserver_list_free (&parser->nameserver_list);
Packit Service 82fcde
  search_list_free (&parser->search_list);
Packit Service 82fcde
  sort_list_free (&parser->sort_list);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Allocate a struct sockaddr_in object on the heap, with the
Packit Service 82fcde
   specified address and port.  */
Packit Service 82fcde
static struct sockaddr *
Packit Service 82fcde
allocate_address_v4 (struct in_addr a, uint16_t port)
Packit Service 82fcde
{
Packit Service 82fcde
  struct sockaddr_in *sa4 = malloc (sizeof (*sa4));
Packit Service 82fcde
  if (sa4 == NULL)
Packit Service 82fcde
    return NULL;
Packit Service 82fcde
  sa4->sin_family = AF_INET;
Packit Service 82fcde
  sa4->sin_addr = a;
Packit Service 82fcde
  sa4->sin_port = htons (port);
Packit Service 82fcde
  return (struct sockaddr *) sa4;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Try to obtain the domain name from the host name and store it in
Packit Service 82fcde
   *RESULT.  Return false on memory allocation failure.  If the domain
Packit Service 82fcde
   name cannot be determined for any other reason, write NULL to
Packit Service 82fcde
   *RESULT and return true.  */
Packit Service 82fcde
static bool
Packit Service 82fcde
domain_from_hostname (char **result)
Packit Service 82fcde
{
Packit Service 82fcde
  char buf[256];
Packit Service 82fcde
  /* gethostbyname may not terminate the buffer.  */
Packit Service 82fcde
  buf[sizeof (buf) - 1] = '\0';
Packit Service 82fcde
  if (__gethostname (buf, sizeof (buf) - 1) == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      char *dot = strchr (buf, '.');
Packit Service 82fcde
      if (dot != NULL)
Packit Service 82fcde
        {
Packit Service 82fcde
          *result = __strdup (dot + 1);
Packit Service 82fcde
          if (*result == NULL)
Packit Service 82fcde
            return false;
Packit Service 82fcde
          return true;
Packit Service 82fcde
        }
Packit Service 82fcde
    }
Packit Service 82fcde
  *result = NULL;
Packit Service 82fcde
  return true;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void res_setoptions (struct resolv_conf_parser *, const char *options);
Packit Service 82fcde
Packit Service 82fcde
/* Internal helper function for __res_vinit, to aid with resource
Packit Service 82fcde
   deallocation and error handling.  Return true on success, false on
Packit Service 82fcde
   failure.  */
Packit Service 82fcde
static bool
Packit Service 82fcde
res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
Packit Service 82fcde
{
Packit Service 82fcde
  char *cp;
Packit Service 82fcde
  size_t buffer_size = 0;
Packit Service 82fcde
  bool haveenv = false;
Packit Service 82fcde
Packit Service 82fcde
  /* Allow user to override the local domain definition.  */
Packit Service 82fcde
  if ((cp = getenv ("LOCALDOMAIN")) != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* The code below splits the string in place.  */
Packit Service 82fcde
      cp = __strdup (cp);
Packit Service 82fcde
      if (cp == NULL)
Packit Service 82fcde
        return false;
Packit Service 82fcde
      free (parser->search_list_store);
Packit Service 82fcde
      parser->search_list_store = cp;
Packit Service 82fcde
      haveenv = true;
Packit Service 82fcde
Packit Service 82fcde
      /* The string will be truncated as needed below.  */
Packit Service 82fcde
      search_list_add (&parser->search_list, cp);
Packit Service 82fcde
Packit Service 82fcde
      /* Set search list to be blank-separated strings from rest of
Packit Service 82fcde
         env value.  Permits users of LOCALDOMAIN to still have a
Packit Service 82fcde
         search list, and anyone to set the one that they want to use
Packit Service 82fcde
         as an individual (even more important now that the rfc1535
Packit Service 82fcde
         stuff restricts searches).  */
Packit Service 82fcde
      for (bool in_name = true; *cp != '\0'; cp++)
Packit Service 82fcde
        {
Packit Service 82fcde
          if (*cp == '\n')
Packit Service 82fcde
            {
Packit Service 82fcde
              *cp = '\0';
Packit Service 82fcde
              break;
Packit Service 82fcde
            }
Packit Service 82fcde
          else if (*cp == ' ' || *cp == '\t')
Packit Service 82fcde
            {
Packit Service 82fcde
              *cp = '\0';
Packit Service 82fcde
              in_name = false;
Packit Service 82fcde
            }
Packit Service 82fcde
          else if (!in_name)
Packit Service 82fcde
            {
Packit Service 82fcde
              search_list_add (&parser->search_list, cp);
Packit Service 82fcde
              in_name = true;
Packit Service 82fcde
            }
Packit Service 82fcde
        }
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
#define MATCH(line, name)                       \
Packit Service 82fcde
  (!strncmp ((line), name, sizeof (name) - 1)     \
Packit Service 82fcde
   && ((line)[sizeof (name) - 1] == ' '           \
Packit Service 82fcde
       || (line)[sizeof (name) - 1] == '\t'))
Packit Service 82fcde
Packit Service 82fcde
  if (fp != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* No threads use this stream.  */
Packit Service 82fcde
      __fsetlocking (fp, FSETLOCKING_BYCALLER);
Packit Service 82fcde
      /* Read the config file.  */
Packit Service 82fcde
      while (true)
Packit Service 82fcde
        {
Packit Service 82fcde
          {
Packit Service 82fcde
            ssize_t ret = __getline (&parser->buffer, &buffer_size, fp);
Packit Service 82fcde
            if (ret <= 0)
Packit Service 82fcde
              {
Packit Service 82fcde
                if (_IO_ferror_unlocked (fp))
Packit Service 82fcde
                  return false;
Packit Service 82fcde
                else
Packit Service 82fcde
                  break;
Packit Service 82fcde
              }
Packit Service 82fcde
          }
Packit Service 82fcde
Packit Service 82fcde
          /* Skip comments.  */
Packit Service 82fcde
          if (*parser->buffer == ';' || *parser->buffer == '#')
Packit Service 82fcde
            continue;
Packit Service 82fcde
          /* Read default domain name.  */
Packit Service 82fcde
          if (MATCH (parser->buffer, "domain"))
Packit Service 82fcde
            {
Packit Service 82fcde
              if (haveenv)
Packit Service 82fcde
                /* LOCALDOMAIN overrides the configuration file.  */
Packit Service 82fcde
                continue;
Packit Service 82fcde
              cp = parser->buffer + sizeof ("domain") - 1;
Packit Service 82fcde
              while (*cp == ' ' || *cp == '\t')
Packit Service 82fcde
                cp++;
Packit Service 82fcde
              if ((*cp == '\0') || (*cp == '\n'))
Packit Service 82fcde
                continue;
Packit Service 82fcde
Packit Service 82fcde
              cp = __strdup (cp);
Packit Service 82fcde
              if (cp == NULL)
Packit Service 82fcde
                return false;
Packit Service 82fcde
              free (parser->search_list_store);
Packit Service 82fcde
              parser->search_list_store = cp;
Packit Service 82fcde
              search_list_clear (&parser->search_list);
Packit Service 82fcde
              search_list_add (&parser->search_list, cp);
Packit Service 82fcde
              /* Replace trailing whitespace.  */
Packit Service 82fcde
              if ((cp = strpbrk (cp, " \t\n")) != NULL)
Packit Service 82fcde
                *cp = '\0';
Packit Service 82fcde
              continue;
Packit Service 82fcde
            }
Packit Service 82fcde
          /* Set search list.  */
Packit Service 82fcde
          if (MATCH (parser->buffer, "search"))
Packit Service 82fcde
            {
Packit Service 82fcde
              if (haveenv)
Packit Service 82fcde
                /* LOCALDOMAIN overrides the configuration file.  */
Packit Service 82fcde
                continue;
Packit Service 82fcde
              cp = parser->buffer + sizeof ("search") - 1;
Packit Service 82fcde
              while (*cp == ' ' || *cp == '\t')
Packit Service 82fcde
                cp++;
Packit Service 82fcde
              if ((*cp == '\0') || (*cp == '\n'))
Packit Service 82fcde
                continue;
Packit Service 82fcde
Packit Service 82fcde
              {
Packit Service 82fcde
                char *p = strchr (cp, '\n');
Packit Service 82fcde
                if (p != NULL)
Packit Service 82fcde
                  *p = '\0';
Packit Service 82fcde
              }
Packit Service 82fcde
              cp = __strdup (cp);
Packit Service 82fcde
              if (cp == NULL)
Packit Service 82fcde
                return false;
Packit Service 82fcde
              free (parser->search_list_store);
Packit Service 82fcde
              parser->search_list_store = cp;
Packit Service 82fcde
Packit Service 82fcde
              /* The string is truncated below.  */
Packit Service 82fcde
              search_list_clear (&parser->search_list);
Packit Service 82fcde
              search_list_add (&parser->search_list, cp);
Packit Service 82fcde
Packit Service 82fcde
              /* Set search list to be blank-separated strings on rest
Packit Service 82fcde
                 of line.  */
Packit Service 82fcde
              for (bool in_name = true; *cp != '\0'; cp++)
Packit Service 82fcde
                {
Packit Service 82fcde
                  if (*cp == ' ' || *cp == '\t')
Packit Service 82fcde
                    {
Packit Service 82fcde
                      *cp = '\0';
Packit Service 82fcde
                      in_name = false;
Packit Service 82fcde
                    }
Packit Service 82fcde
                  else if (!in_name)
Packit Service 82fcde
                    {
Packit Service 82fcde
                      search_list_add (&parser->search_list, cp);
Packit Service 82fcde
                      in_name = true;
Packit Service 82fcde
                    }
Packit Service 82fcde
                }
Packit Service 82fcde
              continue;
Packit Service 82fcde
            }
Packit Service 82fcde
          /* Read nameservers to query.  */
Packit Service 82fcde
          if (MATCH (parser->buffer, "nameserver"))
Packit Service 82fcde
            {
Packit Service 82fcde
              struct in_addr a;
Packit Service 82fcde
Packit Service 82fcde
              cp = parser->buffer + sizeof ("nameserver") - 1;
Packit Service 82fcde
              while (*cp == ' ' || *cp == '\t')
Packit Service 82fcde
                cp++;
Packit Service 82fcde
              struct sockaddr *sa;
Packit Service 1c5418
              if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a))
Packit Service 82fcde
                {
Packit Service 82fcde
                  sa = allocate_address_v4 (a, NAMESERVER_PORT);
Packit Service 82fcde
                  if (sa == NULL)
Packit Service 82fcde
                    return false;
Packit Service 82fcde
                }
Packit Service 82fcde
              else
Packit Service 82fcde
                {
Packit Service 82fcde
                  struct in6_addr a6;
Packit Service 82fcde
                  char *el;
Packit Service 1c5418
Packit Service 1c5418
                  if ((el = strpbrk (cp, " \t\n")) != NULL)
Packit Service 1c5418
                    *el = '\0';
Packit Service 82fcde
                  if ((el = strchr (cp, SCOPE_DELIMITER)) != NULL)
Packit Service 82fcde
                    *el = '\0';
Packit Service 82fcde
                  if ((*cp != '\0') && (__inet_pton (AF_INET6, cp, &a6) > 0))
Packit Service 82fcde
                    {
Packit Service 82fcde
                      struct sockaddr_in6 *sa6;
Packit Service 82fcde
Packit Service 82fcde
                      sa6 = malloc (sizeof (*sa6));
Packit Service 82fcde
                      if (sa6 == NULL)
Packit Service 82fcde
                        return false;
Packit Service 82fcde
Packit Service 82fcde
                      sa6->sin6_family = AF_INET6;
Packit Service 82fcde
                      sa6->sin6_port = htons (NAMESERVER_PORT);
Packit Service 82fcde
                      sa6->sin6_flowinfo = 0;
Packit Service 82fcde
                      sa6->sin6_addr = a6;
Packit Service 82fcde
Packit Service 82fcde
                      sa6->sin6_scope_id = 0;
Packit Service 82fcde
                      if (__glibc_likely (el != NULL))
Packit Service 82fcde
                        /* Ignore errors, for backwards
Packit Service 82fcde
                           compatibility.  */
Packit Service 82fcde
                        __inet6_scopeid_pton
Packit Service 82fcde
                          (&a6, el + 1, &sa6->sin6_scope_id);
Packit Service 82fcde
                      sa = (struct sockaddr *) sa6;
Packit Service 82fcde
                    }
Packit Service 82fcde
                  else
Packit Service 82fcde
                    /* IPv6 address parse failure.  */
Packit Service 82fcde
                    sa = NULL;
Packit Service 82fcde
                }
Packit Service 82fcde
              if (sa != NULL)
Packit Service 82fcde
                {
Packit Service 82fcde
                  const struct sockaddr **p = nameserver_list_emplace
Packit Service 82fcde
                    (&parser->nameserver_list);
Packit Service 82fcde
                  if (p != NULL)
Packit Service 82fcde
                    *p = sa;
Packit Service 82fcde
                  else
Packit Service 82fcde
                    {
Packit Service 82fcde
                      free (sa);
Packit Service 82fcde
                      return false;
Packit Service 82fcde
                    }
Packit Service 82fcde
                }
Packit Service 82fcde
              continue;
Packit Service 82fcde
            }
Packit Service 82fcde
          if (MATCH (parser->buffer, "sortlist"))
Packit Service 82fcde
            {
Packit Service 82fcde
              struct in_addr a;
Packit Service 82fcde
Packit Service 82fcde
              cp = parser->buffer + sizeof ("sortlist") - 1;
Packit Service 82fcde
              while (true)
Packit Service 82fcde
                {
Packit Service 82fcde
                  while (*cp == ' ' || *cp == '\t')
Packit Service 82fcde
                    cp++;
Packit Service 82fcde
                  if (*cp == '\0' || *cp == '\n' || *cp == ';')
Packit Service 82fcde
                    break;
Packit Service 82fcde
                  char *net = cp;
Packit Service 82fcde
                  while (*cp && !is_sort_mask (*cp) && *cp != ';'
Packit Service 82fcde
                         && isascii (*cp) && !isspace (*cp))
Packit Service 82fcde
                    cp++;
Packit Service 82fcde
                  char separator = *cp;
Packit Service 82fcde
                  *cp = 0;
Packit Service 82fcde
                  struct resolv_sortlist_entry e;
Packit Service 1c5418
                  if (__inet_aton (net, &a))
Packit Service 82fcde
                    {
Packit Service 82fcde
                      e.addr = a;
Packit Service 82fcde
                      if (is_sort_mask (separator))
Packit Service 82fcde
                        {
Packit Service 82fcde
                          *cp++ = separator;
Packit Service 82fcde
                          net = cp;
Packit Service 82fcde
                          while (*cp && *cp != ';'
Packit Service 82fcde
                                 && isascii (*cp) && !isspace (*cp))
Packit Service 82fcde
                            cp++;
Packit Service 82fcde
                          separator = *cp;
Packit Service 82fcde
                          *cp = 0;
Packit Service 1c5418
                          if (__inet_aton (net, &a))
Packit Service 82fcde
                            e.mask = a.s_addr;
Packit Service 82fcde
                          else
Packit Service 82fcde
                            e.mask = net_mask (e.addr);
Packit Service 82fcde
                        }
Packit Service 82fcde
                      else
Packit Service 82fcde
                        e.mask = net_mask (e.addr);
Packit Service 82fcde
                      sort_list_add (&parser->sort_list, e);
Packit Service 82fcde
                    }
Packit Service 82fcde
                  *cp = separator;
Packit Service 82fcde
                }
Packit Service 82fcde
              continue;
Packit Service 82fcde
            }
Packit Service 82fcde
          if (MATCH (parser->buffer, "options"))
Packit Service 82fcde
            {
Packit Service 82fcde
              res_setoptions (parser, parser->buffer + sizeof ("options") - 1);
Packit Service 82fcde
              continue;
Packit Service 82fcde
            }
Packit Service 82fcde
        }
Packit Service 1c5418
      fclose (fp);
Packit Service 82fcde
    }
Packit Service 82fcde
  if (__glibc_unlikely (nameserver_list_size (&parser->nameserver_list) == 0))
Packit Service 82fcde
    {
Packit Service 82fcde
      const struct sockaddr **p
Packit Service 82fcde
        = nameserver_list_emplace (&parser->nameserver_list);
Packit Service 82fcde
      if (p == NULL)
Packit Service 82fcde
        return false;
Packit Service 82fcde
      *p = allocate_address_v4 (__inet_makeaddr (IN_LOOPBACKNET, 1),
Packit Service 82fcde
                                NAMESERVER_PORT);
Packit Service 82fcde
      if (*p == NULL)
Packit Service 82fcde
        return false;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if (search_list_size (&parser->search_list) == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      char *domain;
Packit Service 82fcde
      if (!domain_from_hostname (&domain))
Packit Service 82fcde
        return false;
Packit Service 82fcde
      if (domain != NULL)
Packit Service 82fcde
        {
Packit Service 82fcde
          free (parser->search_list_store);
Packit Service 82fcde
          parser->search_list_store = domain;
Packit Service 82fcde
          search_list_add (&parser->search_list, domain);
Packit Service 82fcde
        }
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if ((cp = getenv ("RES_OPTIONS")) != NULL)
Packit Service 82fcde
    res_setoptions (parser, cp);
Packit Service 82fcde
Packit Service 82fcde
  if (nameserver_list_has_failed (&parser->nameserver_list)
Packit Service 82fcde
      || search_list_has_failed (&parser->search_list)
Packit Service 82fcde
      || sort_list_has_failed (&parser->sort_list))
Packit Service 82fcde
    {
Packit Service 82fcde
      __set_errno (ENOMEM);
Packit Service 82fcde
      return false;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return true;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
struct resolv_conf *
Packit Service 1c5418
__resolv_conf_load (struct __res_state *preinit)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Ensure that /etc/hosts.conf has been loaded (once).  */
Packit Service 82fcde
  _res_hconf_init ();
Packit Service 82fcde
Packit Service 82fcde
  FILE *fp = fopen (_PATH_RESCONF, "rce");
Packit Service 82fcde
  if (fp == NULL)
Packit Service 82fcde
    switch (errno)
Packit Service 82fcde
      {
Packit Service 82fcde
      case EACCES:
Packit Service 82fcde
      case EISDIR:
Packit Service 82fcde
      case ELOOP:
Packit Service 82fcde
      case ENOENT:
Packit Service 82fcde
      case ENOTDIR:
Packit Service 82fcde
      case EPERM:
Packit Service 82fcde
        /* Ignore these errors.  They are persistent errors caused
Packit Service 82fcde
           by file system contents.  */
Packit Service 82fcde
        break;
Packit Service 82fcde
      default:
Packit Service 82fcde
        /* Other errors refer to resource allocation problems and
Packit Service 82fcde
           need to be handled by the application.  */
Packit Service 82fcde
        return NULL;
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
  struct resolv_conf_parser parser;
Packit Service 82fcde
  resolv_conf_parser_init (&parser, preinit);
Packit Service 82fcde
Packit Service 82fcde
  struct resolv_conf *conf = NULL;
Packit Service 1c5418
  if (res_vinit_1 (fp, &parser))
Packit Service 82fcde
    {
Packit Service 82fcde
      parser.template.nameserver_list
Packit Service 82fcde
        = nameserver_list_begin (&parser.nameserver_list);
Packit Service 82fcde
      parser.template.nameserver_list_size
Packit Service 82fcde
        = nameserver_list_size (&parser.nameserver_list);
Packit Service 82fcde
      parser.template.search_list = search_list_begin (&parser.search_list);
Packit Service 82fcde
      parser.template.search_list_size
Packit Service 82fcde
        = search_list_size (&parser.search_list);
Packit Service 82fcde
      parser.template.sort_list = sort_list_begin (&parser.sort_list);
Packit Service 82fcde
      parser.template.sort_list_size = sort_list_size (&parser.sort_list);
Packit Service 82fcde
      conf = __resolv_conf_allocate (&parser.template);
Packit Service 82fcde
    }
Packit Service 82fcde
  resolv_conf_parser_free (&parser);
Packit Service 82fcde
Packit Service 82fcde
  return conf;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Set up default settings.  If the /etc/resolv.conf configuration
Packit Service 82fcde
   file exist, the values there will have precedence.  Otherwise, the
Packit Service 82fcde
   server address is set to INADDR_LOOPBACK and the default domain
Packit Service 82fcde
   name comes from gethostname.  The RES_OPTIONS and LOCALDOMAIN
Packit Service 82fcde
   environment variables can be used to override some settings.
Packit Service 82fcde
   Return 0 if completes successfully, -1 on error.  */
Packit Service 82fcde
int
Packit Service 82fcde
__res_vinit (res_state statp, int preinit)
Packit Service 82fcde
{
Packit Service 82fcde
  struct resolv_conf *conf;
Packit Service 82fcde
  if (preinit && has_preinit_values (statp))
Packit Service 82fcde
    /* For the preinit case, we cannot use the cached configuration
Packit Service 82fcde
       because some settings could be different.  */
Packit Service 1c5418
    conf = __resolv_conf_load (statp);
Packit Service 82fcde
  else
Packit Service 82fcde
    conf = __resolv_conf_get_current ();
Packit Service 82fcde
  if (conf == NULL)
Packit Service 82fcde
    return -1;
Packit Service 82fcde
Packit Service 82fcde
  bool ok = __resolv_conf_attach (statp, conf);
Packit Service 82fcde
  __resolv_conf_put (conf);
Packit Service 82fcde
  if (ok)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (preinit)
Packit Service 82fcde
        statp->id = res_randomid ();
Packit Service 82fcde
      return 0;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    return -1;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
res_setoptions (struct resolv_conf_parser *parser, const char *options)
Packit Service 82fcde
{
Packit Service 82fcde
  const char *cp = options;
Packit Service 82fcde
Packit Service 82fcde
  while (*cp)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Skip leading and inner runs of spaces.  */
Packit Service 82fcde
      while (*cp == ' ' || *cp == '\t')
Packit Service 82fcde
        cp++;
Packit Service 82fcde
      /* Search for and process individual options.  */
Packit Service 82fcde
      if (!strncmp (cp, "ndots:", sizeof ("ndots:") - 1))
Packit Service 82fcde
        {
Packit Service 82fcde
          int i = atoi (cp + sizeof ("ndots:") - 1);
Packit Service 82fcde
          if (i <= RES_MAXNDOTS)
Packit Service 82fcde
            parser->template.ndots = i;
Packit Service 82fcde
          else
Packit Service 82fcde
            parser->template.ndots = RES_MAXNDOTS;
Packit Service 82fcde
        }
Packit Service 82fcde
      else if (!strncmp (cp, "timeout:", sizeof ("timeout:") - 1))
Packit Service 82fcde
        {
Packit Service 82fcde
          int i = atoi (cp + sizeof ("timeout:") - 1);
Packit Service 82fcde
          if (i <= RES_MAXRETRANS)
Packit Service 82fcde
            parser->template.retrans = i;
Packit Service 82fcde
          else
Packit Service 82fcde
            parser->template.retrans = RES_MAXRETRANS;
Packit Service 82fcde
        }
Packit Service 82fcde
      else if (!strncmp (cp, "attempts:", sizeof ("attempts:") - 1))
Packit Service 82fcde
        {
Packit Service 82fcde
          int i = atoi (cp + sizeof ("attempts:") - 1);
Packit Service 82fcde
          if (i <= RES_MAXRETRY)
Packit Service 82fcde
            parser->template.retry = i;
Packit Service 82fcde
          else
Packit Service 82fcde
            parser->template.retry = RES_MAXRETRY;
Packit Service 82fcde
        }
Packit Service 82fcde
      else
Packit Service 82fcde
        {
Packit Service 82fcde
          static const struct
Packit Service 82fcde
          {
Packit Service 82fcde
            char str[22];
Packit Service 82fcde
            uint8_t len;
Packit Service 82fcde
            uint8_t clear;
Packit Service 82fcde
            unsigned long int flag;
Packit Service 82fcde
          } options[] = {
Packit Service 82fcde
#define STRnLEN(str) str, sizeof (str) - 1
Packit Service 82fcde
            { STRnLEN ("inet6"), 0, DEPRECATED_RES_USE_INET6 },
Packit Service 82fcde
            { STRnLEN ("rotate"), 0, RES_ROTATE },
Packit Service 82fcde
            { STRnLEN ("edns0"), 0, RES_USE_EDNS0 },
Packit Service 82fcde
            { STRnLEN ("single-request-reopen"), 0, RES_SNGLKUPREOP },
Packit Service 82fcde
            { STRnLEN ("single-request"), 0, RES_SNGLKUP },
Packit Service 82fcde
            { STRnLEN ("no_tld_query"), 0, RES_NOTLDQUERY },
Packit Service 82fcde
            { STRnLEN ("no-tld-query"), 0, RES_NOTLDQUERY },
Packit Service 82fcde
            { STRnLEN ("no-reload"), 0, RES_NORELOAD },
Packit Service 82fcde
            { STRnLEN ("use-vc"), 0, RES_USEVC }
Packit Service 82fcde
          };
Packit Service 82fcde
#define noptions (sizeof (options) / sizeof (options[0]))
Packit Service 82fcde
          for (int i = 0; i < noptions; ++i)
Packit Service 82fcde
            if (strncmp (cp, options[i].str, options[i].len) == 0)
Packit Service 82fcde
              {
Packit Service 82fcde
                if (options[i].clear)
Packit Service 82fcde
                  parser->template.options &= options[i].flag;
Packit Service 82fcde
                else
Packit Service 82fcde
                  parser->template.options |= options[i].flag;
Packit Service 82fcde
                break;
Packit Service 82fcde
              }
Packit Service 82fcde
        }
Packit Service 82fcde
      /* Skip to next run of spaces.  */
Packit Service 82fcde
      while (*cp && *cp != ' ' && *cp != '\t')
Packit Service 82fcde
        cp++;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static uint32_t
Packit Service 82fcde
net_mask (struct in_addr in)
Packit Service 82fcde
{
Packit Service 82fcde
  uint32_t i = ntohl (in.s_addr);
Packit Service 82fcde
Packit Service 82fcde
  if (IN_CLASSA (i))
Packit Service 82fcde
    return htonl (IN_CLASSA_NET);
Packit Service 82fcde
  else if (IN_CLASSB (i))
Packit Service 82fcde
    return htonl (IN_CLASSB_NET);
Packit Service 82fcde
  return htonl (IN_CLASSC_NET);
Packit Service 82fcde
}