Blame resolv/tst-resolv-res_init-skeleton.c

Packit Service 82fcde
/* Test parsing of /etc/resolv.conf.  Genric version.
Packit Service 82fcde
   Copyright (C) 2017-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
/* Before including this file, TEST_THREAD has to be defined to 0 or
Packit Service 82fcde
   1, depending on whether the threading tests should be compiled
Packit Service 82fcde
   in.  */
Packit Service 82fcde
Packit Service 82fcde
#include <arpa/inet.h>
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <gnu/lib-names.h>
Packit Service 82fcde
#include <netdb.h>
Packit Service 82fcde
#include <resolv/resolv-internal.h> /* For DEPRECATED_RES_USE_INET6.  */
Packit Service 82fcde
#include <resolv/resolv_context.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <support/capture_subprocess.h>
Packit Service 82fcde
#include <support/check.h>
Packit Service 82fcde
#include <support/namespace.h>
Packit Service 82fcde
#include <support/run_diff.h>
Packit Service 82fcde
#include <support/support.h>
Packit Service 82fcde
#include <support/temp_file.h>
Packit Service 82fcde
#include <support/test-driver.h>
Packit Service 82fcde
#include <support/xsocket.h>
Packit Service 82fcde
#include <support/xstdio.h>
Packit Service 82fcde
#include <support/xunistd.h>
Packit Service 82fcde
Packit Service 82fcde
#if TEST_THREAD
Packit Service 82fcde
# include <support/xthread.h>
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* This is the host name used to ensure predictable behavior of
Packit Service 82fcde
   res_init.  */
