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. */
30 #include <support/capture_subprocess.h>
31 #include <support/check.h>
32 #include <support/namespace.h>
33 #include <support/run_diff.h>
34 #include <support/support.h>
35 #include <support/temp_file.h>
36 #include <support/test-driver.h>
37 #include <support/xsocket.h>
38 #include <support/xstdio.h>
39 #include <support/xunistd.h>
42 # include <support/xthread.h>
45 /* This is the host name used to ensure predictable behavior of
47 static const char *const test_hostname
= "www.example.com";
49 /* Path to the test root directory. */
50 static char *path_chroot
;
52 /* Path to resolv.conf under path_chroot (outside the chroot). */
53 static char *path_resolv_conf
;
56 prepare (int argc
, char **argv
)
58 path_chroot
= xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir
);
59 if (mkdtemp (path_chroot
) == NULL
)
60 FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", path_chroot
);
61 add_temp_file (path_chroot
);
63 /* Create the /etc directory in the chroot environment. */
64 char *path_etc
= xasprintf ("%s/etc", path_chroot
);
65 xmkdir (path_etc
, 0777);
66 add_temp_file (path_etc
);
68 /* Create an empty resolv.conf file. */
69 path_resolv_conf
= xasprintf ("%s/resolv.conf", path_etc
);
70 add_temp_file (path_resolv_conf
);
71 support_write_file_string (path_resolv_conf
, "");
75 /* valgrind needs a temporary directory in the chroot. */
77 char *path_tmp
= xasprintf ("%s/tmp", path_chroot
);
78 xmkdir (path_tmp
, 0777);
79 add_temp_file (path_tmp
);
84 /* Verify that the chroot environment has been set up. */
86 check_chroot_working (void *closure
)
88 xchroot (path_chroot
);
89 FILE *fp
= xfopen (_PATH_RESCONF
, "r");
92 TEST_VERIFY_EXIT (res_init () == 0);
93 TEST_VERIFY (_res
.options
& RES_INIT
);
96 if (gethostname (buf
, sizeof (buf
)) < 0)
97 FAIL_EXIT1 ("gethostname: %m");
98 if (strcmp (buf
, test_hostname
) != 0)
99 FAIL_EXIT1 ("unexpected host name: %s", buf
);
102 /* If FLAG is set in *OPTIONS, write NAME to FP, and clear it in
105 print_option_flag (FILE *fp
, int *options
, int flag
, const char *name
)
109 fprintf (fp
, " %s", name
);
114 /* Write a decoded version of the resolver configuration *RESP to the
117 print_resp (FILE *fp
, res_state resp
)
119 /* The options directive. */
121 /* RES_INIT is used internally for tracking initialization. */
122 TEST_VERIFY (resp
->options
& RES_INIT
);
123 /* Also mask out other default flags which cannot be set through
124 the options directive. */
126 = resp
->options
& ~(RES_INIT
| RES_RECURSE
| RES_DEFNAMES
| RES_DNSRCH
);
129 || resp
->retrans
!= RES_TIMEOUT
130 || resp
->retry
!= RES_DFLRETRY
)
132 fputs ("options", fp
);
133 if (resp
->ndots
!= 1)
134 fprintf (fp
, " ndots:%d", resp
->ndots
);
135 if (resp
->retrans
!= RES_TIMEOUT
)
136 fprintf (fp
, " timeout:%d", resp
->retrans
);
137 if (resp
->retry
!= RES_DFLRETRY
)
138 fprintf (fp
, " attempts:%d", resp
->retry
);
139 print_option_flag (fp
, &options
, RES_USEVC
, "use-vc");
140 print_option_flag (fp
, &options
, DEPRECATED_RES_USE_INET6
, "inet6");
141 print_option_flag (fp
, &options
, RES_ROTATE
, "rotate");
142 print_option_flag (fp
, &options
, RES_USE_EDNS0
, "edns0");
143 print_option_flag (fp
, &options
, RES_SNGLKUP
,
145 print_option_flag (fp
, &options
, RES_SNGLKUPREOP
,
146 "single-request-reopen");
147 print_option_flag (fp
, &options
, RES_NOTLDQUERY
, "no-tld-query");
150 fprintf (fp
, "; error: unresolved option bits: 0x%x\n", options
);
154 /* The search and domain directives. */
155 if (resp
->dnsrch
[0] != NULL
)
157 fputs ("search", fp
);
158 for (int i
= 0; i
< MAXDNSRCH
&& resp
->dnsrch
[i
] != NULL
; ++i
)
161 fputs (resp
->dnsrch
[i
], fp
);
165 else if (resp
->defdname
[0] != '\0')
166 fprintf (fp
, "domain %s\n", resp
->defdname
);
168 /* The sortlist directive. */
171 fputs ("sortlist", fp
);
172 for (int i
= 0; i
< resp
->nsort
&& i
< MAXRESOLVSORT
; ++i
)
175 if (inet_ntop (AF_INET
, &resp
->sort_list
[i
].addr
,
176 net
, sizeof (net
)) == NULL
)
177 FAIL_EXIT1 ("inet_ntop: %m\n");
179 if (inet_ntop (AF_INET
, &resp
->sort_list
[i
].mask
,
180 mask
, sizeof (mask
)) == NULL
)
181 FAIL_EXIT1 ("inet_ntop: %m\n");
182 fprintf (fp
, " %s/%s", net
, mask
);
187 /* The nameserver directives. */
188 for (size_t i
= 0; i
< resp
->nscount
; ++i
)
190 char host
[NI_MAXHOST
];
191 char service
[NI_MAXSERV
];
193 /* See get_nsaddr in res_send.c. */
196 if (resp
->nsaddr_list
[i
].sin_family
== 0
197 && resp
->_u
._ext
.nsaddrs
[i
] != NULL
)
199 addr
= resp
->_u
._ext
.nsaddrs
[i
];
200 addrlen
= sizeof (*resp
->_u
._ext
.nsaddrs
[i
]);
204 addr
= &resp
->nsaddr_list
[i
];
205 addrlen
= sizeof (resp
->nsaddr_list
[i
]);
208 int ret
= getnameinfo (addr
, addrlen
,
209 host
, sizeof (host
), service
, sizeof (service
),
210 NI_NUMERICHOST
| NI_NUMERICSERV
);
213 if (ret
== EAI_SYSTEM
)
214 fprintf (fp
, "; error: getnameinfo: %m\n");
216 fprintf (fp
, "; error: getnameinfo: %s\n", gai_strerror (ret
));
220 fprintf (fp
, "nameserver %s\n", host
);
221 if (strcmp (service
, "53") != 0)
222 fprintf (fp
, "; unrepresentable port number %s\n\n", service
);
226 TEST_VERIFY (!ferror (fp
));
229 /* Parameters of one test case. */
232 /* A short, descriptive name of the test. */
235 /* The contents of the /etc/resolv.conf file. */
238 /* The expected output from print_resp. */
239 const char *expected
;
241 /* Setting for the LOCALDOMAIN environment variable. NULL if the
242 variable is not to be set. */
243 const char *localdomain
;
245 /* Setting for the RES_OPTIONS environment variable. NULL if the
246 variable is not to be set. */
247 const char *res_options
;
257 test_init_method_last
= test_getaddrinfo
260 static const char *const test_init_names
[] =
262 [test_init
] = "res_init",
263 [test_ninit
] = "res_ninit",
264 [test_mkquery
] = "res_mkquery",
265 [test_gethostbyname
] = "gethostbyname",
266 [test_getaddrinfo
] = "getaddrinfo",
269 /* Closure argument for run_res_init. */
273 const struct test_case
*t
;
277 setup_nss_dns_and_chroot (void)
279 /* Load nss_dns outside of the chroot. */
280 if (dlopen (LIBNSS_DNS_SO
, RTLD_LAZY
) == NULL
)
281 FAIL_EXIT1 ("could not load " LIBNSS_DNS_SO
": %s", dlerror ());
282 xchroot (path_chroot
);
283 /* Force the use of nss_dns. */
284 __nss_configure_lookup ("hosts", "dns");
287 /* Run res_ninit or res_init in a subprocess and dump the parsed
288 resolver state to standard output. */
290 run_res_init (void *closure
)
292 struct test_context
*ctx
= closure
;
293 TEST_VERIFY (getenv ("LOCALDOMAIN") == NULL
);
294 TEST_VERIFY (getenv ("RES_OPTIONS") == NULL
);
295 if (ctx
->t
->localdomain
!= NULL
)
296 setenv ("LOCALDOMAIN", ctx
->t
->localdomain
, 1);
297 if (ctx
->t
->res_options
!= NULL
)
298 setenv ("RES_OPTIONS", ctx
->t
->res_options
, 1);
303 xchroot (path_chroot
);
304 TEST_VERIFY (res_init () == 0);
305 print_resp (stdout
, &_res
);
309 xchroot (path_chroot
);
310 res_state resp
= xmalloc (sizeof (*resp
));
311 memset (resp
, 0, sizeof (*resp
));
312 TEST_VERIFY (res_ninit (resp
) == 0);
313 print_resp (stdout
, resp
);
319 xchroot (path_chroot
);
320 unsigned char buf
[512];
321 TEST_VERIFY (res_mkquery (QUERY
, "www.example",
322 C_IN
, ns_t_a
, NULL
, 0,
323 NULL
, buf
, sizeof (buf
)) > 0);
324 print_resp (stdout
, &_res
);
327 case test_gethostbyname
:
328 setup_nss_dns_and_chroot ();
329 /* Trigger implicit initialization of the _res structure. The
330 actual lookup result is immaterial. */
331 (void )gethostbyname ("www.example");
332 print_resp (stdout
, &_res
);
335 case test_getaddrinfo
:
336 setup_nss_dns_and_chroot ();
337 /* Trigger implicit initialization of the _res structure. The
338 actual lookup result is immaterial. */
340 (void) getaddrinfo ("www.example", NULL
, NULL
, &ai
);
341 print_resp (stdout
, &_res
);
345 FAIL_EXIT1 ("invalid init method %d", ctx
->init
);
349 /* Helper function which calls run_res_init from a thread. */
351 run_res_init_thread_func (void *closure
)
353 run_res_init (closure
);
357 /* Variant of res_run_init which runs the function on a non-main
360 run_res_init_on_thread (void *closure
)
362 xpthread_join (xpthread_create (NULL
, run_res_init_thread_func
, closure
));
364 #endif /* TEST_THREAD */
366 struct test_case test_cases
[] =
368 {.name
= "empty file",
370 .expected
= "search example.com\n"
371 "nameserver 127.0.0.1\n"
373 {.name
= "empty file with LOCALDOMAIN",
375 .expected
= "search example.net\n"
376 "nameserver 127.0.0.1\n",
377 .localdomain
= "example.net",
379 {.name
= "empty file with RES_OPTIONS",
381 .expected
= "options attempts:5 edns0\n"
382 "search example.com\n"
383 "nameserver 127.0.0.1\n",
384 .res_options
= "edns0 attempts:5",
386 {.name
= "empty file with RES_OPTIONS and LOCALDOMAIN",
388 .expected
= "options attempts:5 edns0\n"
389 "search example.org\n"
390 "nameserver 127.0.0.1\n",
391 .localdomain
= "example.org",
392 .res_options
= "edns0 attempts:5",
395 .conf
= "domain example.net\n"
396 "search corp.example.com example.com\n"
397 "nameserver 192.0.2.1\n",
398 .expected
= "search corp.example.com example.com\n"
399 "nameserver 192.0.2.1\n"
401 {.name
= "whitespace",
402 .conf
= "# This test covers comment and whitespace processing "
403 " (trailing whitespace,\n"
404 "# missing newline at end of file).\n"
406 "domain example.net\n"
407 ";search commented out\n"
408 "search corp.example.com\texample.com\n"
409 "#nameserver 192.0.2.3\n"
410 "nameserver 192.0.2.1 \n"
411 "nameserver 192.0.2.2", /* No \n at end of file. */
412 .expected
= "search corp.example.com example.com\n"
413 "nameserver 192.0.2.1\n"
414 "nameserver 192.0.2.2\n"
416 {.name
= "option values, multiple servers",
417 .conf
= "options\tinet6\tndots:3 edns0\tattempts:5\ttimeout:19\n"
418 "domain example.net\n"
420 "search corp.example.com\texample.com\n"
421 "nameserver 192.0.2.1\n"
423 "nameserver 192.0.2.2\n",
424 .expected
= "options ndots:3 timeout:19 attempts:5 inet6 edns0\n"
425 "search corp.example.com example.com\n"
426 "nameserver 192.0.2.1\n"
428 "nameserver 192.0.2.2\n"
430 {.name
= "out-of-range option vales",
431 .conf
= "options use-vc timeout:999 attempts:999 ndots:99\n"
432 "search example.com\n",
433 .expected
= "options ndots:15 timeout:30 attempts:5 use-vc\n"
434 "search example.com\n"
435 "nameserver 127.0.0.1\n"
437 {.name
= "repeated directives",
438 .conf
= "options ndots:3 use-vc\n"
439 "options edns0 ndots:2\n"
440 "domain corp.example\n"
441 "search example.net corp.example.com example.com\n"
442 "search example.org\n"
444 .expected
= "options ndots:2 use-vc edns0\n"
445 "search example.org\n"
446 "nameserver 127.0.0.1\n"
448 {.name
= "many name servers, sortlist",
449 .conf
= "options single-request\n"
450 "search example.org example.com example.net corp.example.com\n"
451 "sortlist 192.0.2.0/255.255.255.0\n"
452 "nameserver 192.0.2.1\n"
453 "nameserver 192.0.2.2\n"
454 "nameserver 192.0.2.3\n"
455 "nameserver 192.0.2.4\n"
456 "nameserver 192.0.2.5\n"
457 "nameserver 192.0.2.6\n"
458 "nameserver 192.0.2.7\n"
459 "nameserver 192.0.2.8\n",
460 .expected
= "options single-request\n"
461 "search example.org example.com example.net corp.example.com\n"
462 "sortlist 192.0.2.0/255.255.255.0\n"
463 "nameserver 192.0.2.1\n"
464 "nameserver 192.0.2.2\n"
465 "nameserver 192.0.2.3\n"
467 {.name
= "IPv4 and IPv6 nameservers",
468 .conf
= "options single-request\n"
469 "search example.org example.com example.net corp.example.com"
470 " legacy.example.com\n"
471 "sortlist 192.0.2.0\n"
472 "nameserver 192.0.2.1\n"
473 "nameserver 2001:db8::2\n"
474 "nameserver 192.0.2.3\n"
475 "nameserver 2001:db8::4\n"
476 "nameserver 192.0.2.5\n"
477 "nameserver 2001:db8::6\n"
478 "nameserver 192.0.2.7\n"
479 "nameserver 2001:db8::8\n",
480 .expected
= "options single-request\n"
481 "search example.org example.com example.net corp.example.com"
482 " legacy.example.com\n"
483 "sortlist 192.0.2.0/255.255.255.0\n"
484 "nameserver 192.0.2.1\n"
485 "nameserver 2001:db8::2\n"
486 "nameserver 192.0.2.3\n"
488 {.name
= "garbage after nameserver",
489 .conf
= "nameserver 192.0.2.1 garbage\n"
490 "nameserver 192.0.2.2:5353\n"
491 "nameserver 192.0.2.3 5353\n",
492 .expected
= "search example.com\n"
493 "nameserver 192.0.2.1\n"
494 "nameserver 192.0.2.3\n"
496 {.name
= "RES_OPTIONS is cummulative",
497 .conf
= "options timeout:7 ndots:2 use-vc\n"
498 "nameserver 192.0.2.1\n",
499 .expected
= "options ndots:3 timeout:7 attempts:5 use-vc edns0\n"
500 "search example.com\n"
501 "nameserver 192.0.2.1\n",
502 .res_options
= "attempts:5 ndots:3 edns0 ",
507 /* Run the indicated test case. This function assumes that the chroot
508 contents has already been set up. */
510 test_file_contents (const struct test_case
*t
)
513 for (int do_thread
= 0; do_thread
< 2; ++do_thread
)
515 for (int init_method
= 0; init_method
<= test_init_method_last
;
518 if (test_verbose
> 0)
519 printf ("info: testing init method %s\n",
520 test_init_names
[init_method
]);
521 struct test_context ctx
= { .init
= init_method
, .t
= t
};
522 void (*func
) (void *) = run_res_init
;
525 func
= run_res_init_on_thread
;
527 struct support_capture_subprocess proc
528 = support_capture_subprocess (func
, &ctx
);
529 if (strcmp (proc
.out
.buffer
, t
->expected
) != 0)
531 support_record_failure ();
532 printf ("error: output mismatch for %s (init method %s)\n",
533 t
->name
, test_init_names
[init_method
]);
534 support_run_diff ("expected", t
->expected
,
535 "actual", proc
.out
.buffer
);
537 support_capture_subprocess_check (&proc
, t
->name
, 0,
539 support_capture_subprocess_free (&proc
);
543 /* Special tests which do not follow the general pattern. */
544 enum { special_tests_count
= 7 };
547 /* Called from test number 3-6 to trigger reloading of the
550 special_test_call_res_init (void *closure
)
552 TEST_VERIFY (res_init () == 0);
557 /* Implementation of special tests. */
559 special_test_callback (void *closure
)
561 unsigned int *test_indexp
= closure
;
562 unsigned test_index
= *test_indexp
;
563 TEST_VERIFY (test_index
< special_tests_count
);
564 if (test_verbose
> 0)
565 printf ("info: special test %u\n", test_index
);
566 xchroot (path_chroot
);
572 /* Second res_init with missing or empty file preserves
575 TEST_VERIFY (unlink (_PATH_RESCONF
) == 0);
576 _res
.options
= RES_USE_EDNS0
;
577 TEST_VERIFY (res_init () == 0);
578 /* First res_init clears flag. */
579 TEST_VERIFY (!(_res
.options
& RES_USE_EDNS0
));
580 _res
.options
|= RES_USE_EDNS0
;
581 TEST_VERIFY (res_init () == 0);
582 /* Second res_init preserves flag. */
583 TEST_VERIFY (_res
.options
& RES_USE_EDNS0
);
585 /* Restore empty file. */
586 support_write_file_string (_PATH_RESCONF
, "");
590 /* Second res_init is cumulative. */
591 support_write_file_string (_PATH_RESCONF
,
593 "nameserver 192.0.2.1\n");
594 _res
.options
= RES_USE_EDNS0
;
595 TEST_VERIFY (res_init () == 0);
596 /* First res_init clears flag. */
597 TEST_VERIFY (!(_res
.options
& RES_USE_EDNS0
));
598 /* And sets RES_ROTATE. */
599 TEST_VERIFY (_res
.options
& RES_ROTATE
);
600 _res
.options
|= RES_USE_EDNS0
;
601 TEST_VERIFY (res_init () == 0);
602 /* Second res_init preserves flag. */
603 TEST_VERIFY (_res
.options
& RES_USE_EDNS0
);
604 TEST_VERIFY (_res
.options
& RES_ROTATE
);
605 /* Reloading the configuration does not clear the explicitly set
607 support_write_file_string (_PATH_RESCONF
,
608 "nameserver 192.0.2.1\n"
609 "nameserver 192.0.2.2\n");
610 TEST_VERIFY (res_init () == 0);
611 TEST_VERIFY (_res
.nscount
== 2);
612 TEST_VERIFY (_res
.options
& RES_USE_EDNS0
);
613 /* Whether RES_ROTATE (originally in resolv.conf, now removed)
614 should be preserved is subject to debate. See bug 21701. */
615 /* TEST_VERIFY (!(_res.options & RES_ROTATE)); */
622 /* Test res_init change broadcast. This requires a second
623 thread to trigger the reload. */
625 support_write_file_string (_PATH_RESCONF
,
627 "nameserver 192.0.2.1\n");
628 for (int iteration
= 0; iteration
< 2; ++iteration
)
633 TEST_VERIFY (res_init () == 0);
637 unsigned char buf
[512];
639 (res_mkquery (QUERY
, test_hostname
, C_IN
, T_A
,
640 NULL
, 0, NULL
, buf
, sizeof (buf
)) > 0);
644 gethostbyname (test_hostname
);
649 (void) getaddrinfo (test_hostname
, NULL
, NULL
, &ai
);
655 TEST_VERIFY (_res
.options
& RES_USE_EDNS0
);
656 TEST_VERIFY (!(_res
.options
& RES_ROTATE
));
657 TEST_VERIFY (_res
.nscount
== 1);
658 support_write_file_string (_PATH_RESCONF
,
660 "nameserver 192.0.2.1\n"
661 "nameserver 192.0.2.2\n");
662 xpthread_join (xpthread_create
663 (NULL
, special_test_call_res_init
, NULL
));
667 /* edns0 was dropped, but the flag is not cleared. See
669 /* TEST_VERIFY (!(_res.options & RES_USE_EDNS0)); */
670 TEST_VERIFY (_res
.options
& RES_ROTATE
);
671 TEST_VERIFY (_res
.nscount
== 2);
680 /* Helper function which calls special_test_callback from a
683 special_test_thread_func (void *closure
)
685 special_test_callback (closure
);
689 /* Variant of special_test_callback which runs the function on a
692 run_special_test_on_thread (void *closure
)
694 xpthread_join (xpthread_create (NULL
, special_test_thread_func
, closure
));
696 #endif /* TEST_THREAD */
698 /* Perform the requested special test in a subprocess using
699 special_test_callback. */
701 special_test (unsigned int test_index
)
704 for (int do_thread
= 0; do_thread
< 2; ++do_thread
)
707 void (*func
) (void *) = special_test_callback
;
710 func
= run_special_test_on_thread
;
712 struct support_capture_subprocess proc
713 = support_capture_subprocess (func
, &test_index
);
714 char *test_name
= xasprintf ("special test %u", test_index
);
715 if (strcmp (proc
.out
.buffer
, "") != 0)
717 support_record_failure ();
718 printf ("error: output mismatch for %s\n", test_name
);
719 support_run_diff ("expected", "",
720 "actual", proc
.out
.buffer
);
722 support_capture_subprocess_check (&proc
, test_name
, 0, sc_allow_stdout
);
724 support_capture_subprocess_free (&proc
);
729 /* Dummy DNS server. It ensures that the probe queries sent by
730 gethostbyname and getaddrinfo receive a reply even if the system
731 applies a very strict rate limit to localhost. */
733 start_dummy_server (void)
735 int server_socket
= xsocket (AF_INET
, SOCK_DGRAM
, 0);
737 struct sockaddr_in sin
=
739 .sin_family
= AF_INET
,
740 .sin_addr
= { .s_addr
= htonl (INADDR_LOOPBACK
) },
741 .sin_port
= htons (53),
743 int ret
= bind (server_socket
, (struct sockaddr
*) &sin
, sizeof (sin
));
747 /* The port is reserved, which means we cannot start the
750 FAIL_EXIT1 ("cannot bind socket to port 53: %m");
754 pid_t pid
= xfork ();
757 /* Child process. Echo back queries as SERVFAIL responses. */
763 unsigned char bytes
[512];
765 struct sockaddr_in sin
;
766 socklen_t sinlen
= sizeof (sin
);
768 ssize_t ret
= recvfrom
769 (server_socket
, &packet
, sizeof (packet
),
770 MSG_NOSIGNAL
, (struct sockaddr
*) &sin
, &sinlen
);
772 FAIL_EXIT1 ("recvfrom on fake server socket: %m");
773 if (ret
> sizeof (HEADER
))
775 /* Turn the query into a SERVFAIL response. */
776 packet
.header
.qr
= 1;
777 packet
.header
.rcode
= ns_r_servfail
;
779 /* Send the response. */
780 ret
= sendto (server_socket
, &packet
, ret
,
781 MSG_NOSIGNAL
, (struct sockaddr
*) &sin
, sinlen
);
783 /* The peer may have closed socket prematurely, so
784 this is not an error. */
785 printf ("warning: sending DNS server reply: %m\n");
790 /* In the parent, close the socket. */
791 xclose (server_socket
);
799 support_become_root ();
800 support_enter_network_namespace ();
801 if (!support_in_uts_namespace () || !support_can_chroot ())
802 return EXIT_UNSUPPORTED
;
804 /* We are in an UTS namespace, so we can set the host name without
805 altering the state of the entire system. */
806 if (sethostname (test_hostname
, strlen (test_hostname
)) != 0)
807 FAIL_EXIT1 ("sethostname: %m");
809 /* These environment variables affect resolv.conf parsing. */
810 unsetenv ("LOCALDOMAIN");
811 unsetenv ("RES_OPTIONS");
813 /* Ensure that the chroot setup worked. */
815 struct support_capture_subprocess proc
816 = support_capture_subprocess (check_chroot_working
, NULL
);
817 support_capture_subprocess_check (&proc
, "chroot", 0, sc_allow_none
);
818 support_capture_subprocess_free (&proc
);
821 pid_t server
= start_dummy_server ();
823 for (size_t i
= 0; test_cases
[i
].name
!= NULL
; ++i
)
825 if (test_verbose
> 0)
826 printf ("info: running test: %s\n", test_cases
[i
].name
);
827 TEST_VERIFY (test_cases
[i
].conf
!= NULL
);
828 TEST_VERIFY (test_cases
[i
].expected
!= NULL
);
830 support_write_file_string (path_resolv_conf
, test_cases
[i
].conf
);
832 test_file_contents (&test_cases
[i
]);
834 /* The expected output from the empty file test is used for
836 if (test_cases
[i
].conf
[0] == '\0')
838 if (test_verbose
> 0)
839 printf ("info: special test: missing file\n");
840 TEST_VERIFY (unlink (path_resolv_conf
) == 0);
841 test_file_contents (&test_cases
[i
]);
843 if (test_verbose
> 0)
844 printf ("info: special test: dangling symbolic link\n");
845 TEST_VERIFY (symlink ("does-not-exist", path_resolv_conf
) == 0);
846 test_file_contents (&test_cases
[i
]);
847 TEST_VERIFY (unlink (path_resolv_conf
) == 0);
849 if (test_verbose
> 0)
850 printf ("info: special test: unreadable file\n");
851 support_write_file_string (path_resolv_conf
, "");
852 TEST_VERIFY (chmod (path_resolv_conf
, 0) == 0);
853 test_file_contents (&test_cases
[i
]);
855 /* Restore the empty file. */
856 TEST_VERIFY (unlink (path_resolv_conf
) == 0);
857 support_write_file_string (path_resolv_conf
, "");
861 /* The tests which do not follow a regular pattern. */
862 for (unsigned int test_index
= 0;
863 test_index
< special_tests_count
; ++test_index
)
864 special_test (test_index
);
868 if (kill (server
, SIGTERM
) < 0)
869 FAIL_EXIT1 ("could not terminate server process: %m");
870 xwaitpid (server
, NULL
, 0);
875 free (path_resolv_conf
);
876 path_resolv_conf
= NULL
;
880 #define PREPARE prepare
881 #include <support/test-driver.c>