1 /* Test parsing of /etc/resolv.conf. Genric version.
2 Copyright (C) 2017 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 /* Before including this file, TEST_THREAD has to be defined to 0 or
20 1, depending on whether the threading tests should be compiled
23 #include <arpa/inet.h>
25 #include <gnu/lib-names.h>
27 #include <resolv/resolv-internal.h> /* For DEPRECATED_RES_USE_INET6. */
28 #include <resolv/resolv_context.h>
31 #include <support/capture_subprocess.h>
32 #include <support/check.h>
33 #include <support/namespace.h>
34 #include <support/run_diff.h>
35 #include <support/support.h>
36 #include <support/temp_file.h>
37 #include <support/test-driver.h>
38 #include <support/xsocket.h>
39 #include <support/xstdio.h>
40 #include <support/xunistd.h>
43 # include <support/xthread.h>
46 /* This is the host name used to ensure predictable behavior of
48 static const char *const test_hostname
= "www.example.com";
50 /* Path to the test root directory. */
51 static char *path_chroot
;
53 /* Path to resolv.conf under path_chroot (outside the chroot). */
54 static char *path_resolv_conf
;
57 prepare (int argc
, char **argv
)
59 path_chroot
= xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir
);
60 if (mkdtemp (path_chroot
) == NULL
)
61 FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", path_chroot
);
62 add_temp_file (path_chroot
);
64 /* Create the /etc directory in the chroot environment. */
65 char *path_etc
= xasprintf ("%s/etc", path_chroot
);
66 xmkdir (path_etc
, 0777);
67 add_temp_file (path_etc
);
69 /* Create an empty resolv.conf file. */
70 path_resolv_conf
= xasprintf ("%s/resolv.conf", path_etc
);
71 add_temp_file (path_resolv_conf
);
72 support_write_file_string (path_resolv_conf
, "");
76 /* valgrind needs a temporary directory in the chroot. */
78 char *path_tmp
= xasprintf ("%s/tmp", path_chroot
);
79 xmkdir (path_tmp
, 0777);
80 add_temp_file (path_tmp
);
85 /* Verify that the chroot environment has been set up. */
87 check_chroot_working (void *closure
)
89 xchroot (path_chroot
);
90 FILE *fp
= xfopen (_PATH_RESCONF
, "r");
93 TEST_VERIFY_EXIT (res_init () == 0);
94 TEST_VERIFY (_res
.options
& RES_INIT
);
97 if (gethostname (buf
, sizeof (buf
)) < 0)
98 FAIL_EXIT1 ("gethostname: %m");
99 if (strcmp (buf
, test_hostname
) != 0)
100 FAIL_EXIT1 ("unexpected host name: %s", buf
);
103 /* If FLAG is set in *OPTIONS, write NAME to FP, and clear it in
106 print_option_flag (FILE *fp
, int *options
, int flag
, const char *name
)
110 fprintf (fp
, " %s", name
);
115 /* Write a decoded version of the resolver configuration *RESP to the
118 print_resp (FILE *fp
, res_state resp
)
120 struct resolv_context
*ctx
= __resolv_context_get_override (resp
);
121 TEST_VERIFY_EXIT (ctx
!= NULL
);
122 if (ctx
->conf
== NULL
)
123 fprintf (fp
, "; extended resolver state missing\n");
125 /* The options directive. */
127 /* RES_INIT is used internally for tracking initialization. */
128 TEST_VERIFY (resp
->options
& RES_INIT
);
129 /* Also mask out other default flags which cannot be set through
130 the options directive. */
132 = resp
->options
& ~(RES_INIT
| RES_RECURSE
| RES_DEFNAMES
| RES_DNSRCH
);
135 || resp
->retrans
!= RES_TIMEOUT
136 || resp
->retry
!= RES_DFLRETRY
)
138 fputs ("options", fp
);
139 if (resp
->ndots
!= 1)
140 fprintf (fp
, " ndots:%d", resp
->ndots
);
141 if (resp
->retrans
!= RES_TIMEOUT
)
142 fprintf (fp
, " timeout:%d", resp
->retrans
);
143 if (resp
->retry
!= RES_DFLRETRY
)
144 fprintf (fp
, " attempts:%d", resp
->retry
);
145 print_option_flag (fp
, &options
, RES_USEVC
, "use-vc");
146 print_option_flag (fp
, &options
, DEPRECATED_RES_USE_INET6
, "inet6");
147 print_option_flag (fp
, &options
, RES_ROTATE
, "rotate");
148 print_option_flag (fp
, &options
, RES_USE_EDNS0
, "edns0");
149 print_option_flag (fp
, &options
, RES_SNGLKUP
,
151 print_option_flag (fp
, &options
, RES_SNGLKUPREOP
,
152 "single-request-reopen");
153 print_option_flag (fp
, &options
, RES_NOTLDQUERY
, "no-tld-query");
156 fprintf (fp
, "; error: unresolved option bits: 0x%x\n", options
);
160 /* The search and domain directives. */
161 if (resp
->dnsrch
[0] != NULL
)
163 fputs ("search", fp
);
164 for (int i
= 0; i
< MAXDNSRCH
&& resp
->dnsrch
[i
] != NULL
; ++i
)
167 fputs (resp
->dnsrch
[i
], fp
);
171 else if (resp
->defdname
[0] != '\0')
172 fprintf (fp
, "domain %s\n", resp
->defdname
);
174 /* The extended search path. */
179 const char *name
= __resolv_context_search_list (ctx
, i
);
182 fprintf (fp
, "; search[%zu]: %s\n", i
, name
);
187 /* The sortlist directive. */
190 fputs ("sortlist", fp
);
191 for (int i
= 0; i
< resp
->nsort
&& i
< MAXRESOLVSORT
; ++i
)
194 if (inet_ntop (AF_INET
, &resp
->sort_list
[i
].addr
,
195 net
, sizeof (net
)) == NULL
)
196 FAIL_EXIT1 ("inet_ntop: %m\n");
198 if (inet_ntop (AF_INET
, &resp
->sort_list
[i
].mask
,
199 mask
, sizeof (mask
)) == NULL
)
200 FAIL_EXIT1 ("inet_ntop: %m\n");
201 fprintf (fp
, " %s/%s", net
, mask
);
206 /* The nameserver directives. */
207 for (size_t i
= 0; i
< resp
->nscount
; ++i
)
209 char host
[NI_MAXHOST
];
210 char service
[NI_MAXSERV
];
212 /* See get_nsaddr in res_send.c. */
215 if (resp
->nsaddr_list
[i
].sin_family
== 0
216 && resp
->_u
._ext
.nsaddrs
[i
] != NULL
)
218 addr
= resp
->_u
._ext
.nsaddrs
[i
];
219 addrlen
= sizeof (*resp
->_u
._ext
.nsaddrs
[i
]);
223 addr
= &resp
->nsaddr_list
[i
];
224 addrlen
= sizeof (resp
->nsaddr_list
[i
]);
227 int ret
= getnameinfo (addr
, addrlen
,
228 host
, sizeof (host
), service
, sizeof (service
),
229 NI_NUMERICHOST
| NI_NUMERICSERV
);
232 if (ret
== EAI_SYSTEM
)
233 fprintf (fp
, "; error: getnameinfo: %m\n");
235 fprintf (fp
, "; error: getnameinfo: %s\n", gai_strerror (ret
));
239 fprintf (fp
, "nameserver %s\n", host
);
240 if (strcmp (service
, "53") != 0)
241 fprintf (fp
, "; unrepresentable port number %s\n\n", service
);
245 /* The extended name server list. */
250 const struct sockaddr
*addr
= __resolv_context_nameserver (ctx
, i
);
254 switch (addr
->sa_family
)
257 addrlen
= sizeof (struct sockaddr_in
);
260 addrlen
= sizeof (struct sockaddr_in6
);
263 FAIL_EXIT1 ("invalid address family %d", addr
->sa_family
);
266 char host
[NI_MAXHOST
];
267 char service
[NI_MAXSERV
];
268 int ret
= getnameinfo (addr
, addrlen
,
269 host
, sizeof (host
), service
, sizeof (service
),
270 NI_NUMERICHOST
| NI_NUMERICSERV
);
274 if (ret
== EAI_SYSTEM
)
275 fprintf (fp
, "; error: getnameinfo: %m\n");
277 fprintf (fp
, "; error: getnameinfo: %s\n", gai_strerror (ret
));
280 fprintf (fp
, "; nameserver[%zu]: [%s]:%s\n", i
, host
, service
);
285 TEST_VERIFY (!ferror (fp
));
287 __resolv_context_put (ctx
);
290 /* Parameters of one test case. */
293 /* A short, descriptive name of the test. */
296 /* The contents of the /etc/resolv.conf file. */
299 /* The expected output from print_resp. */
300 const char *expected
;
302 /* Setting for the LOCALDOMAIN environment variable. NULL if the
303 variable is not to be set. */
304 const char *localdomain
;
306 /* Setting for the RES_OPTIONS environment variable. NULL if the
307 variable is not to be set. */
308 const char *res_options
;
318 test_init_method_last
= test_getaddrinfo
321 static const char *const test_init_names
[] =
323 [test_init
] = "res_init",
324 [test_ninit
] = "res_ninit",
325 [test_mkquery
] = "res_mkquery",
326 [test_gethostbyname
] = "gethostbyname",
327 [test_getaddrinfo
] = "getaddrinfo",
330 /* Closure argument for run_res_init. */
334 const struct test_case
*t
;
338 setup_nss_dns_and_chroot (void)
340 /* Load nss_dns outside of the chroot. */
341 if (dlopen (LIBNSS_DNS_SO
, RTLD_LAZY
) == NULL
)
342 FAIL_EXIT1 ("could not load " LIBNSS_DNS_SO
": %s", dlerror ());
343 xchroot (path_chroot
);
344 /* Force the use of nss_dns. */
345 __nss_configure_lookup ("hosts", "dns");
348 /* Run res_ninit or res_init in a subprocess and dump the parsed
349 resolver state to standard output. */
351 run_res_init (void *closure
)
353 struct test_context
*ctx
= closure
;
354 TEST_VERIFY (getenv ("LOCALDOMAIN") == NULL
);
355 TEST_VERIFY (getenv ("RES_OPTIONS") == NULL
);
356 if (ctx
->t
->localdomain
!= NULL
)
357 setenv ("LOCALDOMAIN", ctx
->t
->localdomain
, 1);
358 if (ctx
->t
->res_options
!= NULL
)
359 setenv ("RES_OPTIONS", ctx
->t
->res_options
, 1);
364 xchroot (path_chroot
);
365 TEST_VERIFY (res_init () == 0);
366 print_resp (stdout
, &_res
);
370 xchroot (path_chroot
);
371 res_state resp
= xmalloc (sizeof (*resp
));
372 memset (resp
, 0, sizeof (*resp
));
373 TEST_VERIFY (res_ninit (resp
) == 0);
374 print_resp (stdout
, resp
);
380 xchroot (path_chroot
);
381 unsigned char buf
[512];
382 TEST_VERIFY (res_mkquery (QUERY
, "www.example",
383 C_IN
, ns_t_a
, NULL
, 0,
384 NULL
, buf
, sizeof (buf
)) > 0);
385 print_resp (stdout
, &_res
);
388 case test_gethostbyname
:
389 setup_nss_dns_and_chroot ();
390 /* Trigger implicit initialization of the _res structure. The
391 actual lookup result is immaterial. */
392 (void )gethostbyname ("www.example");
393 print_resp (stdout
, &_res
);
396 case test_getaddrinfo
:
397 setup_nss_dns_and_chroot ();
398 /* Trigger implicit initialization of the _res structure. The
399 actual lookup result is immaterial. */
401 (void) getaddrinfo ("www.example", NULL
, NULL
, &ai
);
402 print_resp (stdout
, &_res
);
406 FAIL_EXIT1 ("invalid init method %d", ctx
->init
);
410 /* Helper function which calls run_res_init from a thread. */
412 run_res_init_thread_func (void *closure
)
414 run_res_init (closure
);
418 /* Variant of res_run_init which runs the function on a non-main
421 run_res_init_on_thread (void *closure
)
423 xpthread_join (xpthread_create (NULL
, run_res_init_thread_func
, closure
));
425 #endif /* TEST_THREAD */
427 struct test_case test_cases
[] =
429 {.name
= "empty file",
431 .expected
= "search example.com\n"
432 "; search[0]: example.com\n"
433 "nameserver 127.0.0.1\n"
434 "; nameserver[0]: [127.0.0.1]:53\n"
436 {.name
= "empty file with LOCALDOMAIN",
438 .expected
= "search example.net\n"
439 "; search[0]: example.net\n"
440 "nameserver 127.0.0.1\n"
441 "; nameserver[0]: [127.0.0.1]:53\n",
442 .localdomain
= "example.net",
444 {.name
= "empty file with RES_OPTIONS",
446 .expected
= "options attempts:5 edns0\n"
447 "search example.com\n"
448 "; search[0]: example.com\n"
449 "nameserver 127.0.0.1\n"
450 "; nameserver[0]: [127.0.0.1]:53\n",
451 .res_options
= "edns0 attempts:5",
453 {.name
= "empty file with RES_OPTIONS and LOCALDOMAIN",
455 .expected
= "options attempts:5 edns0\n"
456 "search example.org\n"
457 "; search[0]: example.org\n"
458 "nameserver 127.0.0.1\n"
459 "; nameserver[0]: [127.0.0.1]:53\n",
460 .localdomain
= "example.org",
461 .res_options
= "edns0 attempts:5",
464 .conf
= "domain example.net\n"
465 "search corp.example.com example.com\n"
466 "nameserver 192.0.2.1\n",
467 .expected
= "search corp.example.com example.com\n"
468 "; search[0]: corp.example.com\n"
469 "; search[1]: example.com\n"
470 "nameserver 192.0.2.1\n"
471 "; nameserver[0]: [192.0.2.1]:53\n"
473 {.name
= "whitespace",
474 .conf
= "# This test covers comment and whitespace processing "
475 " (trailing whitespace,\n"
476 "# missing newline at end of file).\n"
478 ";search commented out\n"
479 "search corp.example.com\texample.com \n"
480 "#nameserver 192.0.2.3\n"
481 "nameserver 192.0.2.1 \n"
482 "nameserver 192.0.2.2", /* No \n at end of file. */
483 .expected
= "search corp.example.com example.com\n"
484 "; search[0]: corp.example.com\n"
485 "; search[1]: example.com\n"
486 "nameserver 192.0.2.1\n"
487 "nameserver 192.0.2.2\n"
488 "; nameserver[0]: [192.0.2.1]:53\n"
489 "; nameserver[1]: [192.0.2.2]:53\n"
492 .conf
= "domain example.net\n"
493 "nameserver 192.0.2.1\n",
494 .expected
= "search example.net\n"
495 "; search[0]: example.net\n"
496 "nameserver 192.0.2.1\n"
497 "; nameserver[0]: [192.0.2.1]:53\n"
499 {.name
= "domain space",
500 .conf
= "domain example.net \n"
501 "nameserver 192.0.2.1\n",
502 .expected
= "search example.net\n"
503 "; search[0]: example.net\n"
504 "nameserver 192.0.2.1\n"
505 "; nameserver[0]: [192.0.2.1]:53\n"
507 {.name
= "domain tab",
508 .conf
= "domain example.net\t\n"
509 "nameserver 192.0.2.1\n",
510 .expected
= "search example.net\n"
511 "; search[0]: example.net\n"
512 "nameserver 192.0.2.1\n"
513 "; nameserver[0]: [192.0.2.1]:53\n"
515 {.name
= "domain override",
516 .conf
= "search example.com example.org\n"
517 "nameserver 192.0.2.1\n"
518 "domain example.net", /* No \n at end of file. */
519 .expected
= "search example.net\n"
520 "; search[0]: example.net\n"
521 "nameserver 192.0.2.1\n"
522 "; nameserver[0]: [192.0.2.1]:53\n"
524 {.name
= "option values, multiple servers",
525 .conf
= "options\tinet6\tndots:3 edns0\tattempts:5\ttimeout:19\n"
526 "domain example.net\n"
528 "search corp.example.com\texample.com\n"
529 "nameserver 192.0.2.1\n"
531 "nameserver 192.0.2.2\n",
532 .expected
= "options ndots:3 timeout:19 attempts:5 inet6 edns0\n"
533 "search corp.example.com example.com\n"
534 "; search[0]: corp.example.com\n"
535 "; search[1]: example.com\n"
536 "nameserver 192.0.2.1\n"
538 "nameserver 192.0.2.2\n"
539 "; nameserver[0]: [192.0.2.1]:53\n"
540 "; nameserver[1]: [::1]:53\n"
541 "; nameserver[2]: [192.0.2.2]:53\n"
543 {.name
= "out-of-range option vales",
544 .conf
= "options use-vc timeout:999 attempts:999 ndots:99\n"
545 "search example.com\n",
546 .expected
= "options ndots:15 timeout:30 attempts:5 use-vc\n"
547 "search example.com\n"
548 "; search[0]: example.com\n"
549 "nameserver 127.0.0.1\n"
550 "; nameserver[0]: [127.0.0.1]:53\n"
552 {.name
= "repeated directives",
553 .conf
= "options ndots:3 use-vc\n"
554 "options edns0 ndots:2\n"
555 "domain corp.example\n"
556 "search example.net corp.example.com example.com\n"
557 "search example.org\n"
559 .expected
= "options ndots:2 use-vc edns0\n"
560 "search example.org\n"
561 "; search[0]: example.org\n"
562 "nameserver 127.0.0.1\n"
563 "; nameserver[0]: [127.0.0.1]:53\n"
565 {.name
= "many name servers, sortlist",
566 .conf
= "options single-request\n"
567 "search example.org example.com example.net corp.example.com\n"
568 "sortlist 192.0.2.0/255.255.255.0\n"
569 "nameserver 192.0.2.1\n"
570 "nameserver 192.0.2.2\n"
571 "nameserver 192.0.2.3\n"
572 "nameserver 192.0.2.4\n"
573 "nameserver 192.0.2.5\n"
574 "nameserver 192.0.2.6\n"
575 "nameserver 192.0.2.7\n"
576 "nameserver 192.0.2.8\n",
577 .expected
= "options single-request\n"
578 "search example.org example.com example.net corp.example.com\n"
579 "; search[0]: example.org\n"
580 "; search[1]: example.com\n"
581 "; search[2]: example.net\n"
582 "; search[3]: corp.example.com\n"
583 "sortlist 192.0.2.0/255.255.255.0\n"
584 "nameserver 192.0.2.1\n"
585 "nameserver 192.0.2.2\n"
586 "nameserver 192.0.2.3\n"
587 "; nameserver[0]: [192.0.2.1]:53\n"
588 "; nameserver[1]: [192.0.2.2]:53\n"
589 "; nameserver[2]: [192.0.2.3]:53\n"
590 "; nameserver[3]: [192.0.2.4]:53\n"
591 "; nameserver[4]: [192.0.2.5]:53\n"
592 "; nameserver[5]: [192.0.2.6]:53\n"
593 "; nameserver[6]: [192.0.2.7]:53\n"
594 "; nameserver[7]: [192.0.2.8]:53\n"
596 {.name
= "IPv4 and IPv6 nameservers",
597 .conf
= "options single-request\n"
598 "search example.org example.com example.net corp.example.com"
599 " legacy.example.com\n"
600 "sortlist 192.0.2.0\n"
601 "nameserver 192.0.2.1\n"
602 "nameserver 2001:db8::2\n"
603 "nameserver 192.0.2.3\n"
604 "nameserver 2001:db8::4\n"
605 "nameserver 192.0.2.5\n"
606 "nameserver 2001:db8::6\n"
607 "nameserver 192.0.2.7\n"
608 "nameserver 2001:db8::8\n",
609 .expected
= "options single-request\n"
610 "search example.org example.com example.net corp.example.com"
611 " legacy.example.com\n"
612 "; search[0]: example.org\n"
613 "; search[1]: example.com\n"
614 "; search[2]: example.net\n"
615 "; search[3]: corp.example.com\n"
616 "; search[4]: legacy.example.com\n"
617 "sortlist 192.0.2.0/255.255.255.0\n"
618 "nameserver 192.0.2.1\n"
619 "nameserver 2001:db8::2\n"
620 "nameserver 192.0.2.3\n"
621 "; nameserver[0]: [192.0.2.1]:53\n"
622 "; nameserver[1]: [2001:db8::2]:53\n"
623 "; nameserver[2]: [192.0.2.3]:53\n"
624 "; nameserver[3]: [2001:db8::4]:53\n"
625 "; nameserver[4]: [192.0.2.5]:53\n"
626 "; nameserver[5]: [2001:db8::6]:53\n"
627 "; nameserver[6]: [192.0.2.7]:53\n"
628 "; nameserver[7]: [2001:db8::8]:53\n",
630 {.name
= "garbage after nameserver",
631 .conf
= "nameserver 192.0.2.1 garbage\n"
632 "nameserver 192.0.2.2:5353\n"
633 "nameserver 192.0.2.3 5353\n",
634 .expected
= "search example.com\n"
635 "; search[0]: example.com\n"
636 "nameserver 192.0.2.1\n"
637 "nameserver 192.0.2.3\n"
638 "; nameserver[0]: [192.0.2.1]:53\n"
639 "; nameserver[1]: [192.0.2.3]:53\n"
641 {.name
= "RES_OPTIONS is cummulative",
642 .conf
= "options timeout:7 ndots:2 use-vc\n"
643 "nameserver 192.0.2.1\n",
644 .expected
= "options ndots:3 timeout:7 attempts:5 use-vc edns0\n"
645 "search example.com\n"
646 "; search[0]: example.com\n"
647 "nameserver 192.0.2.1\n"
648 "; nameserver[0]: [192.0.2.1]:53\n",
649 .res_options
= "attempts:5 ndots:3 edns0 ",
651 {.name
= "many search list entries (bug 19569)",
652 .conf
= "nameserver 192.0.2.1\n"
653 "search corp.example.com support.example.com"
654 " community.example.org wan.example.net vpn.example.net"
655 " example.com example.org example.net\n",
656 .expected
= "search corp.example.com support.example.com"
657 " community.example.org wan.example.net vpn.example.net example.com\n"
658 "; search[0]: corp.example.com\n"
659 "; search[1]: support.example.com\n"
660 "; search[2]: community.example.org\n"
661 "; search[3]: wan.example.net\n"
662 "; search[4]: vpn.example.net\n"
663 "; search[5]: example.com\n"
664 "; search[6]: example.org\n"
665 "; search[7]: example.net\n"
666 "nameserver 192.0.2.1\n"
667 "; nameserver[0]: [192.0.2.1]:53\n"
669 {.name
= "very long search list entries (bug 21475)",
670 .conf
= "nameserver 192.0.2.1\n"
671 "search example.com "
672 #define H63 "this-host-name-is-longer-than-yours-yes-I-really-really-mean-it"
673 #define D63 "this-domain-name-is-as-long-as-the-previous-name--63-characters"
674 " " H63
"." D63
".example.org"
675 " " H63
"." D63
".example.net\n",
676 .expected
= "search example.com " H63
"." D63
".example.org\n"
677 "; search[0]: example.com\n"
678 "; search[1]: " H63
"." D63
".example.org\n"
679 "; search[2]: " H63
"." D63
".example.net\n"
682 "nameserver 192.0.2.1\n"
683 "; nameserver[0]: [192.0.2.1]:53\n"
688 /* Run the indicated test case. This function assumes that the chroot
689 contents has already been set up. */
691 test_file_contents (const struct test_case
*t
)
694 for (int do_thread
= 0; do_thread
< 2; ++do_thread
)
696 for (int init_method
= 0; init_method
<= test_init_method_last
;
699 if (test_verbose
> 0)
700 printf ("info: testing init method %s\n",
701 test_init_names
[init_method
]);
702 struct test_context ctx
= { .init
= init_method
, .t
= t
};
703 void (*func
) (void *) = run_res_init
;
706 func
= run_res_init_on_thread
;
708 struct support_capture_subprocess proc
709 = support_capture_subprocess (func
, &ctx
);
710 if (strcmp (proc
.out
.buffer
, t
->expected
) != 0)
712 support_record_failure ();
713 printf ("error: output mismatch for %s (init method %s)\n",
714 t
->name
, test_init_names
[init_method
]);
715 support_run_diff ("expected", t
->expected
,
716 "actual", proc
.out
.buffer
);
718 support_capture_subprocess_check (&proc
, t
->name
, 0,
720 support_capture_subprocess_free (&proc
);
724 /* Special tests which do not follow the general pattern. */
725 enum { special_tests_count
= 7 };
728 /* Called from test number 3-6 to trigger reloading of the
731 special_test_call_res_init (void *closure
)
733 TEST_VERIFY (res_init () == 0);
738 /* Implementation of special tests. */
740 special_test_callback (void *closure
)
742 unsigned int *test_indexp
= closure
;
743 unsigned test_index
= *test_indexp
;
744 TEST_VERIFY (test_index
< special_tests_count
);
745 if (test_verbose
> 0)
746 printf ("info: special test %u\n", test_index
);
747 xchroot (path_chroot
);
753 /* Second res_init with missing or empty file preserves
756 TEST_VERIFY (unlink (_PATH_RESCONF
) == 0);
757 _res
.options
= RES_USE_EDNS0
;
758 TEST_VERIFY (res_init () == 0);
759 /* First res_init clears flag. */
760 TEST_VERIFY (!(_res
.options
& RES_USE_EDNS0
));
761 _res
.options
|= RES_USE_EDNS0
;
762 TEST_VERIFY (res_init () == 0);
763 /* Second res_init preserves flag. */
764 TEST_VERIFY (_res
.options
& RES_USE_EDNS0
);
766 /* Restore empty file. */
767 support_write_file_string (_PATH_RESCONF
, "");
771 /* Second res_init is cumulative. */
772 support_write_file_string (_PATH_RESCONF
,
774 "nameserver 192.0.2.1\n");
775 _res
.options
= RES_USE_EDNS0
;
776 TEST_VERIFY (res_init () == 0);
777 /* First res_init clears flag. */
778 TEST_VERIFY (!(_res
.options
& RES_USE_EDNS0
));
779 /* And sets RES_ROTATE. */
780 TEST_VERIFY (_res
.options
& RES_ROTATE
);
781 _res
.options
|= RES_USE_EDNS0
;
782 TEST_VERIFY (res_init () == 0);
783 /* Second res_init preserves flag. */
784 TEST_VERIFY (_res
.options
& RES_USE_EDNS0
);
785 TEST_VERIFY (_res
.options
& RES_ROTATE
);
786 /* Reloading the configuration does not clear the explicitly set
788 support_write_file_string (_PATH_RESCONF
,
789 "nameserver 192.0.2.1\n"
790 "nameserver 192.0.2.2\n");
791 TEST_VERIFY (res_init () == 0);
792 TEST_VERIFY (_res
.nscount
== 2);
793 TEST_VERIFY (_res
.options
& RES_USE_EDNS0
);
794 /* Whether RES_ROTATE (originally in resolv.conf, now removed)
795 should be preserved is subject to debate. See bug 21701. */
796 /* TEST_VERIFY (!(_res.options & RES_ROTATE)); */
803 /* Test res_init change broadcast. This requires a second
804 thread to trigger the reload. */
806 support_write_file_string (_PATH_RESCONF
,
808 "nameserver 192.0.2.1\n");
809 for (int iteration
= 0; iteration
< 2; ++iteration
)
814 TEST_VERIFY (res_init () == 0);
818 unsigned char buf
[512];
820 (res_mkquery (QUERY
, test_hostname
, C_IN
, T_A
,
821 NULL
, 0, NULL
, buf
, sizeof (buf
)) > 0);
825 gethostbyname (test_hostname
);
830 (void) getaddrinfo (test_hostname
, NULL
, NULL
, &ai
);
836 TEST_VERIFY (_res
.options
& RES_USE_EDNS0
);
837 TEST_VERIFY (!(_res
.options
& RES_ROTATE
));
838 TEST_VERIFY (_res
.nscount
== 1);
839 support_write_file_string (_PATH_RESCONF
,
841 "nameserver 192.0.2.1\n"
842 "nameserver 192.0.2.2\n");
843 xpthread_join (xpthread_create
844 (NULL
, special_test_call_res_init
, NULL
));
848 /* edns0 was dropped, but the flag is not cleared. See
850 /* TEST_VERIFY (!(_res.options & RES_USE_EDNS0)); */
851 TEST_VERIFY (_res
.options
& RES_ROTATE
);
852 TEST_VERIFY (_res
.nscount
== 2);
861 /* Helper function which calls special_test_callback from a
864 special_test_thread_func (void *closure
)
866 special_test_callback (closure
);
870 /* Variant of special_test_callback which runs the function on a
873 run_special_test_on_thread (void *closure
)
875 xpthread_join (xpthread_create (NULL
, special_test_thread_func
, closure
));
877 #endif /* TEST_THREAD */
879 /* Perform the requested special test in a subprocess using
880 special_test_callback. */
882 special_test (unsigned int test_index
)
885 for (int do_thread
= 0; do_thread
< 2; ++do_thread
)
888 void (*func
) (void *) = special_test_callback
;
891 func
= run_special_test_on_thread
;
893 struct support_capture_subprocess proc
894 = support_capture_subprocess (func
, &test_index
);
895 char *test_name
= xasprintf ("special test %u", test_index
);
896 if (strcmp (proc
.out
.buffer
, "") != 0)
898 support_record_failure ();
899 printf ("error: output mismatch for %s\n", test_name
);
900 support_run_diff ("expected", "",
901 "actual", proc
.out
.buffer
);
903 support_capture_subprocess_check (&proc
, test_name
, 0, sc_allow_stdout
);
905 support_capture_subprocess_free (&proc
);
910 /* Dummy DNS server. It ensures that the probe queries sent by
911 gethostbyname and getaddrinfo receive a reply even if the system
912 applies a very strict rate limit to localhost. */
914 start_dummy_server (void)
916 int server_socket
= xsocket (AF_INET
, SOCK_DGRAM
, 0);
918 struct sockaddr_in sin
=
920 .sin_family
= AF_INET
,
921 .sin_addr
= { .s_addr
= htonl (INADDR_LOOPBACK
) },
922 .sin_port
= htons (53),
924 int ret
= bind (server_socket
, (struct sockaddr
*) &sin
, sizeof (sin
));
928 /* The port is reserved, which means we cannot start the
931 FAIL_EXIT1 ("cannot bind socket to port 53: %m");
935 pid_t pid
= xfork ();
938 /* Child process. Echo back queries as SERVFAIL responses. */
944 unsigned char bytes
[512];
946 struct sockaddr_in sin
;
947 socklen_t sinlen
= sizeof (sin
);
949 ssize_t ret
= recvfrom
950 (server_socket
, &packet
, sizeof (packet
),
951 MSG_NOSIGNAL
, (struct sockaddr
*) &sin
, &sinlen
);
953 FAIL_EXIT1 ("recvfrom on fake server socket: %m");
954 if (ret
> sizeof (HEADER
))
956 /* Turn the query into a SERVFAIL response. */
957 packet
.header
.qr
= 1;
958 packet
.header
.rcode
= ns_r_servfail
;
960 /* Send the response. */
961 ret
= sendto (server_socket
, &packet
, ret
,
962 MSG_NOSIGNAL
, (struct sockaddr
*) &sin
, sinlen
);
964 /* The peer may have closed socket prematurely, so
965 this is not an error. */
966 printf ("warning: sending DNS server reply: %m\n");
971 /* In the parent, close the socket. */
972 xclose (server_socket
);
980 support_become_root ();
981 support_enter_network_namespace ();
982 if (!support_in_uts_namespace () || !support_can_chroot ())
983 return EXIT_UNSUPPORTED
;
985 /* We are in an UTS namespace, so we can set the host name without
986 altering the state of the entire system. */
987 if (sethostname (test_hostname
, strlen (test_hostname
)) != 0)
988 FAIL_EXIT1 ("sethostname: %m");
990 /* These environment variables affect resolv.conf parsing. */
991 unsetenv ("LOCALDOMAIN");
992 unsetenv ("RES_OPTIONS");
994 /* Ensure that the chroot setup worked. */
996 struct support_capture_subprocess proc
997 = support_capture_subprocess (check_chroot_working
, NULL
);
998 support_capture_subprocess_check (&proc
, "chroot", 0, sc_allow_none
);
999 support_capture_subprocess_free (&proc
);
1002 pid_t server
= start_dummy_server ();
1004 for (size_t i
= 0; test_cases
[i
].name
!= NULL
; ++i
)
1006 if (test_verbose
> 0)
1007 printf ("info: running test: %s\n", test_cases
[i
].name
);
1008 TEST_VERIFY (test_cases
[i
].conf
!= NULL
);
1009 TEST_VERIFY (test_cases
[i
].expected
!= NULL
);
1011 support_write_file_string (path_resolv_conf
, test_cases
[i
].conf
);
1013 test_file_contents (&test_cases
[i
]);
1015 /* The expected output from the empty file test is used for
1017 if (test_cases
[i
].conf
[0] == '\0')
1019 if (test_verbose
> 0)
1020 printf ("info: special test: missing file\n");
1021 TEST_VERIFY (unlink (path_resolv_conf
) == 0);
1022 test_file_contents (&test_cases
[i
]);
1024 if (test_verbose
> 0)
1025 printf ("info: special test: dangling symbolic link\n");
1026 TEST_VERIFY (symlink ("does-not-exist", path_resolv_conf
) == 0);
1027 test_file_contents (&test_cases
[i
]);
1028 TEST_VERIFY (unlink (path_resolv_conf
) == 0);
1030 if (test_verbose
> 0)
1031 printf ("info: special test: unreadable file\n");
1032 support_write_file_string (path_resolv_conf
, "");
1033 TEST_VERIFY (chmod (path_resolv_conf
, 0) == 0);
1034 test_file_contents (&test_cases
[i
]);
1036 /* Restore the empty file. */
1037 TEST_VERIFY (unlink (path_resolv_conf
) == 0);
1038 support_write_file_string (path_resolv_conf
, "");
1042 /* The tests which do not follow a regular pattern. */
1043 for (unsigned int test_index
= 0;
1044 test_index
< special_tests_count
; ++test_index
)
1045 special_test (test_index
);
1049 if (kill (server
, SIGTERM
) < 0)
1050 FAIL_EXIT1 ("could not terminate server process: %m");
1051 xwaitpid (server
, NULL
, 0);
1056 free (path_resolv_conf
);
1057 path_resolv_conf
= NULL
;
1061 #define PREPARE prepare
1062 #include <support/test-driver.c>