Packit Service 82fcde
static const char *const test_hostname = "www.example.com";
Packit Service 82fcde
Packit Service 82fcde
struct support_chroot *chroot_env;
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
prepare (int argc, char **argv)
Packit Service 82fcde
{
Packit Service 82fcde
  chroot_env = support_chroot_create
Packit Service 82fcde
    ((struct support_chroot_configuration)
Packit Service 82fcde
     {
Packit Service 82fcde
       .resolv_conf = "",
Packit Service 82fcde
     });
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Verify that the chroot environment has been set up.  */
Packit Service 82fcde
static void
Packit Service 82fcde
check_chroot_working (void *closure)
Packit Service 82fcde
{
Packit Service 82fcde
  xchroot (chroot_env->path_chroot);
Packit Service 82fcde
  FILE *fp = xfopen (_PATH_RESCONF, "r");
Packit Service 82fcde
  xfclose (fp);
Packit Service 82fcde
Packit Service 82fcde
  TEST_VERIFY_EXIT (res_init () == 0);
Packit Service 82fcde
  TEST_VERIFY (_res.options & RES_INIT);
Packit Service 82fcde
Packit Service 82fcde
  char buf[100];
Packit Service 82fcde
  if (gethostname (buf, sizeof (buf)) < 0)
Packit Service 82fcde
    FAIL_EXIT1 ("gethostname: %m");
Packit Service 82fcde
  if (strcmp (buf, test_hostname) != 0)
Packit Service 82fcde
    FAIL_EXIT1 ("unexpected host name: %s", buf);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* If FLAG is set in *OPTIONS, write NAME to FP, and clear it in
Packit Service 82fcde
   *OPTIONS.  */
Packit Service 82fcde
static void
Packit Service 82fcde
print_option_flag (FILE *fp, int *options, int flag, const char *name)
Packit Service 82fcde
{
Packit Service 82fcde
  if (*options & flag)
Packit Service 82fcde
    {
Packit Service 82fcde
      fprintf (fp, " %s", name);
Packit Service 82fcde
      *options &= ~flag;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Write a decoded version of the resolver configuration *RESP to the
Packit Service 82fcde
   stream FP.  */
Packit Service 82fcde
static void
Packit Service 82fcde
print_resp (FILE *fp, res_state resp)
Packit Service 82fcde
{
Packit Service 82fcde
  struct resolv_context *ctx = __resolv_context_get_override (resp);
Packit Service 82fcde
  TEST_VERIFY_EXIT (ctx != NULL);
Packit Service 82fcde
  if (ctx->conf == NULL)
Packit Service 82fcde
    fprintf (fp, "; extended resolver state missing\n");
Packit Service 82fcde
Packit Service 82fcde
  /* The options directive.  */
Packit Service 82fcde
  {
Packit Service 82fcde
    /* RES_INIT is used internally for tracking initialization.  */
Packit Service 82fcde
    TEST_VERIFY (resp->options & RES_INIT);
Packit Service 82fcde
    /* Also mask out other default flags which cannot be set through
Packit Service 82fcde
       the options directive.  */
Packit Service 82fcde
    int options
Packit Service 82fcde
      = resp->options & ~(RES_INIT | RES_RECURSE | RES_DEFNAMES | RES_DNSRCH);
Packit Service 82fcde
    if (options != 0
Packit Service 82fcde
        || resp->ndots != 1
Packit Service 82fcde
        || resp->retrans != RES_TIMEOUT
Packit Service 82fcde
        || resp->retry != RES_DFLRETRY)
Packit Service 82fcde
      {
Packit Service 82fcde
        fputs ("options", fp);
Packit Service 82fcde
        if (resp->ndots != 1)
Packit Service 82fcde
          fprintf (fp, " ndots:%d", resp->ndots);
Packit Service 82fcde
        if (resp->retrans != RES_TIMEOUT)
Packit Service 82fcde
          fprintf (fp, " timeout:%d", resp->retrans);
Packit Service 82fcde
        if (resp->retry != RES_DFLRETRY)
Packit Service 82fcde
          fprintf (fp, " attempts:%d", resp->retry);
Packit Service 82fcde
        print_option_flag (fp, &options, RES_USEVC, "use-vc");
Packit Service 82fcde
        print_option_flag (fp, &options, DEPRECATED_RES_USE_INET6, "inet6");
Packit Service 82fcde
        print_option_flag (fp, &options, RES_ROTATE, "rotate");
Packit Service 82fcde
        print_option_flag (fp, &options, RES_USE_EDNS0, "edns0");
Packit Service 82fcde
        print_option_flag (fp, &options, RES_SNGLKUP,
Packit Service 82fcde
                           "single-request");
Packit Service 82fcde
        print_option_flag (fp, &options, RES_SNGLKUPREOP,
Packit Service 82fcde
                           "single-request-reopen");
Packit Service 82fcde
        print_option_flag (fp, &options, RES_NOTLDQUERY, "no-tld-query");
Packit Service 82fcde
        print_option_flag (fp, &options, RES_NORELOAD, "no-reload");
Packit Service 82fcde
        fputc ('\n', fp);
Packit Service 82fcde
        if (options != 0)
Packit Service 82fcde
          fprintf (fp, "; error: unresolved option bits: 0x%x\n", options);
Packit Service 82fcde
      }
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
  /* The search and domain directives.  */
Packit Service 82fcde
  if (resp->dnsrch[0] != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      fputs ("search", fp);
Packit Service 82fcde
      for (int i = 0; i < MAXDNSRCH && resp->dnsrch[i] != NULL; ++i)
Packit Service 82fcde
        {
Packit Service 82fcde
          fputc (' ', fp);
Packit Service 82fcde
          fputs (resp->dnsrch[i], fp);
Packit Service 82fcde
        }
Packit Service 82fcde
      fputc ('\n', fp);
Packit Service 82fcde
    }
Packit Service 82fcde
  else if (resp->defdname[0] != '\0')
Packit Service 82fcde
    fprintf (fp, "domain %s\n", resp->defdname);
Packit Service 82fcde
Packit Service 82fcde
  /* The extended search path.  */
Packit Service 82fcde
  {
Packit Service 82fcde
    size_t i = 0;
Packit Service 82fcde
    while (true)
Packit Service 82fcde
      {
Packit Service 82fcde
        const char *name = __resolv_context_search_list (ctx, i);
Packit Service 82fcde
        if (name == NULL)
Packit Service 82fcde
          break;
Packit Service 82fcde
        fprintf (fp, "; search[%zu]: %s\n", i, name);
Packit Service 82fcde
        ++i;
Packit Service 82fcde
      }
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
  /* The sortlist directive.  */
Packit Service 82fcde
  if (resp->nsort > 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      fputs ("sortlist", fp);
Packit Service 82fcde
      for (int i = 0; i < resp->nsort && i < MAXRESOLVSORT; ++i)
Packit Service 82fcde
        {
Packit Service 82fcde
          char net[20];
Packit Service 82fcde
          if (inet_ntop (AF_INET, &resp->sort_list[i].addr,
Packit Service 82fcde
                         net, sizeof (net)) == NULL)
Packit Service 82fcde
            FAIL_EXIT1 ("inet_ntop: %m\n");
Packit Service 82fcde
          char mask[20];
Packit Service 82fcde
          if (inet_ntop (AF_INET, &resp->sort_list[i].mask,
Packit Service 82fcde
                         mask, sizeof (mask)) == NULL)
Packit Service 82fcde
            FAIL_EXIT1 ("inet_ntop: %m\n");
Packit Service 82fcde
          fprintf (fp, " %s/%s", net, mask);
Packit Service 82fcde
        }
Packit Service 82fcde
      fputc ('\n', fp);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* The nameserver directives.  */
Packit Service 82fcde
  for (size_t i = 0; i < resp->nscount; ++i)
Packit Service 82fcde
    {
Packit Service 82fcde
      char host[NI_MAXHOST];
Packit Service 82fcde
      char service[NI_MAXSERV];
Packit Service 82fcde
Packit Service 82fcde
      /* See get_nsaddr in res_send.c.  */
Packit Service 82fcde
      void *addr;
Packit Service 82fcde
      size_t addrlen;
Packit Service 82fcde
      if (resp->nsaddr_list[i].sin_family == 0
Packit Service 82fcde
          && resp->_u._ext.nsaddrs[i] != NULL)
Packit Service 82fcde
        {
Packit Service 82fcde
          addr = resp->_u._ext.nsaddrs[i];
Packit Service 82fcde
          addrlen = sizeof (*resp->_u._ext.nsaddrs[i]);
Packit Service 82fcde
        }
Packit Service 82fcde
      else
Packit Service 82fcde
        {
Packit Service 82fcde
          addr = &resp->nsaddr_list[i];
Packit Service 82fcde
          addrlen = sizeof (resp->nsaddr_list[i]);
Packit Service 82fcde
        }
Packit Service 82fcde
Packit Service 82fcde
      int ret = getnameinfo (addr, addrlen,
Packit Service 82fcde
                             host, sizeof (host), service, sizeof (service),
Packit Service 82fcde
                             NI_NUMERICHOST | NI_NUMERICSERV);
Packit Service 82fcde
      if (ret != 0)
Packit Service 82fcde
        {
Packit Service 82fcde
          if (ret == EAI_SYSTEM)
Packit Service 82fcde
            fprintf (fp, "; error: getnameinfo: %m\n");
Packit Service 82fcde
          else
Packit Service 82fcde
            fprintf (fp, "; error: getnameinfo: %s\n", gai_strerror (ret));
Packit Service 82fcde
        }
Packit Service 82fcde
      else
Packit Service 82fcde
        {
Packit Service 82fcde
          fprintf (fp, "nameserver %s\n", host);
Packit Service 82fcde
          if (strcmp (service, "53") != 0)
Packit Service 82fcde
            fprintf (fp, "; unrepresentable port number %s\n\n", service);
Packit Service 82fcde
        }
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* The extended name server list.  */
Packit Service 82fcde
  {
Packit Service 82fcde
    size_t i = 0;
Packit Service 82fcde
    while (true)
Packit Service 82fcde
      {
Packit Service 82fcde
        const struct sockaddr *addr = __resolv_context_nameserver (ctx, i);
Packit Service 82fcde
        if (addr == NULL)
Packit Service 82fcde
          break;
Packit Service 82fcde
        size_t addrlen;
Packit Service 82fcde
        switch (addr->sa_family)
Packit Service 82fcde
          {
Packit Service 82fcde
          case AF_INET:
Packit Service 82fcde
            addrlen = sizeof (struct sockaddr_in);
Packit Service 82fcde
            break;
Packit Service 82fcde
          case AF_INET6:
Packit Service 82fcde
            addrlen = sizeof (struct sockaddr_in6);
Packit Service 82fcde
            break;
Packit Service 82fcde
          default:
Packit Service 82fcde
            FAIL_EXIT1 ("invalid address family %d", addr->sa_family);
Packit Service 82fcde
          }
Packit Service 82fcde
Packit Service 82fcde
        char host[NI_MAXHOST];
Packit Service 82fcde
        char service[NI_MAXSERV];
Packit Service 82fcde
        int ret = getnameinfo (addr, addrlen,
Packit Service 82fcde
                               host, sizeof (host), service, sizeof (service),
Packit Service 82fcde
                               NI_NUMERICHOST | NI_NUMERICSERV);
Packit Service 82fcde
Packit Service 82fcde
        if (ret != 0)
Packit Service 82fcde
          {
Packit Service 82fcde
            if (ret == EAI_SYSTEM)
Packit Service 82fcde
              fprintf (fp, "; error: getnameinfo: %m\n");
Packit Service 82fcde
            else
Packit Service 82fcde
              fprintf (fp, "; error: getnameinfo: %s\n", gai_strerror (ret));
Packit Service 82fcde
          }
Packit Service 82fcde
        else
Packit Service 82fcde
          fprintf (fp, "; nameserver[%zu]: [%s]:%s\n", i, host, service);
Packit Service 82fcde
        ++i;
Packit Service 82fcde
      }
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
  TEST_VERIFY (!ferror (fp));
Packit Service 82fcde
Packit Service 82fcde
  __resolv_context_put (ctx);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Parameters of one test case.  */
Packit Service 82fcde
struct test_case
Packit Service 82fcde
{
Packit Service 82fcde
  /* A short, descriptive name of the test.  */
Packit Service 82fcde
  const char *name;
Packit Service 82fcde
Packit Service 82fcde
  /* The contents of the /etc/resolv.conf file.  */
Packit Service 82fcde
  const char *conf;
Packit Service 82fcde
Packit Service 82fcde
  /* The expected output from print_resp.  */
Packit Service 82fcde
  const char *expected;
Packit Service 82fcde
Packit Service 82fcde
  /* Setting for the LOCALDOMAIN environment variable.  NULL if the
Packit Service 82fcde
     variable is not to be set.  */
Packit Service 82fcde
  const char *localdomain;
Packit Service 82fcde
Packit Service 82fcde
  /* Setting for the RES_OPTIONS environment variable.  NULL if the
Packit Service 82fcde
     variable is not to be set.  */
Packit Service 82fcde
  const char *res_options;
Packit Service 82fcde
Packit Service 82fcde
  /* Override the system host name.  NULL means that no change is made
Packit Service 82fcde
     and the default is used (test_hostname).  */
Packit Service 82fcde
  const char *hostname;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
enum test_init
Packit Service 82fcde
{
Packit Service 82fcde
  test_init,
Packit Service 82fcde
  test_ninit,
Packit Service 82fcde
  test_mkquery,
Packit Service 82fcde
  test_gethostbyname,
Packit Service 82fcde
  test_getaddrinfo,
Packit Service 82fcde
  test_init_method_last = test_getaddrinfo
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
static const char *const test_init_names[] =
Packit Service 82fcde
  {
Packit Service 82fcde
    [test_init] = "res_init",
Packit Service 82fcde
    [test_ninit] = "res_ninit",
Packit Service 82fcde
    [test_mkquery] = "res_mkquery",
Packit Service 82fcde
    [test_gethostbyname] = "gethostbyname",
Packit Service 82fcde
    [test_getaddrinfo] = "getaddrinfo",
Packit Service 82fcde
  };
Packit Service 82fcde
Packit Service 82fcde
/* Closure argument for run_res_init.  */
Packit Service 82fcde
struct test_context
Packit Service 82fcde
{
Packit Service 82fcde
  enum test_init init;
Packit Service 82fcde
  const struct test_case *t;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
setup_nss_dns_and_chroot (void)
Packit Service 82fcde
{
Packit Service 82fcde
  /* Load nss_dns outside of the chroot.  */
Packit Service 82fcde
  if (dlopen (LIBNSS_DNS_SO, RTLD_LAZY) == NULL)
Packit Service 82fcde
    FAIL_EXIT1 ("could not load " LIBNSS_DNS_SO ": %s", dlerror ());
Packit Service 82fcde
  xchroot (chroot_env->path_chroot);
Packit Service 82fcde
  /* Force the use of nss_dns.  */
Packit Service 82fcde
  __nss_configure_lookup ("hosts", "dns");
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Run res_ninit or res_init in a subprocess and dump the parsed
Packit Service 82fcde
   resolver state to standard output.  */
Packit Service 82fcde
static void
Packit Service 82fcde
run_res_init (void *closure)
Packit Service 82fcde
{
Packit Service 82fcde
  struct test_context *ctx = closure;
Packit Service 82fcde
  TEST_VERIFY (getenv ("LOCALDOMAIN") == NULL);
Packit Service 82fcde
  TEST_VERIFY (getenv ("RES_OPTIONS") == NULL);
Packit Service 82fcde
  if (ctx->t->localdomain != NULL)
Packit Service 82fcde
    setenv ("LOCALDOMAIN", ctx->t->localdomain, 1);
Packit Service 82fcde
  if (ctx->t->res_options != NULL)
Packit Service 82fcde
    setenv ("RES_OPTIONS", ctx->t->res_options, 1);
Packit Service 82fcde
  if (ctx->t->hostname != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
#ifdef CLONE_NEWUTS
Packit Service 82fcde
      /* This test needs its own namespace, to avoid changing the host
Packit Service 82fcde
         name for the parent, too.  */
Packit Service 82fcde
      TEST_VERIFY_EXIT (unshare (CLONE_NEWUTS) == 0);
Packit Service 82fcde
      if (sethostname (ctx->t->hostname, strlen (ctx->t->hostname)) != 0)
Packit Service 82fcde
        FAIL_EXIT1 ("sethostname (\"%s\"): %m", ctx->t->hostname);
Packit Service 82fcde
#else
Packit Service 82fcde
      FAIL_UNSUPPORTED ("clone (CLONE_NEWUTS) not supported");
Packit Service 82fcde
#endif
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  switch (ctx->init)
Packit Service 82fcde
    {
Packit Service 82fcde
    case test_init:
Packit Service 82fcde
      xchroot (chroot_env->path_chroot);
Packit Service 82fcde
      TEST_VERIFY (res_init () == 0);
Packit Service 82fcde
      print_resp (stdout, &_res);
Packit Service 82fcde
      return;
Packit Service 82fcde
Packit Service 82fcde
    case test_ninit:
Packit Service 82fcde
      xchroot (chroot_env->path_chroot);
Packit Service 82fcde
      res_state resp = xmalloc (sizeof (*resp));
Packit Service 82fcde
      memset (resp, 0, sizeof (*resp));
Packit Service 82fcde
      TEST_VERIFY (res_ninit (resp) == 0);
Packit Service 82fcde
      print_resp (stdout, resp);
Packit Service 82fcde
      res_nclose (resp);
Packit Service 82fcde
      free (resp);
Packit Service 82fcde
      return;
Packit Service 82fcde
Packit Service 82fcde
    case test_mkquery:
Packit Service 82fcde
      xchroot (chroot_env->path_chroot);
Packit Service 82fcde
      unsigned char buf[512];
Packit Service 82fcde
      TEST_VERIFY (res_mkquery (QUERY, "www.example",
Packit Service 82fcde
                                C_IN, ns_t_a, NULL, 0,
Packit Service 82fcde
                                NULL, buf, sizeof (buf)) > 0);
Packit Service 82fcde
      print_resp (stdout, &_res);
Packit Service 82fcde
      return;
Packit Service 82fcde
Packit Service 82fcde
    case test_gethostbyname:
Packit Service 82fcde
      setup_nss_dns_and_chroot ();
Packit Service 82fcde
      /* Trigger implicit initialization of the _res structure.  The
Packit Service 82fcde
         actual lookup result is immaterial.  */
Packit Service 82fcde
      (void )gethostbyname ("www.example");
Packit Service 82fcde
      print_resp (stdout, &_res);
Packit Service 82fcde
      return;
Packit Service 82fcde
Packit Service 82fcde
    case test_getaddrinfo:
Packit Service 82fcde
      setup_nss_dns_and_chroot ();
Packit Service 82fcde
      /* Trigger implicit initialization of the _res structure.  The
Packit Service 82fcde
         actual lookup result is immaterial.  */
Packit Service 82fcde
      struct addrinfo *ai;
Packit Service 82fcde
      (void) getaddrinfo ("www.example", NULL, NULL, &ai;;
Packit Service 82fcde
      print_resp (stdout, &_res);
Packit Service 82fcde
      return;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  FAIL_EXIT1 ("invalid init method %d", ctx->init);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#if TEST_THREAD
Packit Service 82fcde
/* Helper function which calls run_res_init from a thread.  */
Packit Service 82fcde
static void *
Packit Service 82fcde
run_res_init_thread_func (void *closure)
Packit Service 82fcde
{
Packit Service 82fcde
  run_res_init (closure);
Packit Service 82fcde
  return NULL;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Variant of res_run_init which runs the function on a non-main
Packit Service 82fcde
   thread.  */
Packit Service 82fcde
static void
Packit Service 82fcde
run_res_init_on_thread (void *closure)
Packit Service 82fcde
{
Packit Service 82fcde
  xpthread_join (xpthread_create (NULL, run_res_init_thread_func, closure));
Packit Service 82fcde
}
Packit Service 82fcde
#endif /* TEST_THREAD */
Packit Service 82fcde
Packit Service 82fcde
struct test_case test_cases[] =
Packit Service 82fcde
  {
Packit Service 82fcde
    {.name = "empty file",
Packit Service 82fcde
     .conf = "",
Packit Service 82fcde
     .expected = "search example.com\n"
Packit Service 82fcde
     "; search[0]: example.com\n"
Packit Service 82fcde
     "nameserver 127.0.0.1\n"
Packit Service 82fcde
     "; nameserver[0]: [127.0.0.1]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "empty file, no-dot hostname",
Packit Service 82fcde
     .conf = "",
Packit Service 82fcde
     .expected = "nameserver 127.0.0.1\n"
Packit Service 82fcde
     "; nameserver[0]: [127.0.0.1]:53\n",
Packit Service 82fcde
     .hostname = "example",
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "empty file with LOCALDOMAIN",
Packit Service 82fcde
     .conf = "",
Packit Service 82fcde
     .expected = "search example.net\n"
Packit Service 82fcde
     "; search[0]: example.net\n"
Packit Service 82fcde
     "nameserver 127.0.0.1\n"
Packit Service 82fcde
     "; nameserver[0]: [127.0.0.1]:53\n",
Packit Service 82fcde
     .localdomain = "example.net",
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "empty file with RES_OPTIONS",
Packit Service 82fcde
     .conf = "",
Packit Service 82fcde
     .expected = "options attempts:5 edns0\n"
Packit Service 82fcde
     "search example.com\n"
Packit Service 82fcde
     "; search[0]: example.com\n"
Packit Service 82fcde
     "nameserver 127.0.0.1\n"
Packit Service 82fcde
     "; nameserver[0]: [127.0.0.1]:53\n",
Packit Service 82fcde
     .res_options = "edns0 attempts:5",
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "empty file with RES_OPTIONS and LOCALDOMAIN",
Packit Service 82fcde
     .conf = "",
Packit Service 82fcde
     .expected = "options attempts:5 edns0\n"
Packit Service 82fcde
     "search example.org\n"
Packit Service 82fcde
     "; search[0]: example.org\n"
Packit Service 82fcde
     "nameserver 127.0.0.1\n"
Packit Service 82fcde
     "; nameserver[0]: [127.0.0.1]:53\n",
Packit Service 82fcde
     .localdomain = "example.org",
Packit Service 82fcde
     .res_options = "edns0 attempts:5",
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "basic",
Packit Service 82fcde
     .conf =  "search corp.example.com example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n",
Packit Service 82fcde
     .expected = "search corp.example.com example.com\n"
Packit Service 82fcde
     "; search[0]: corp.example.com\n"
Packit Service 82fcde
     "; search[1]: example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "basic with no-dot hostname",
Packit Service 82fcde
     .conf = "search corp.example.com example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n",
Packit Service 82fcde
     .expected = "search corp.example.com example.com\n"
Packit Service 82fcde
     "; search[0]: corp.example.com\n"
Packit Service 82fcde
     "; search[1]: example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n",
Packit Service 82fcde
     .hostname = "example",
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "basic no-reload",
Packit Service 82fcde
     .conf = "options no-reload\n"
Packit Service 82fcde
     "search corp.example.com example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n",
Packit Service 82fcde
     .expected = "options no-reload\n"
Packit Service 82fcde
     "search corp.example.com example.com\n"
Packit Service 82fcde
     "; search[0]: corp.example.com\n"
Packit Service 82fcde
     "; search[1]: example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "basic no-reload via RES_OPTIONS",
Packit Service 82fcde
     .conf = "search corp.example.com example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n",
Packit Service 82fcde
     .expected = "options no-reload\n"
Packit Service 82fcde
     "search corp.example.com example.com\n"
Packit Service 82fcde
     "; search[0]: corp.example.com\n"
Packit Service 82fcde
     "; search[1]: example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n",
Packit Service 82fcde
     .res_options = "no-reload"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "whitespace",
Packit Service 82fcde
     .conf = "# This test covers comment and whitespace processing "
Packit Service 82fcde
     " (trailing whitespace,\n"
Packit Service 82fcde
     "# missing newline at end of file).\n"
Packit Service 82fcde
     "\n"
Packit Service 82fcde
     ";search commented out\n"
Packit Service 82fcde
     "search corp.example.com\texample.com \n"
Packit Service 82fcde
     "#nameserver 192.0.2.3\n"
Packit Service 82fcde
     "nameserver 192.0.2.1 \n"
Packit Service 82fcde
     "nameserver 192.0.2.2",    /* No \n at end of file.  */
Packit Service 82fcde
     .expected = "search corp.example.com example.com\n"
Packit Service 82fcde
     "; search[0]: corp.example.com\n"
Packit Service 82fcde
     "; search[1]: example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "nameserver 192.0.2.2\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
     "; nameserver[1]: [192.0.2.2]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "domain",
Packit Service 82fcde
     .conf = "domain example.net\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n",
Packit Service 82fcde
     .expected = "search example.net\n"
Packit Service 82fcde
     "; search[0]: example.net\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "domain space",
Packit Service 82fcde
     .conf = "domain example.net \n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n",
Packit Service 82fcde
     .expected = "search example.net\n"
Packit Service 82fcde
     "; search[0]: example.net\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "domain tab",
Packit Service 82fcde
     .conf = "domain example.net\t\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n",
Packit Service 82fcde
     .expected = "search example.net\n"
Packit Service 82fcde
     "; search[0]: example.net\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "domain override",
Packit Service 82fcde
     .conf = "search example.com example.org\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "domain example.net",      /* No \n at end of file.  */
Packit Service 82fcde
     .expected = "search example.net\n"
Packit Service 82fcde
     "; search[0]: example.net\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "option values, multiple servers",
Packit Service 82fcde
     .conf = "options\tinet6\tndots:3 edns0\tattempts:5\ttimeout:19\n"
Packit Service 82fcde
     "domain  example.net\n"
Packit Service 82fcde
     ";domain comment\n"
Packit Service 82fcde
     "search corp.example.com\texample.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "nameserver ::1\n"
Packit Service 82fcde
     "nameserver 192.0.2.2\n",
Packit Service 82fcde
     .expected = "options ndots:3 timeout:19 attempts:5 inet6 edns0\n"
Packit Service 82fcde
     "search corp.example.com example.com\n"
Packit Service 82fcde
     "; search[0]: corp.example.com\n"
Packit Service 82fcde
     "; search[1]: example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "nameserver ::1\n"
Packit Service 82fcde
     "nameserver 192.0.2.2\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
     "; nameserver[1]: [::1]:53\n"
Packit Service 82fcde
     "; nameserver[2]: [192.0.2.2]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "out-of-range option vales",
Packit Service 82fcde
     .conf = "options use-vc timeout:999 attempts:999 ndots:99\n"
Packit Service 82fcde
     "search example.com\n",
Packit Service 82fcde
     .expected = "options ndots:15 timeout:30 attempts:5 use-vc\n"
Packit Service 82fcde
     "search example.com\n"
Packit Service 82fcde
     "; search[0]: example.com\n"
Packit Service 82fcde
     "nameserver 127.0.0.1\n"
Packit Service 82fcde
     "; nameserver[0]: [127.0.0.1]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "repeated directives",
Packit Service 82fcde
     .conf = "options ndots:3 use-vc\n"
Packit Service 82fcde
     "options edns0 ndots:2\n"
Packit Service 82fcde
     "domain corp.example\n"
Packit Service 82fcde
     "search example.net corp.example.com example.com\n"
Packit Service 82fcde
     "search example.org\n"
Packit Service 82fcde
     "search\n",
Packit Service 82fcde
     .expected = "options ndots:2 use-vc edns0\n"
Packit Service 82fcde
     "search example.org\n"
Packit Service 82fcde
     "; search[0]: example.org\n"
Packit Service 82fcde
     "nameserver 127.0.0.1\n"
Packit Service 82fcde
     "; nameserver[0]: [127.0.0.1]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "many name servers, sortlist",
Packit Service 82fcde
     .conf = "options single-request\n"
Packit Service 82fcde
     "search example.org example.com example.net corp.example.com\n"
Packit Service 82fcde
     "sortlist 192.0.2.0/255.255.255.0\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "nameserver 192.0.2.2\n"
Packit Service 82fcde
     "nameserver 192.0.2.3\n"
Packit Service 82fcde
     "nameserver 192.0.2.4\n"
Packit Service 82fcde
     "nameserver 192.0.2.5\n"
Packit Service 82fcde
     "nameserver 192.0.2.6\n"
Packit Service 82fcde
     "nameserver 192.0.2.7\n"
Packit Service 82fcde
     "nameserver 192.0.2.8\n",
Packit Service 82fcde
     .expected = "options single-request\n"
Packit Service 82fcde
     "search example.org example.com example.net corp.example.com\n"
Packit Service 82fcde
     "; search[0]: example.org\n"
Packit Service 82fcde
     "; search[1]: example.com\n"
Packit Service 82fcde
     "; search[2]: example.net\n"
Packit Service 82fcde
     "; search[3]: corp.example.com\n"
Packit Service 82fcde
     "sortlist 192.0.2.0/255.255.255.0\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "nameserver 192.0.2.2\n"
Packit Service 82fcde
     "nameserver 192.0.2.3\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
     "; nameserver[1]: [192.0.2.2]:53\n"
Packit Service 82fcde
     "; nameserver[2]: [192.0.2.3]:53\n"
Packit Service 82fcde
     "; nameserver[3]: [192.0.2.4]:53\n"
Packit Service 82fcde
     "; nameserver[4]: [192.0.2.5]:53\n"
Packit Service 82fcde
     "; nameserver[5]: [192.0.2.6]:53\n"
Packit Service 82fcde
     "; nameserver[6]: [192.0.2.7]:53\n"
Packit Service 82fcde
     "; nameserver[7]: [192.0.2.8]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "IPv4 and IPv6 nameservers",
Packit Service 82fcde
     .conf = "options single-request\n"
Packit Service 82fcde
     "search example.org example.com example.net corp.example.com"
Packit Service 82fcde
     " legacy.example.com\n"
Packit Service 82fcde
     "sortlist 192.0.2.0\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "nameserver 2001:db8::2\n"
Packit Service 82fcde
     "nameserver 192.0.2.3\n"
Packit Service 82fcde
     "nameserver 2001:db8::4\n"
Packit Service 82fcde
     "nameserver 192.0.2.5\n"
Packit Service 82fcde
     "nameserver 2001:db8::6\n"
Packit Service 82fcde
     "nameserver 192.0.2.7\n"
Packit Service 82fcde
     "nameserver 2001:db8::8\n",
Packit Service 82fcde
     .expected = "options single-request\n"
Packit Service 82fcde
     "search example.org example.com example.net corp.example.com"
Packit Service 82fcde
     " legacy.example.com\n"
Packit Service 82fcde
     "; search[0]: example.org\n"
Packit Service 82fcde
     "; search[1]: example.com\n"
Packit Service 82fcde
     "; search[2]: example.net\n"
Packit Service 82fcde
     "; search[3]: corp.example.com\n"
Packit Service 82fcde
     "; search[4]: legacy.example.com\n"
Packit Service 82fcde
     "sortlist 192.0.2.0/255.255.255.0\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "nameserver 2001:db8::2\n"
Packit Service 82fcde
     "nameserver 192.0.2.3\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
     "; nameserver[1]: [2001:db8::2]:53\n"
Packit Service 82fcde
     "; nameserver[2]: [192.0.2.3]:53\n"
Packit Service 82fcde
     "; nameserver[3]: [2001:db8::4]:53\n"
Packit Service 82fcde
     "; nameserver[4]: [192.0.2.5]:53\n"
Packit Service 82fcde
     "; nameserver[5]: [2001:db8::6]:53\n"
Packit Service 82fcde
     "; nameserver[6]: [192.0.2.7]:53\n"
Packit Service 82fcde
     "; nameserver[7]: [2001:db8::8]:53\n",
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "garbage after nameserver",
Packit Service 82fcde
     .conf = "nameserver 192.0.2.1 garbage\n"
Packit Service 82fcde
     "nameserver 192.0.2.2:5353\n"
Packit Service 82fcde
     "nameserver 192.0.2.3 5353\n",
Packit Service 82fcde
     .expected = "search example.com\n"
Packit Service 82fcde
     "; search[0]: example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "nameserver 192.0.2.3\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
     "; nameserver[1]: [192.0.2.3]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "RES_OPTIONS is cummulative",
Packit Service 82fcde
     .conf = "options timeout:7 ndots:2 use-vc\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n",
Packit Service 82fcde
     .expected = "options ndots:3 timeout:7 attempts:5 use-vc edns0\n"
Packit Service 82fcde
     "search example.com\n"
Packit Service 82fcde
     "; search[0]: example.com\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n",
Packit Service 82fcde
     .res_options = "attempts:5 ndots:3 edns0 ",
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "many search list entries (bug 19569)",
Packit Service 82fcde
     .conf = "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "search corp.example.com support.example.com"
Packit Service 82fcde
     " community.example.org wan.example.net vpn.example.net"
Packit Service 82fcde
     " example.com example.org example.net\n",
Packit Service 82fcde
     .expected = "search corp.example.com support.example.com"
Packit Service 82fcde
     " community.example.org wan.example.net vpn.example.net example.com\n"
Packit Service 82fcde
     "; search[0]: corp.example.com\n"
Packit Service 82fcde
     "; search[1]: support.example.com\n"
Packit Service 82fcde
     "; search[2]: community.example.org\n"
Packit Service 82fcde
     "; search[3]: wan.example.net\n"
Packit Service 82fcde
     "; search[4]: vpn.example.net\n"
Packit Service 82fcde
     "; search[5]: example.com\n"
Packit Service 82fcde
     "; search[6]: example.org\n"
Packit Service 82fcde
     "; search[7]: example.net\n"
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    {.name = "very long search list entries (bug 21475)",
Packit Service 82fcde
     .conf = "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "search example.com "
Packit Service 82fcde
#define H63 "this-host-name-is-longer-than-yours-yes-I-really-really-mean-it"
Packit Service 82fcde
#define D63 "this-domain-name-is-as-long-as-the-previous-name--63-characters"
Packit Service 82fcde
     " " H63 "." D63 ".example.org"
Packit Service 82fcde
     " " H63 "." D63 ".example.net\n",
Packit Service 82fcde
     .expected = "search example.com " H63 "." D63 ".example.org\n"
Packit Service 82fcde
     "; search[0]: example.com\n"
Packit Service 82fcde
     "; search[1]: " H63 "." D63 ".example.org\n"
Packit Service 82fcde
     "; search[2]: " H63 "." D63 ".example.net\n"
Packit Service 82fcde
#undef H63
Packit Service 82fcde
#undef D63
Packit Service 82fcde
     "nameserver 192.0.2.1\n"
Packit Service 82fcde
     "; nameserver[0]: [192.0.2.1]:53\n"
Packit Service 82fcde
    },
Packit Service 82fcde
    { NULL }
Packit Service 82fcde
  };
Packit Service 82fcde
Packit Service 82fcde
/* Run the indicated test case.  This function assumes that the chroot
Packit Service 82fcde
   contents has already been set up.  */
Packit Service 82fcde
static void
Packit Service 82fcde
test_file_contents (const struct test_case *t)
Packit Service 82fcde
{
Packit Service 82fcde
#if TEST_THREAD
Packit Service 82fcde
  for (int do_thread = 0; do_thread < 2; ++do_thread)
Packit Service 82fcde
#endif
Packit Service 82fcde
    for (int init_method = 0; init_method <= test_init_method_last;
Packit Service 82fcde
         ++init_method)
Packit Service 82fcde
      {
Packit Service 82fcde
        if (test_verbose > 0)
Packit Service 82fcde
          printf ("info:  testing init method %s\n",
Packit Service 82fcde
                  test_init_names[init_method]);
Packit Service 82fcde
        struct test_context ctx = { .init = init_method, .t = t };
Packit Service 82fcde
        void (*func) (void *) = run_res_init;
Packit Service 82fcde
#if TEST_THREAD
Packit Service 82fcde
        if (do_thread)
Packit Service 82fcde
          func = run_res_init_on_thread;
Packit Service 82fcde
#endif
Packit Service 82fcde
        struct support_capture_subprocess proc
Packit Service 82fcde
          = support_capture_subprocess (func, &ctx;;
Packit Service 82fcde
        if (strcmp (proc.out.buffer, t->expected) != 0)
Packit Service 82fcde
          {
Packit Service 82fcde
            support_record_failure ();
Packit Service 82fcde
            printf ("error: output mismatch for %s (init method %s)\n",
Packit Service 82fcde
                    t->name, test_init_names[init_method]);
Packit Service 82fcde
            support_run_diff ("expected", t->expected,
Packit Service 82fcde
                              "actual", proc.out.buffer);
Packit Service 82fcde
          }
Packit Service 82fcde
        support_capture_subprocess_check (&proc, t->name, 0,
Packit Service 82fcde
                                          sc_allow_stdout);
Packit Service 82fcde
        support_capture_subprocess_free (&proc;;
Packit Service 82fcde
      }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Special tests which do not follow the general pattern.  */
Packit Service 82fcde
enum { special_tests_count = 11 };
Packit Service 82fcde
Packit Service 82fcde
/* Implementation of special tests.  */
Packit Service 82fcde
static void
Packit Service 82fcde
special_test_callback (void *closure)
Packit Service 82fcde
{
Packit Service 82fcde
  unsigned int *test_indexp = closure;
Packit Service 82fcde
  unsigned test_index = *test_indexp;
Packit Service 82fcde
  TEST_VERIFY (test_index < special_tests_count);
Packit Service 82fcde
  if (test_verbose > 0)
Packit Service 82fcde
    printf ("info: special test %u\n", test_index);
Packit Service 82fcde
  xchroot (chroot_env->path_chroot);
Packit Service 82fcde
Packit Service 82fcde
  switch (test_index)
Packit Service 82fcde
    {
Packit Service 82fcde
    case 0:
Packit Service 82fcde
    case 1:
Packit Service 82fcde
      /* Second res_init with missing or empty file preserves
Packit Service 82fcde
         flags.  */
Packit Service 82fcde
      if (test_index == 1)
Packit Service 82fcde
        TEST_VERIFY (unlink (_PATH_RESCONF) == 0);
Packit Service 82fcde
      _res.options = RES_USE_EDNS0;
Packit Service 82fcde
      TEST_VERIFY (res_init () == 0);
Packit Service 82fcde
      /* First res_init clears flag.  */
Packit Service 82fcde
      TEST_VERIFY (!(_res.options & RES_USE_EDNS0));
Packit Service 82fcde
      _res.options |= RES_USE_EDNS0;
Packit Service 82fcde
      TEST_VERIFY (res_init () == 0);
Packit Service 82fcde
      /* Second res_init preserves flag.  */
Packit Service 82fcde
      TEST_VERIFY (_res.options & RES_USE_EDNS0);
Packit Service 82fcde
      if (test_index == 1)
Packit Service 82fcde
        /* Restore empty file.  */
Packit Service 82fcde
        support_write_file_string (_PATH_RESCONF, "");
Packit Service 82fcde
      break;
Packit Service 82fcde
Packit Service 82fcde
    case 2:
Packit Service 82fcde
      /* Second res_init is cumulative.  */
Packit Service 82fcde
      support_write_file_string (_PATH_RESCONF,
Packit Service 82fcde
                                 "options rotate\n"
Packit Service 82fcde
                                 "nameserver 192.0.2.1\n");
Packit Service 82fcde
      _res.options = RES_USE_EDNS0;
Packit Service 82fcde
      TEST_VERIFY (res_init () == 0);
Packit Service 82fcde
      /* First res_init clears flag.  */
Packit Service 82fcde
      TEST_VERIFY (!(_res.options & RES_USE_EDNS0));
Packit Service 82fcde
      /* And sets RES_ROTATE.  */
Packit Service 82fcde
      TEST_VERIFY (_res.options & RES_ROTATE);
Packit Service 82fcde
      _res.options |= RES_USE_EDNS0;
Packit Service 82fcde
      TEST_VERIFY (res_init () == 0);
Packit Service 82fcde
      /* Second res_init preserves flag.  */
Packit Service 82fcde
      TEST_VERIFY (_res.options & RES_USE_EDNS0);
Packit Service 82fcde
      TEST_VERIFY (_res.options & RES_ROTATE);
Packit Service 82fcde
      /* Reloading the configuration does not clear the explicitly set
Packit Service 82fcde
         flag.  */
Packit Service 82fcde
      support_write_file_string (_PATH_RESCONF,
Packit Service 82fcde
                                 "nameserver 192.0.2.1\n"
Packit Service 82fcde
                                 "nameserver 192.0.2.2\n");
Packit Service 82fcde
      TEST_VERIFY (res_init () == 0);
Packit Service 82fcde
      TEST_VERIFY (_res.nscount == 2);
Packit Service 82fcde
      TEST_VERIFY (_res.options & RES_USE_EDNS0);
Packit Service 82fcde
      /* Whether RES_ROTATE (originally in resolv.conf, now removed)
Packit Service 82fcde
         should be preserved is subject to debate.  See bug 21701.  */
Packit Service 82fcde
      /* TEST_VERIFY (!(_res.options & RES_ROTATE)); */
Packit Service 82fcde
      break;
Packit Service 82fcde
Packit Service 82fcde
    case 3:
Packit Service 82fcde
    case 4:
Packit Service 82fcde
    case 5:
Packit Service 82fcde
    case 6:
Packit Service 82fcde
      support_write_file_string (_PATH_RESCONF,
Packit Service 82fcde
                                 "options edns0\n"
Packit Service 82fcde
                                 "nameserver 192.0.2.1\n");
Packit Service 82fcde
      goto reload_tests;
Packit Service 82fcde
    case 7: /* 7 and the following tests are with no-reload.  */
Packit Service 82fcde
    case 8:
Packit Service 82fcde
    case 9:
Packit Service 82fcde
    case 10:
Packit Service 82fcde
        support_write_file_string (_PATH_RESCONF,
Packit Service 82fcde
                                   "options edns0 no-reload\n"
Packit Service 82fcde
                                   "nameserver 192.0.2.1\n");
Packit Service 82fcde
        /* Fall through.  */
Packit Service 82fcde
    reload_tests:
Packit Service 82fcde
      for (int iteration = 0; iteration < 2; ++iteration)
Packit Service 82fcde
        {
Packit Service 82fcde
          switch (test_index)
Packit Service 82fcde
            {
Packit Service 82fcde
            case 3:
Packit Service 82fcde
            case 7:
Packit Service 82fcde
              TEST_VERIFY (res_init () == 0);
Packit Service 82fcde
              break;
Packit Service 82fcde
            case 4:
Packit Service 82fcde
            case 8:
Packit Service 82fcde
              {
Packit Service 82fcde
                unsigned char buf[512];
Packit Service 82fcde
                TEST_VERIFY
Packit Service 82fcde
                  (res_mkquery (QUERY, test_hostname, C_IN, T_A,
Packit Service 82fcde
                                NULL, 0, NULL, buf, sizeof (buf)) > 0);
Packit Service 82fcde
              }
Packit Service 82fcde
              break;
Packit Service 82fcde
            case 5:
Packit Service 82fcde
            case 9:
Packit Service 82fcde
              gethostbyname (test_hostname);
Packit Service 82fcde
              break;
Packit Service 82fcde
            case 6:
Packit Service 82fcde
            case 10:
Packit Service 82fcde
              {
Packit Service 82fcde
                struct addrinfo *ai;
Packit Service 82fcde
                (void) getaddrinfo (test_hostname, NULL, NULL, &ai;;
Packit Service 82fcde
              }
Packit Service 82fcde
              break;
Packit Service 82fcde
            }
Packit Service 82fcde
          /* test_index == 7 is res_init and performs a reload even
Packit Service 82fcde
             with no-reload.  */
Packit Service 82fcde
          if (iteration == 0 || test_index > 7)
Packit Service 82fcde
            {
Packit Service 82fcde
              TEST_VERIFY (_res.options & RES_USE_EDNS0);
Packit Service 82fcde
              TEST_VERIFY (!(_res.options & RES_ROTATE));
Packit Service 82fcde
              if (test_index < 7)
Packit Service 82fcde
                TEST_VERIFY (!(_res.options & RES_NORELOAD));
Packit Service 82fcde
              else
Packit Service 82fcde
                TEST_VERIFY (_res.options & RES_NORELOAD);
Packit Service 82fcde
              TEST_VERIFY (_res.nscount == 1);
Packit Service 82fcde
              /* File change triggers automatic reloading.  */
Packit Service 82fcde
              support_write_file_string (_PATH_RESCONF,
Packit Service 82fcde
                                         "options rotate\n"
Packit Service 82fcde
                                         "nameserver 192.0.2.1\n"
Packit Service 82fcde
                                         "nameserver 192.0.2.2\n");
Packit Service 82fcde
            }
Packit Service 82fcde
          else
Packit Service 82fcde
            {
Packit Service 82fcde
              if (test_index != 3 && test_index != 7)
Packit Service 82fcde
                /* test_index 3, 7 are res_init; this function does
Packit Service 82fcde
                   not reset flags.  See bug 21701.  */
Packit Service 82fcde
                TEST_VERIFY (!(_res.options & RES_USE_EDNS0));
Packit Service 82fcde
              TEST_VERIFY (_res.options & RES_ROTATE);
Packit Service 82fcde
              TEST_VERIFY (_res.nscount == 2);
Packit Service 82fcde
            }
Packit Service 82fcde
        }
Packit Service 82fcde
      break;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#if TEST_THREAD
Packit Service 82fcde
/* Helper function which calls special_test_callback from a
Packit Service 82fcde
   thread.  */
Packit Service 82fcde
static void *
Packit Service 82fcde
special_test_thread_func (void *closure)
Packit Service 82fcde
{
Packit Service 82fcde
  special_test_callback (closure);
Packit Service 82fcde
  return NULL;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/* Variant of special_test_callback which runs the function on a
Packit Service 82fcde
   non-main thread.  */
Packit Service 82fcde
static void
Packit Service 82fcde
run_special_test_on_thread (void *closure)
Packit Service 82fcde
{
Packit Service 82fcde
  xpthread_join (xpthread_create (NULL, special_test_thread_func, closure));
Packit Service 82fcde
}
Packit Service 82fcde
#endif /* TEST_THREAD */
Packit Service 82fcde
Packit Service 82fcde
/* Perform the requested special test in a subprocess using
Packit Service 82fcde
   special_test_callback.  */
Packit Service 82fcde
static void
Packit Service 82fcde
special_test (unsigned int test_index)
Packit Service 82fcde
{
Packit Service 82fcde
#if TEST_THREAD
Packit Service 82fcde
  for (int do_thread = 0; do_thread < 2; ++do_thread)
Packit Service 82fcde
#endif
Packit Service 82fcde
    {
Packit Service 82fcde
      void (*func) (void *) = special_test_callback;
Packit Service 82fcde
#if TEST_THREAD
Packit Service 82fcde
      if (do_thread)
Packit Service 82fcde
        func = run_special_test_on_thread;
Packit Service 82fcde
#endif
Packit Service 82fcde
      struct support_capture_subprocess proc
Packit Service 82fcde
        = support_capture_subprocess (func, &test_index);
Packit Service 82fcde
      char *test_name = xasprintf ("special test %u", test_index);
Packit Service 82fcde
      if (strcmp (proc.out.buffer, "") != 0)
Packit Service 82fcde
        {
Packit Service 82fcde
          support_record_failure ();
Packit Service 82fcde
          printf ("error: output mismatch for %s\n", test_name);
Packit Service 82fcde
          support_run_diff ("expected", "",
Packit Service 82fcde
                            "actual", proc.out.buffer);
Packit Service 82fcde
        }
Packit Service 82fcde
      support_capture_subprocess_check (&proc, test_name, 0, sc_allow_stdout);
Packit Service 82fcde
      free (test_name);
Packit Service 82fcde
      support_capture_subprocess_free (&proc;;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Dummy DNS server.  It ensures that the probe queries sent by
Packit Service 82fcde
   gethostbyname and getaddrinfo receive a reply even if the system
Packit Service 82fcde
   applies a very strict rate limit to localhost.  */
Packit Service 82fcde
static pid_t
Packit Service 82fcde
start_dummy_server (void)
Packit Service 82fcde
{
Packit Service 82fcde
  int server_socket = xsocket (AF_INET, SOCK_DGRAM, 0);
Packit Service 82fcde
  {
Packit Service 82fcde
    struct sockaddr_in sin =
Packit Service 82fcde
      {
Packit Service 82fcde
        .sin_family = AF_INET,
Packit Service 82fcde
        .sin_addr = { .s_addr = htonl (INADDR_LOOPBACK) },
Packit Service 82fcde
        .sin_port = htons (53),
Packit Service 82fcde
      };
Packit Service 82fcde
    int ret = bind (server_socket, (struct sockaddr *) &sin, sizeof (sin));
Packit Service 82fcde
    if (ret < 0)
Packit Service 82fcde
      {
Packit Service 82fcde
        if (errno == EACCES)
Packit Service 82fcde
          /* The port is reserved, which means we cannot start the
Packit Service 82fcde
             server.  */
Packit Service 82fcde
          return -1;
Packit Service 82fcde
        FAIL_EXIT1 ("cannot bind socket to port 53: %m");
Packit Service 82fcde
      }
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
  pid_t pid = xfork ();
Packit Service 82fcde
  if (pid == 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Child process.  Echo back queries as SERVFAIL responses.  */
Packit Service 82fcde
      while (true)
Packit Service 82fcde
        {
Packit Service 82fcde
          union
Packit Service 82fcde
          {
Packit Service 82fcde
            HEADER header;
Packit Service 82fcde
            unsigned char bytes[512];
Packit Service 82fcde
          } packet;
Packit Service 82fcde
          struct sockaddr_in sin;
Packit Service 82fcde
          socklen_t sinlen = sizeof (sin);
Packit Service 82fcde
Packit Service 82fcde
          ssize_t ret = recvfrom
Packit Service 82fcde
            (server_socket, &packet, sizeof (packet),
Packit Service 82fcde
             MSG_NOSIGNAL, (struct sockaddr *) &sin, &sinlen);
Packit Service 82fcde
          if (ret < 0)
Packit Service 82fcde
            FAIL_EXIT1 ("recvfrom on fake server socket: %m");
Packit Service 82fcde
          if (ret > sizeof (HEADER))
Packit Service 82fcde
            {
Packit Service 82fcde
              /* Turn the query into a SERVFAIL response.  */
Packit Service 82fcde
              packet.header.qr = 1;
Packit Service 82fcde
              packet.header.rcode = ns_r_servfail;
Packit Service 82fcde
Packit Service 82fcde
              /* Send the response.  */
Packit Service 82fcde
              ret = sendto (server_socket, &packet, ret,
Packit Service 82fcde
                            MSG_NOSIGNAL, (struct sockaddr *) &sin, sinlen);
Packit Service 82fcde
              if (ret < 0)
Packit Service 82fcde
                /* The peer may have closed socket prematurely, so
Packit Service 82fcde
                   this is not an error.  */
Packit Service 82fcde
                printf ("warning: sending DNS server reply: %m\n");
Packit Service 82fcde
            }
Packit Service 82fcde
        }
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* In the parent, close the socket.  */
Packit Service 82fcde
  xclose (server_socket);
Packit Service 82fcde
Packit Service 82fcde
  return pid;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
do_test (void)
Packit Service 82fcde
{
Packit Service 82fcde
  support_become_root ();
Packit Service 82fcde
  support_enter_network_namespace ();
Packit Service 82fcde
  if (!support_in_uts_namespace () || !support_can_chroot ())
Packit Service 82fcde
    return EXIT_UNSUPPORTED;
Packit Service 82fcde
Packit Service 82fcde
  /* We are in an UTS namespace, so we can set the host name without
Packit Service 82fcde
     altering the state of the entire system.  */
Packit Service 82fcde
  if (sethostname (test_hostname, strlen (test_hostname)) != 0)
Packit Service 82fcde
    FAIL_EXIT1 ("sethostname: %m");
Packit Service 82fcde
Packit Service 82fcde
  /* These environment variables affect resolv.conf parsing.  */
Packit Service 82fcde
  unsetenv ("LOCALDOMAIN");
Packit Service 82fcde
  unsetenv ("RES_OPTIONS");
Packit Service 82fcde
Packit Service 82fcde
  /* Ensure that the chroot setup worked.  */
Packit Service 82fcde
  {
Packit Service 82fcde
    struct support_capture_subprocess proc
Packit Service 82fcde
      = support_capture_subprocess (check_chroot_working, NULL);
Packit Service 82fcde
    support_capture_subprocess_check (&proc, "chroot", 0, sc_allow_none);
Packit Service 82fcde
    support_capture_subprocess_free (&proc;;
Packit Service 82fcde
  }
Packit Service 82fcde
Packit Service 82fcde
  pid_t server = start_dummy_server ();
Packit Service 82fcde
Packit Service 82fcde
  for (size_t i = 0; test_cases[i].name != NULL; ++i)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (test_verbose > 0)
Packit Service 82fcde
        printf ("info: running test: %s\n", test_cases[i].name);
Packit Service 82fcde
      TEST_VERIFY (test_cases[i].conf != NULL);
Packit Service 82fcde
      TEST_VERIFY (test_cases[i].expected != NULL);
Packit Service 82fcde
Packit Service 82fcde
      support_write_file_string (chroot_env->path_resolv_conf,
Packit Service 82fcde
                                 test_cases[i].conf);
Packit Service 82fcde
Packit Service 82fcde
      test_file_contents (&test_cases[i]);
Packit Service 82fcde
Packit Service 82fcde
      /* The expected output from the empty file test is used for
Packit Service 82fcde
         further tests.  */
Packit Service 82fcde
      if (test_cases[i].conf[0] == '\0')
Packit Service 82fcde
        {
Packit Service 82fcde
          if (test_verbose > 0)
Packit Service 82fcde
            printf ("info:  special test: missing file\n");
Packit Service 82fcde
          TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0);
Packit Service 82fcde
          test_file_contents (&test_cases[i]);
Packit Service 82fcde
Packit Service 82fcde
          if (test_verbose > 0)
Packit Service 82fcde
            printf ("info:  special test: dangling symbolic link\n");
Packit Service 82fcde
          TEST_VERIFY (symlink ("does-not-exist", chroot_env->path_resolv_conf) == 0);
Packit Service 82fcde
          test_file_contents (&test_cases[i]);
Packit Service 82fcde
          TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0);
Packit Service 82fcde
Packit Service 82fcde
          if (test_verbose > 0)
Packit Service 82fcde
            printf ("info:  special test: unreadable file\n");
Packit Service 82fcde
          support_write_file_string (chroot_env->path_resolv_conf, "");
Packit Service 82fcde
          TEST_VERIFY (chmod (chroot_env->path_resolv_conf, 0) == 0);
Packit Service 82fcde
          test_file_contents (&test_cases[i]);
Packit Service 82fcde
Packit Service 82fcde
          /* Restore the empty file.  */
Packit Service 82fcde
          TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0);
Packit Service 82fcde
          support_write_file_string (chroot_env->path_resolv_conf, "");
Packit Service 82fcde
        }
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* The tests which do not follow a regular pattern.  */
Packit Service 82fcde
  for (unsigned int test_index = 0;
Packit Service 82fcde
       test_index < special_tests_count; ++test_index)
Packit Service 82fcde
    special_test (test_index);
Packit Service 82fcde
Packit Service 82fcde
  if (server > 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (kill (server, SIGTERM) < 0)
Packit Service 82fcde
        FAIL_EXIT1 ("could not terminate server process: %m");
Packit Service 82fcde
      xwaitpid (server, NULL, 0);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  support_chroot_free (chroot_env);
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#define PREPARE prepare
Packit Service 82fcde
#include <support/test-driver.c>