1 /* Test basic nss_dns functionality and the resolver test harness itself.
2 Copyright (C) 2016-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/>. */
23 #include <support/check.h>
24 #include <support/check_nss.h>
25 #include <support/resolv_test.h>
26 #include <support/support.h>
29 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax." \
30 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay." \
31 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz." \
32 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat"
35 response (const struct resolv_response_context
*ctx
,
36 struct resolv_response_builder
*b
,
37 const char *qname
, uint16_t qclass
, uint16_t qtype
)
39 TEST_VERIFY_EXIT (qname
!= NULL
);
41 /* The "t." prefix can be used to request TCP fallback. */
43 if (strncmp ("t.", qname
, 2) == 0)
47 const char *qname_compare
;
49 qname_compare
= qname
+ 2;
51 qname_compare
= qname
;
52 enum {www
, alias
, nxdomain
, long_name
} requested_qname
;
53 if (strcmp (qname_compare
, "www.example") == 0)
54 requested_qname
= www
;
55 else if (strcmp (qname_compare
, "alias.example") == 0)
56 requested_qname
= alias
;
57 else if (strcmp (qname_compare
, "nxdomain.example") == 0)
58 requested_qname
= nxdomain
;
59 else if (strcmp (qname_compare
, LONG_NAME
) == 0)
60 requested_qname
= long_name
;
63 support_record_failure ();
64 printf ("error: unexpected QNAME: %s\n", qname
);
67 TEST_VERIFY_EXIT (qclass
== C_IN
);
68 struct resolv_response_flags flags
= {.tc
= force_tcp
&& !ctx
->tcp
};
69 if (requested_qname
== nxdomain
)
70 flags
.rcode
= 3; /* NXDOMAIN */
71 resolv_response_init (b
, flags
);
72 resolv_response_add_question (b
, qname
, qclass
, qtype
);
73 if (requested_qname
== nxdomain
|| flags
.tc
)
76 resolv_response_section (b
, ns_s_an
);
77 switch (requested_qname
)
81 resolv_response_open_record (b
, qname
, qclass
, qtype
, 0);
84 resolv_response_open_record (b
, qname
, qclass
, T_CNAME
, 0);
85 resolv_response_add_name (b
, "www.example");
86 resolv_response_close_record (b
);
87 resolv_response_open_record (b
, "www.example", qclass
, qtype
, 0);
90 FAIL_EXIT1 ("unreachable");
96 char ipv4
[4] = {192, 0, 2, 17};
97 ipv4
[3] += requested_qname
+ 2 * ctx
->tcp
+ 4 * ctx
->server_index
;
98 resolv_response_add_data (b
, &ipv4
, sizeof (ipv4
));
104 = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
105 ipv6
[15] += requested_qname
+ 2 * ctx
->tcp
+ 4 * ctx
->server_index
;
106 resolv_response_add_data (b
, &ipv6
, sizeof (ipv6
));
110 support_record_failure ();
111 printf ("error: unexpected QTYPE: %s/%u/%u\n",
112 qname
, qclass
, qtype
);
114 resolv_response_close_record (b
);
118 check_h (const char *name
, int family
, const char *expected
)
120 if (family
== AF_INET
)
122 char *query
= xasprintf ("gethostbyname (\"%s\")", name
);
123 check_hostent (query
, gethostbyname (name
), expected
);
127 char *query
= xasprintf ("gethostbyname2 (\"%s\", %d)", name
, family
);
128 check_hostent (query
, gethostbyname2 (name
, family
), expected
);
132 bool too_small
= true;
133 for (unsigned int offset
= 0; offset
< 8; ++offset
)
134 for (unsigned int size
= 1; too_small
; ++size
)
136 char *buf
= xmalloc (offset
+ size
);
139 struct hostent hostbuf
;
140 struct hostent
*result
;
142 if (family
== AF_INET
)
144 char *query
= xasprintf ("gethostbyname (\"%s\") %u/%u",
146 int ret
= gethostbyname_r
147 (name
, &hostbuf
, buf
+ offset
, size
, &result
, &herror
);
151 check_hostent (query
, result
, expected
);
153 else if (ret
== ERANGE
)
158 FAIL_EXIT1 ("gethostbyname_r: %m");
161 memset (buf
, 0, offset
+ size
);
163 char *query
= xasprintf ("gethostbyname2 (\"%s\", %d) %u/%u",
164 name
, family
, offset
, size
);
165 int ret
= gethostbyname2_r
166 (name
, family
, &hostbuf
, buf
+ offset
, size
, &result
, &herror
);
170 check_hostent (query
, result
, expected
);
172 else if (ret
== ERANGE
)
177 FAIL_EXIT1 ("gethostbyname_r: %m");
185 check_ai_hints (const char *name
, const char *service
,
186 struct addrinfo hints
, const char *expected
)
189 char *query
= xasprintf ("%s:%s [%d]/0x%x", name
, service
,
190 hints
.ai_family
, hints
.ai_flags
);
191 int ret
= getaddrinfo (name
, service
, &hints
, &ai
);
192 check_addrinfo (query
, ai
, ret
, expected
);
199 check_ai (const char *name
, const char *service
,
200 int family
, const char *expected
)
202 return check_ai_hints (name
, service
,
203 (struct addrinfo
) { .ai_family
= family
, },
210 struct resolv_test
*aux
= resolv_test_start
211 ((struct resolv_redirect_config
)
213 .response_callback
= response
,
216 check_h ("www.example", AF_INET
,
217 "name: www.example\n"
218 "address: 192.0.2.17\n");
219 check_h ("alias.example", AF_INET
,
220 "name: www.example\n"
221 "alias: alias.example\n"
222 "address: 192.0.2.18\n");
223 check_h ("www.example", AF_INET6
,
224 "name: www.example\n"
225 "address: 2001:db8::1\n");
226 check_h ("alias.example", AF_INET6
,
227 "name: www.example\n"
228 "alias: alias.example\n"
229 "address: 2001:db8::2\n");
230 check_h (LONG_NAME
, AF_INET
,
231 "name: " LONG_NAME
"\n"
232 "address: 192.0.2.20\n");
234 check_ai ("www.example", "80", AF_UNSPEC
,
235 "address: STREAM/TCP 192.0.2.17 80\n"
236 "address: DGRAM/UDP 192.0.2.17 80\n"
237 "address: RAW/IP 192.0.2.17 80\n"
238 "address: STREAM/TCP 2001:db8::1 80\n"
239 "address: DGRAM/UDP 2001:db8::1 80\n"
240 "address: RAW/IP 2001:db8::1 80\n");
241 check_ai_hints ("www.example", "80",
242 (struct addrinfo
) { .ai_family
= AF_UNSPEC
,
243 .ai_flags
= AI_CANONNAME
, },
244 "flags: AI_CANONNAME\n"
245 "canonname: www.example\n"
246 "address: STREAM/TCP 192.0.2.17 80\n"
247 "address: DGRAM/UDP 192.0.2.17 80\n"
248 "address: RAW/IP 192.0.2.17 80\n"
249 "address: STREAM/TCP 2001:db8::1 80\n"
250 "address: DGRAM/UDP 2001:db8::1 80\n"
251 "address: RAW/IP 2001:db8::1 80\n");
252 check_ai ("alias.example", "80", AF_UNSPEC
,
253 "address: STREAM/TCP 192.0.2.18 80\n"
254 "address: DGRAM/UDP 192.0.2.18 80\n"
255 "address: RAW/IP 192.0.2.18 80\n"
256 "address: STREAM/TCP 2001:db8::2 80\n"
257 "address: DGRAM/UDP 2001:db8::2 80\n"
258 "address: RAW/IP 2001:db8::2 80\n");
259 check_ai_hints ("alias.example", "80",
260 (struct addrinfo
) { .ai_family
= AF_UNSPEC
,
261 .ai_flags
= AI_CANONNAME
, },
262 "flags: AI_CANONNAME\n"
263 "canonname: www.example\n"
264 "address: STREAM/TCP 192.0.2.18 80\n"
265 "address: DGRAM/UDP 192.0.2.18 80\n"
266 "address: RAW/IP 192.0.2.18 80\n"
267 "address: STREAM/TCP 2001:db8::2 80\n"
268 "address: DGRAM/UDP 2001:db8::2 80\n"
269 "address: RAW/IP 2001:db8::2 80\n");
270 check_ai (LONG_NAME
, "80", AF_UNSPEC
,
271 "address: STREAM/TCP 192.0.2.20 80\n"
272 "address: DGRAM/UDP 192.0.2.20 80\n"
273 "address: RAW/IP 192.0.2.20 80\n"
274 "address: STREAM/TCP 2001:db8::4 80\n"
275 "address: DGRAM/UDP 2001:db8::4 80\n"
276 "address: RAW/IP 2001:db8::4 80\n");
277 check_ai ("www.example", "80", AF_INET
,
278 "address: STREAM/TCP 192.0.2.17 80\n"
279 "address: DGRAM/UDP 192.0.2.17 80\n"
280 "address: RAW/IP 192.0.2.17 80\n");
281 check_ai_hints ("www.example", "80",
282 (struct addrinfo
) { .ai_family
= AF_INET
,
283 .ai_flags
= AI_CANONNAME
, },
284 "flags: AI_CANONNAME\n"
285 "canonname: www.example\n"
286 "address: STREAM/TCP 192.0.2.17 80\n"
287 "address: DGRAM/UDP 192.0.2.17 80\n"
288 "address: RAW/IP 192.0.2.17 80\n");
289 check_ai ("alias.example", "80", AF_INET
,
290 "address: STREAM/TCP 192.0.2.18 80\n"
291 "address: DGRAM/UDP 192.0.2.18 80\n"
292 "address: RAW/IP 192.0.2.18 80\n");
293 check_ai_hints ("alias.example", "80",
294 (struct addrinfo
) { .ai_family
= AF_INET
,
295 .ai_flags
= AI_CANONNAME
, },
296 "flags: AI_CANONNAME\n"
297 "canonname: www.example\n"
298 "address: STREAM/TCP 192.0.2.18 80\n"
299 "address: DGRAM/UDP 192.0.2.18 80\n"
300 "address: RAW/IP 192.0.2.18 80\n");
301 check_ai (LONG_NAME
, "80", AF_INET
,
302 "address: STREAM/TCP 192.0.2.20 80\n"
303 "address: DGRAM/UDP 192.0.2.20 80\n"
304 "address: RAW/IP 192.0.2.20 80\n");
305 check_ai ("www.example", "80", AF_INET6
,
306 "address: STREAM/TCP 2001:db8::1 80\n"
307 "address: DGRAM/UDP 2001:db8::1 80\n"
308 "address: RAW/IP 2001:db8::1 80\n");
309 check_ai_hints ("www.example", "80",
310 (struct addrinfo
) { .ai_family
= AF_INET6
,
311 .ai_flags
= AI_CANONNAME
, },
312 "flags: AI_CANONNAME\n"
313 "canonname: www.example\n"
314 "address: STREAM/TCP 2001:db8::1 80\n"
315 "address: DGRAM/UDP 2001:db8::1 80\n"
316 "address: RAW/IP 2001:db8::1 80\n");
317 check_ai ("alias.example", "80", AF_INET6
,
318 "address: STREAM/TCP 2001:db8::2 80\n"
319 "address: DGRAM/UDP 2001:db8::2 80\n"
320 "address: RAW/IP 2001:db8::2 80\n");
321 check_ai_hints ("alias.example", "80",
322 (struct addrinfo
) { .ai_family
= AF_INET6
,
323 .ai_flags
= AI_CANONNAME
, },
324 "flags: AI_CANONNAME\n"
325 "canonname: www.example\n"
326 "address: STREAM/TCP 2001:db8::2 80\n"
327 "address: DGRAM/UDP 2001:db8::2 80\n"
328 "address: RAW/IP 2001:db8::2 80\n");
329 check_ai (LONG_NAME
, "80", AF_INET6
,
330 "address: STREAM/TCP 2001:db8::4 80\n"
331 "address: DGRAM/UDP 2001:db8::4 80\n"
332 "address: RAW/IP 2001:db8::4 80\n");
334 check_h ("t.www.example", AF_INET
,
335 "name: t.www.example\n"
336 "address: 192.0.2.19\n");
337 check_h ("t.alias.example", AF_INET
,
338 "name: www.example\n"
339 "alias: t.alias.example\n"
340 "address: 192.0.2.20\n");
341 check_h ("t.www.example", AF_INET6
,
342 "name: t.www.example\n"
343 "address: 2001:db8::3\n");
344 check_h ("t.alias.example", AF_INET6
,
345 "name: www.example\n"
346 "alias: t.alias.example\n"
347 "address: 2001:db8::4\n");
348 check_ai ("t.www.example", "80", AF_UNSPEC
,
349 "address: STREAM/TCP 192.0.2.19 80\n"
350 "address: DGRAM/UDP 192.0.2.19 80\n"
351 "address: RAW/IP 192.0.2.19 80\n"
352 "address: STREAM/TCP 2001:db8::3 80\n"
353 "address: DGRAM/UDP 2001:db8::3 80\n"
354 "address: RAW/IP 2001:db8::3 80\n");
355 check_ai ("t.alias.example", "80", AF_UNSPEC
,
356 "address: STREAM/TCP 192.0.2.20 80\n"
357 "address: DGRAM/UDP 192.0.2.20 80\n"
358 "address: RAW/IP 192.0.2.20 80\n"
359 "address: STREAM/TCP 2001:db8::4 80\n"
360 "address: DGRAM/UDP 2001:db8::4 80\n"
361 "address: RAW/IP 2001:db8::4 80\n");
362 check_ai ("t.www.example", "80", AF_INET
,
363 "address: STREAM/TCP 192.0.2.19 80\n"
364 "address: DGRAM/UDP 192.0.2.19 80\n"
365 "address: RAW/IP 192.0.2.19 80\n");
366 check_ai ("t.alias.example", "80", AF_INET
,
367 "address: STREAM/TCP 192.0.2.20 80\n"
368 "address: DGRAM/UDP 192.0.2.20 80\n"
369 "address: RAW/IP 192.0.2.20 80\n");
370 check_ai ("t.www.example", "80", AF_INET6
,
371 "address: STREAM/TCP 2001:db8::3 80\n"
372 "address: DGRAM/UDP 2001:db8::3 80\n"
373 "address: RAW/IP 2001:db8::3 80\n");
374 check_ai ("t.alias.example", "80", AF_INET6
,
375 "address: STREAM/TCP 2001:db8::4 80\n"
376 "address: DGRAM/UDP 2001:db8::4 80\n"
377 "address: RAW/IP 2001:db8::4 80\n");
379 check_h ("nxdomain.example", AF_INET
,
380 "error: HOST_NOT_FOUND\n");
381 check_h ("nxdomain.example", AF_INET6
,
382 "error: HOST_NOT_FOUND\n");
383 check_ai ("nxdomain.example", "80", AF_UNSPEC
,
384 "error: Name or service not known\n");
385 check_ai ("nxdomain.example", "80", AF_INET
,
386 "error: Name or service not known\n");
387 check_ai ("nxdomain.example", "80", AF_INET6
,
388 "error: Name or service not known\n");
390 check_h ("t.nxdomain.example", AF_INET
,
391 "error: HOST_NOT_FOUND\n");
392 check_h ("t.nxdomain.example", AF_INET6
,
393 "error: HOST_NOT_FOUND\n");
394 check_ai ("t.nxdomain.example", "80", AF_UNSPEC
,
395 "error: Name or service not known\n");
396 check_ai ("t.nxdomain.example", "80", AF_INET
,
397 "error: Name or service not known\n");
398 check_ai ("t.nxdomain.example", "80", AF_INET6
,
399 "error: Name or service not known\n");
401 /* Test for bug 21295. */
402 check_ai_hints ("www.example", "80",
403 (struct addrinfo
) { .ai_family
= AF_INET6
,
404 .ai_socktype
= SOCK_STREAM
,
405 .ai_flags
= AI_V4MAPPED
| AI_ALL
, },
406 "flags: AI_V4MAPPED AI_ALL\n"
407 "address: STREAM/TCP 2001:db8::1 80\n"
408 "address: STREAM/TCP ::ffff:192.0.2.17 80\n");
409 check_ai_hints ("t.www.example", "80",
410 (struct addrinfo
) { .ai_family
= AF_INET6
,
411 .ai_socktype
= SOCK_STREAM
,
412 .ai_flags
= AI_V4MAPPED
| AI_ALL
, },
413 "flags: AI_V4MAPPED AI_ALL\n"
414 "address: STREAM/TCP 2001:db8::3 80\n"
415 "address: STREAM/TCP ::ffff:192.0.2.19 80\n");
417 resolv_test_end (aux
);
422 #include <support/test-driver.c>