1 /* Test the RES_NOAAAA resolver option.
2 Copyright (C) 2022 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 <https://www.gnu.org/licenses/>. */
23 #include <support/check.h>
24 #include <support/check_nss.h>
25 #include <support/resolv_test.h>
26 #include <support/support.h>
28 /* Used to keep track of the number of queries. */
29 static volatile unsigned int queries
;
32 response (const struct resolv_response_context
*ctx
,
33 struct resolv_response_builder
*b
,
34 const char *qname
, uint16_t qclass
, uint16_t qtype
)
36 /* Each test should only send one query. */
38 TEST_COMPARE (queries
, 1);
40 /* AAAA queries are supposed to be disabled. */
41 TEST_VERIFY (qtype
!= T_AAAA
);
42 TEST_COMPARE (qclass
, C_IN
);
44 /* The only other query type besides A is PTR. */
46 TEST_COMPARE (qtype
, T_PTR
);
50 if (sscanf (qname
, "an%d.ns%d.ar%d.%ms", &an
, &ns
, &ar
, &tail
) != 4)
51 FAIL_EXIT1 ("invalid QNAME: %s\n", qname
);
52 TEST_COMPARE_STRING (tail
, "example");
55 if (an
< 0 || ns
< 0 || ar
< 0)
57 struct resolv_response_flags flags
= { .rcode
= NXDOMAIN
, };
58 resolv_response_init (b
, flags
);
59 resolv_response_add_question (b
, qname
, qclass
, qtype
);
63 struct resolv_response_flags flags
= {};
64 resolv_response_init (b
, flags
);
65 resolv_response_add_question (b
, qname
, qclass
, qtype
);
67 resolv_response_section (b
, ns_s_an
);
68 for (int i
= 0; i
< an
; ++i
)
70 resolv_response_open_record (b
, qname
, qclass
, qtype
, 60);
75 char ipv4
[4] = {192, 0, 2, i
+ 1};
76 resolv_response_add_data (b
, &ipv4
, sizeof (ipv4
));
82 char *name
= xasprintf ("ptr-%d", i
);
83 resolv_response_add_name (b
, name
);
88 resolv_response_close_record (b
);
91 resolv_response_section (b
, ns_s_ns
);
92 for (int i
= 0; i
< ns
; ++i
)
94 resolv_response_open_record (b
, qname
, qclass
, T_NS
, 60);
95 char *name
= xasprintf ("ns%d.example.net", i
);
96 resolv_response_add_name (b
, name
);
98 resolv_response_close_record (b
);
101 resolv_response_section (b
, ns_s_ar
);
103 for (int i
= 0; i
< ns
; ++i
)
105 char *name
= xasprintf ("ns%d.example.net", i
);
106 for (int j
= 0; j
< ar
; ++j
)
108 resolv_response_open_record (b
, name
, qclass
, T_A
, 60);
109 char ipv4
[4] = {192, 0, 2, addr
};
110 resolv_response_add_data (b
, &ipv4
, sizeof (ipv4
));
111 resolv_response_close_record (b
);
113 resolv_response_open_record (b
, name
, qclass
, T_AAAA
, 60);
115 = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, addr
};
116 resolv_response_add_data (b
, &ipv6
, sizeof (ipv6
));
117 resolv_response_close_record (b
);
125 /* Number of modes. Lowest bit encodes *n* function vs implicit _res
126 argument. The mode numbers themselves are arbitrary. */
127 enum { mode_count
= 8 };
129 /* res_send-like modes do not perform error translation. */
130 enum { first_send_mode
= 6 };
133 libresolv_query (unsigned int mode
, const char *qname
, uint16_t qtype
,
134 unsigned char *buf
, size_t buflen
)
136 int saved_errno
= errno
;
138 TEST_VERIFY_EXIT (mode
< mode_count
);
143 return res_query (qname
, C_IN
, qtype
, buf
, buflen
);
145 return res_nquery (&_res
, qname
, C_IN
, qtype
, buf
, buflen
);
147 return res_search (qname
, C_IN
, qtype
, buf
, buflen
);
149 return res_nsearch (&_res
, qname
, C_IN
, qtype
, buf
, buflen
);
151 return res_querydomain (qname
, "", C_IN
, qtype
, buf
, buflen
);
153 return res_nquerydomain (&_res
, qname
, "", C_IN
, qtype
, buf
, buflen
);
156 unsigned char querybuf
[512];
157 int ret
= res_mkquery (QUERY
, qname
, C_IN
, qtype
,
158 NULL
, 0, NULL
, querybuf
, sizeof (querybuf
));
159 TEST_VERIFY_EXIT (ret
> 0);
161 return res_send (querybuf
, ret
, buf
, buflen
);
165 unsigned char querybuf
[512];
166 int ret
= res_nmkquery (&_res
, QUERY
, qname
, C_IN
, qtype
,
167 NULL
, 0, NULL
, querybuf
, sizeof (querybuf
));
168 TEST_VERIFY_EXIT (ret
> 0);
170 return res_nsend (&_res
, querybuf
, ret
, buf
, buflen
);
173 __builtin_unreachable ();
179 struct resolv_test
*obj
= resolv_test_start
180 ((struct resolv_redirect_config
)
182 .response_callback
= response
185 _res
.options
|= RES_NOAAAA
;
187 check_hostent ("an1.ns2.ar1.example",
188 gethostbyname ("an1.ns2.ar1.example"),
189 "name: an1.ns2.ar1.example\n"
190 "address: 192.0.2.1\n");
192 check_hostent ("an0.ns2.ar1.example",
193 gethostbyname ("an0.ns2.ar1.example"),
194 "error: NO_ADDRESS\n");
196 check_hostent ("an-1.ns2.ar1.example",
197 gethostbyname ("an-1.ns2.ar1.example"),
198 "error: HOST_NOT_FOUND\n");
201 check_hostent ("an1.ns2.ar1.example AF_INET",
202 gethostbyname2 ("an1.ns2.ar1.example", AF_INET
),
203 "name: an1.ns2.ar1.example\n"
204 "address: 192.0.2.1\n");
206 check_hostent ("an0.ns2.ar1.example AF_INET",
207 gethostbyname2 ("an0.ns2.ar1.example", AF_INET
),
208 "error: NO_ADDRESS\n");
210 check_hostent ("an-1.ns2.ar1.example AF_INET",
211 gethostbyname2 ("an-1.ns2.ar1.example", AF_INET
),
212 "error: HOST_NOT_FOUND\n");
215 check_hostent ("an1.ns2.ar1.example AF_INET6",
216 gethostbyname2 ("an1.ns2.ar1.example", AF_INET6
),
217 "error: NO_ADDRESS\n");
219 check_hostent ("an0.ns2.ar1.example AF_INET6",
220 gethostbyname2 ("an0.ns2.ar1.example", AF_INET6
),
221 "error: NO_ADDRESS\n");
223 check_hostent ("an-1.ns2.ar1.example AF_INET6",
224 gethostbyname2 ("an-1.ns2.ar1.example", AF_INET6
),
225 "error: HOST_NOT_FOUND\n");
228 /* Multiple addresses. */
229 check_hostent ("an2.ns0.ar0.example",
230 gethostbyname ("an2.ns0.ar0.example"),
231 "name: an2.ns0.ar0.example\n"
232 "address: 192.0.2.1\n"
233 "address: 192.0.2.2\n");
235 check_hostent ("an2.ns0.ar0.example AF_INET6",
236 gethostbyname2 ("an2.ns0.ar0.example", AF_INET6
),
237 "error: NO_ADDRESS\n");
240 /* getaddrinfo checks with one address. */
243 ret
= getaddrinfo ("an1.ns2.ar1.example", "80",
246 .ai_family
= AF_INET
,
247 .ai_socktype
= SOCK_STREAM
,
249 check_addrinfo ("an1.ns2.ar1.example (AF_INET)", ai
, ret
,
250 "address: STREAM/TCP 192.0.2.1 80\n");
253 ret
= getaddrinfo ("an1.ns2.ar1.example", "80",
256 .ai_family
= AF_INET6
,
257 .ai_socktype
= SOCK_STREAM
,
259 check_addrinfo ("an1.ns2.ar1.example (AF_INET6)", ai
, ret
,
260 "error: No address associated with hostname\n");
262 ret
= getaddrinfo ("an1.ns2.ar1.example", "80",
265 .ai_family
= AF_UNSPEC
,
266 .ai_socktype
= SOCK_STREAM
,
268 check_addrinfo ("an1.ns2.ar1.example (AF_UNSPEC)", ai
, ret
,
269 "address: STREAM/TCP 192.0.2.1 80\n");
273 /* getaddrinfo checks with three addresses. */
274 ret
= getaddrinfo ("an3.ns2.ar1.example", "80",
277 .ai_family
= AF_INET
,
278 .ai_socktype
= SOCK_STREAM
,
280 check_addrinfo ("an3.ns2.ar1.example (AF_INET)", ai
, ret
,
281 "address: STREAM/TCP 192.0.2.1 80\n"
282 "address: STREAM/TCP 192.0.2.2 80\n"
283 "address: STREAM/TCP 192.0.2.3 80\n");
286 ret
= getaddrinfo ("an3.ns2.ar1.example", "80",
289 .ai_family
= AF_INET6
,
290 .ai_socktype
= SOCK_STREAM
,
292 check_addrinfo ("an3.ns2.ar1.example (AF_INET6)", ai
, ret
,
293 "error: No address associated with hostname\n");
295 ret
= getaddrinfo ("an3.ns2.ar1.example", "80",
298 .ai_family
= AF_UNSPEC
,
299 .ai_socktype
= SOCK_STREAM
,
301 check_addrinfo ("an3.ns2.ar1.example (AF_UNSPEC)", ai
, ret
,
302 "address: STREAM/TCP 192.0.2.1 80\n"
303 "address: STREAM/TCP 192.0.2.2 80\n"
304 "address: STREAM/TCP 192.0.2.3 80\n");
308 /* getaddrinfo checks with no address. */
309 ret
= getaddrinfo ("an0.ns2.ar1.example", "80",
312 .ai_family
= AF_INET
,
313 .ai_socktype
= SOCK_STREAM
,
315 check_addrinfo ("an0.ns2.ar1.example (AF_INET)", ai
, ret
,
316 "error: No address associated with hostname\n");
318 ret
= getaddrinfo ("an0.ns2.ar1.example", "80",
321 .ai_family
= AF_INET6
,
322 .ai_socktype
= SOCK_STREAM
,
324 check_addrinfo ("an0.ns2.ar1.example (AF_INET6)", ai
, ret
,
325 "error: No address associated with hostname\n");
327 ret
= getaddrinfo ("an0.ns2.ar1.example", "80",
330 .ai_family
= AF_UNSPEC
,
331 .ai_socktype
= SOCK_STREAM
,
333 check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai
, ret
,
334 "error: No address associated with hostname\n");
337 /* getaddrinfo checks with NXDOMAIN. */
338 ret
= getaddrinfo ("an-1.ns2.ar1.example", "80",
341 .ai_family
= AF_INET
,
342 .ai_socktype
= SOCK_STREAM
,
344 check_addrinfo ("an-1.ns2.ar1.example (AF_INET)", ai
, ret
,
345 "error: Name or service not known\n");
347 ret
= getaddrinfo ("an-1.ns2.ar1.example", "80",
350 .ai_family
= AF_INET6
,
351 .ai_socktype
= SOCK_STREAM
,
353 check_addrinfo ("an-1.ns2.ar1.example (AF_INET6)", ai
, ret
,
354 "error: Name or service not known\n");
356 ret
= getaddrinfo ("an-1.ns2.ar1.example", "80",
359 .ai_family
= AF_UNSPEC
,
360 .ai_socktype
= SOCK_STREAM
,
362 check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai
, ret
,
363 "error: Name or service not known\n");
366 for (unsigned int mode
= 0; mode
< mode_count
; ++mode
)
371 /* Response for A. */
373 ret
= libresolv_query (mode
, "an1.ns2.ar1.example", T_A
, buf
, 512);
374 TEST_VERIFY_EXIT (ret
> 0);
375 check_dns_packet ("an1.ns2.ar1.example A", buf
, ret
,
376 "name: an1.ns2.ar1.example\n"
377 "address: 192.0.2.1\n");
381 /* NODATA response for A. */
384 ret
= libresolv_query (mode
, "an0.ns2.ar1.example", T_A
, buf
, 512);
385 if (mode
< first_send_mode
)
387 TEST_COMPARE (ret
, -1);
388 TEST_COMPARE (errno
, 0);
389 TEST_COMPARE (h_errno
, NO_ADDRESS
);
393 TEST_VERIFY_EXIT (ret
> 0);
394 TEST_COMPARE (((HEADER
*)buf
)->rcode
, 0);
395 check_dns_packet ("an1.ns2.ar1.example A", buf
, ret
,
396 "name: an0.ns2.ar1.example\n");
401 /* NXDOMAIN response for A. */
404 ret
= libresolv_query (mode
, "an-1.ns2.ar1.example", T_A
, buf
, 512);
405 if (mode
< first_send_mode
)
407 TEST_COMPARE (ret
, -1);
408 TEST_COMPARE (errno
, 0);
409 TEST_COMPARE (h_errno
, HOST_NOT_FOUND
);
413 TEST_VERIFY_EXIT (ret
> 0);
414 TEST_COMPARE (((HEADER
*)buf
)->rcode
, NXDOMAIN
);
415 check_dns_packet ("an1.ns2.ar1.example A", buf
, ret
,
416 "name: an-1.ns2.ar1.example\n");
421 /* Response for PTR. */
423 ret
= libresolv_query (mode
, "an1.ns2.ar1.example", T_PTR
, buf
, 512);
424 TEST_VERIFY_EXIT (ret
> 0);
425 check_dns_packet ("an1.ns2.ar1.example PTR", buf
, ret
,
426 "name: an1.ns2.ar1.example\n"
427 "data: an1.ns2.ar1.example PTR ptr-0\n");
431 /* NODATA response for PTR. */
434 ret
= libresolv_query (mode
, "an0.ns2.ar1.example", T_PTR
, buf
, 512);
435 if (mode
< first_send_mode
)
437 TEST_COMPARE (ret
, -1);
438 TEST_COMPARE (errno
, 0);
439 TEST_COMPARE (h_errno
, NO_ADDRESS
);
443 TEST_VERIFY_EXIT (ret
> 0);
444 TEST_COMPARE (((HEADER
*)buf
)->rcode
, 0);
445 check_dns_packet ("an1.ns2.ar1.example PTR", buf
, ret
,
446 "name: an0.ns2.ar1.example\n");
451 /* NXDOMAIN response for PTR. */
454 ret
= libresolv_query (mode
, "an-1.ns2.ar1.example", T_PTR
, buf
, 512);
455 if (mode
< first_send_mode
)
457 TEST_COMPARE (ret
, -1);
458 TEST_COMPARE (errno
, 0);
459 TEST_COMPARE (h_errno
, HOST_NOT_FOUND
);
463 TEST_VERIFY_EXIT (ret
> 0);
464 TEST_COMPARE (((HEADER
*)buf
)->rcode
, NXDOMAIN
);
465 check_dns_packet ("an1.ns2.ar1.example PTR", buf
, ret
,
466 "name: an-1.ns2.ar1.example\n");
471 /* NODATA response for AAAA. */
474 ret
= libresolv_query (mode
, "an1.ns2.ar1.example", T_AAAA
, buf
, 512);
475 if (mode
< first_send_mode
)
477 TEST_COMPARE (ret
, -1);
478 TEST_COMPARE (errno
, 0);
479 TEST_COMPARE (h_errno
, NO_ADDRESS
);
483 TEST_VERIFY_EXIT (ret
> 0);
484 TEST_COMPARE (((HEADER
*)buf
)->rcode
, 0);
485 check_dns_packet ("an1.ns2.ar1.example A", buf
, ret
,
486 "name: an1.ns2.ar1.example\n");
491 /* NODATA response for AAAA (original is already NODATA). */
494 ret
= libresolv_query (mode
, "an0.ns2.ar1.example", T_AAAA
, buf
, 512);
495 if (mode
< first_send_mode
)
497 TEST_COMPARE (ret
, -1);
498 TEST_COMPARE (errno
, 0);
499 TEST_COMPARE (h_errno
, NO_ADDRESS
);
503 TEST_VERIFY_EXIT (ret
> 0);
504 TEST_COMPARE (((HEADER
*)buf
)->rcode
, 0);
505 check_dns_packet ("an0.ns2.ar1.example A", buf
, ret
,
506 "name: an0.ns2.ar1.example\n");
511 /* NXDOMAIN response. */
514 ret
= libresolv_query (mode
, "an-1.ns2.ar1.example", T_AAAA
, buf
, 512);
515 if (mode
< first_send_mode
)
517 TEST_COMPARE (ret
, -1);
518 TEST_COMPARE (errno
, 0);
519 TEST_COMPARE (h_errno
, HOST_NOT_FOUND
);
523 TEST_VERIFY_EXIT (ret
> 0);
524 TEST_COMPARE (((HEADER
*)buf
)->rcode
, NXDOMAIN
);
525 check_dns_packet ("an-1.ns2.ar1.example A", buf
, ret
,
526 "name: an-1.ns2.ar1.example\n");
532 resolv_test_end (obj
);
537 #include <support/test-driver.c>