Prevent an implicit int promotion in malloc/tst-alloc_buffer.c
[glibc.git] / resolv / tst-resolv-basic.c
blob3dfa1657f50ab5880cb18a57d9e33a681efbc5c2
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/>. */
19 #include <errno.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <support/check.h>
24 #include <support/check_nss.h>
25 #include <support/resolv_test.h>
26 #include <support/support.h>
28 #define LONG_NAME \
29 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax." \
30 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay." \
31 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz." \
32 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat"
34 static void
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. */
42 bool force_tcp;
43 if (strncmp ("t.", qname, 2) == 0)
44 force_tcp = true;
45 else
46 force_tcp = false;
47 const char *qname_compare;
48 if (force_tcp)
49 qname_compare = qname + 2;
50 else
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;
61 else
63 support_record_failure ();
64 printf ("error: unexpected QNAME: %s\n", qname);
65 return;
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)
74 return;
76 resolv_response_section (b, ns_s_an);
77 switch (requested_qname)
79 case www:
80 case long_name:
81 resolv_response_open_record (b, qname, qclass, qtype, 0);
82 break;
83 case alias:
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);
88 break;
89 case nxdomain:
90 FAIL_EXIT1 ("unreachable");
92 switch (qtype)
94 case T_A:
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));
100 break;
101 case T_AAAA:
103 char ipv6[16]
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));
108 break;
109 default:
110 support_record_failure ();
111 printf ("error: unexpected QTYPE: %s/%u/%u\n",
112 qname, qclass, qtype);
114 resolv_response_close_record (b);
117 static void
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);
124 free (query);
127 char *query = xasprintf ("gethostbyname2 (\"%s\", %d)", name, family);
128 check_hostent (query, gethostbyname2 (name, family), expected);
129 free (query);
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);
137 too_small = false;
139 struct hostent hostbuf;
140 struct hostent *result;
141 int herror;
142 if (family == AF_INET)
144 char *query = xasprintf ("gethostbyname (\"%s\") %u/%u",
145 name, offset, size);
146 int ret = gethostbyname_r
147 (name, &hostbuf, buf + offset, size, &result, &herror);
148 if (ret == 0)
150 h_errno = herror;
151 check_hostent (query, result, expected);
153 else if (ret == ERANGE)
154 too_small = true;
155 else
157 errno = ret;
158 FAIL_EXIT1 ("gethostbyname_r: %m");
160 free (query);
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);
167 if (ret == 0)
169 h_errno = herror;
170 check_hostent (query, result, expected);
172 else if (ret == ERANGE)
173 too_small = true;
174 else
176 errno = ret;
177 FAIL_EXIT1 ("gethostbyname_r: %m");
179 free (buf);
180 free (query);
184 static void
185 check_ai_hints (const char *name, const char *service,
186 struct addrinfo hints, const char *expected)
188 struct addrinfo *ai;
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);
193 if (ret == 0)
194 freeaddrinfo (ai);
195 free (query);
198 static void
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, },
204 expected);
207 static int
208 do_test (void)
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);
419 return 0;
422 #include <support/test-driver.c>