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 response (const struct resolv_response_context
*ctx
,
30 struct resolv_response_builder
*b
,
31 const char *qname
, uint16_t qclass
, uint16_t qtype
)
33 TEST_VERIFY_EXIT (qname
!= NULL
);
35 /* The "t." prefix can be used to request TCP fallback. */
37 if (strncmp ("t.", qname
, 2) == 0)
41 const char *qname_compare
;
43 qname_compare
= qname
+ 2;
45 qname_compare
= qname
;
46 enum {www
, alias
, nxdomain
} requested_qname
;
47 if (strcmp (qname_compare
, "www.example") == 0)
48 requested_qname
= www
;
49 else if (strcmp (qname_compare
, "alias.example") == 0)
50 requested_qname
= alias
;
51 else if (strcmp (qname_compare
, "nxdomain.example") == 0)
52 requested_qname
= nxdomain
;
55 support_record_failure ();
56 printf ("error: unexpected QNAME: %s\n", qname
);
59 TEST_VERIFY_EXIT (qclass
== C_IN
);
60 struct resolv_response_flags flags
= {.tc
= force_tcp
&& !ctx
->tcp
};
61 if (requested_qname
== nxdomain
)
62 flags
.rcode
= 3; /* NXDOMAIN */
63 resolv_response_init (b
, flags
);
64 resolv_response_add_question (b
, qname
, qclass
, qtype
);
65 if (requested_qname
== nxdomain
|| flags
.tc
)
68 resolv_response_section (b
, ns_s_an
);
69 switch (requested_qname
)
72 resolv_response_open_record (b
, qname
, qclass
, qtype
, 0);
75 resolv_response_open_record (b
, qname
, qclass
, T_CNAME
, 0);
76 resolv_response_add_name (b
, "www.example");
77 resolv_response_close_record (b
);
78 resolv_response_open_record (b
, "www.example", qclass
, qtype
, 0);
81 FAIL_EXIT1 ("unreachable");
87 char ipv4
[4] = {192, 0, 2, 17};
88 ipv4
[3] += requested_qname
+ 2 * ctx
->tcp
+ 4 * ctx
->server_index
;
89 resolv_response_add_data (b
, &ipv4
, sizeof (ipv4
));
95 = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
96 ipv6
[15] += requested_qname
+ 2 * ctx
->tcp
+ 4 * ctx
->server_index
;
97 resolv_response_add_data (b
, &ipv6
, sizeof (ipv6
));
101 support_record_failure ();
102 printf ("error: unexpected QTYPE: %s/%u/%u\n",
103 qname
, qclass
, qtype
);
105 resolv_response_close_record (b
);
109 check_h (const char *name
, int family
, const char *expected
)
111 if (family
== AF_INET
)
113 char *query
= xasprintf ("gethostbyname (\"%s\")", name
);
114 check_hostent (query
, gethostbyname (name
), expected
);
118 char *query
= xasprintf ("gethostbyname2 (\"%s\", %d)", name
, family
);
119 check_hostent (query
, gethostbyname2 (name
, family
), expected
);
123 bool too_small
= true;
124 for (unsigned int offset
= 0; offset
< 8; ++offset
)
125 for (unsigned int size
= 1; too_small
; ++size
)
127 char *buf
= xmalloc (offset
+ size
);
130 struct hostent hostbuf
;
131 struct hostent
*result
;
133 if (family
== AF_INET
)
135 char *query
= xasprintf ("gethostbyname (\"%s\") %u/%u",
137 int ret
= gethostbyname_r
138 (name
, &hostbuf
, buf
+ offset
, size
, &result
, &herror
);
142 check_hostent (query
, result
, expected
);
144 else if (ret
== ERANGE
)
149 FAIL_EXIT1 ("gethostbyname_r: %m");
152 memset (buf
, 0, offset
+ size
);
154 char *query
= xasprintf ("gethostbyname2 (\"%s\", %d) %u/%u",
155 name
, family
, offset
, size
);
156 int ret
= gethostbyname2_r
157 (name
, family
, &hostbuf
, buf
+ offset
, size
, &result
, &herror
);
161 check_hostent (query
, result
, expected
);
163 else if (ret
== ERANGE
)
168 FAIL_EXIT1 ("gethostbyname_r: %m");
176 check_ai (const char *name
, const char *service
,
177 int family
, const char *expected
)
179 struct addrinfo hints
= {.ai_family
= family
};
181 char *query
= xasprintf ("%s:%s [%d]", name
, service
, family
);
182 int ret
= getaddrinfo (name
, service
, &hints
, &ai
);
183 check_addrinfo (query
, ai
, ret
, expected
);
192 struct resolv_test
*aux
= resolv_test_start
193 ((struct resolv_redirect_config
)
195 .response_callback
= response
,
198 check_h ("www.example", AF_INET
,
199 "name: www.example\n"
200 "address: 192.0.2.17\n");
201 check_h ("alias.example", AF_INET
,
202 "name: www.example\n"
203 "alias: alias.example\n"
204 "address: 192.0.2.18\n");
205 check_h ("www.example", AF_INET6
,
206 "name: www.example\n"
207 "address: 2001:db8::1\n");
208 check_h ("alias.example", AF_INET6
,
209 "name: www.example\n"
210 "alias: alias.example\n"
211 "address: 2001:db8::2\n");
212 check_ai ("www.example", "80", AF_UNSPEC
,
213 "address: STREAM/TCP 192.0.2.17 80\n"
214 "address: DGRAM/UDP 192.0.2.17 80\n"
215 "address: RAW/IP 192.0.2.17 80\n"
216 "address: STREAM/TCP 2001:db8::1 80\n"
217 "address: DGRAM/UDP 2001:db8::1 80\n"
218 "address: RAW/IP 2001:db8::1 80\n");
219 check_ai ("alias.example", "80", AF_UNSPEC
,
220 "address: STREAM/TCP 192.0.2.18 80\n"
221 "address: DGRAM/UDP 192.0.2.18 80\n"
222 "address: RAW/IP 192.0.2.18 80\n"
223 "address: STREAM/TCP 2001:db8::2 80\n"
224 "address: DGRAM/UDP 2001:db8::2 80\n"
225 "address: RAW/IP 2001:db8::2 80\n");
226 check_ai ("www.example", "80", AF_INET
,
227 "address: STREAM/TCP 192.0.2.17 80\n"
228 "address: DGRAM/UDP 192.0.2.17 80\n"
229 "address: RAW/IP 192.0.2.17 80\n");
230 check_ai ("alias.example", "80", AF_INET
,
231 "address: STREAM/TCP 192.0.2.18 80\n"
232 "address: DGRAM/UDP 192.0.2.18 80\n"
233 "address: RAW/IP 192.0.2.18 80\n");
234 check_ai ("www.example", "80", AF_INET6
,
235 "address: STREAM/TCP 2001:db8::1 80\n"
236 "address: DGRAM/UDP 2001:db8::1 80\n"
237 "address: RAW/IP 2001:db8::1 80\n");
238 check_ai ("alias.example", "80", AF_INET6
,
239 "address: STREAM/TCP 2001:db8::2 80\n"
240 "address: DGRAM/UDP 2001:db8::2 80\n"
241 "address: RAW/IP 2001:db8::2 80\n");
243 check_h ("t.www.example", AF_INET
,
244 "name: t.www.example\n"
245 "address: 192.0.2.19\n");
246 check_h ("t.alias.example", AF_INET
,
247 "name: www.example\n"
248 "alias: t.alias.example\n"
249 "address: 192.0.2.20\n");
250 check_h ("t.www.example", AF_INET6
,
251 "name: t.www.example\n"
252 "address: 2001:db8::3\n");
253 check_h ("t.alias.example", AF_INET6
,
254 "name: www.example\n"
255 "alias: t.alias.example\n"
256 "address: 2001:db8::4\n");
257 check_ai ("t.www.example", "80", AF_UNSPEC
,
258 "address: STREAM/TCP 192.0.2.19 80\n"
259 "address: DGRAM/UDP 192.0.2.19 80\n"
260 "address: RAW/IP 192.0.2.19 80\n"
261 "address: STREAM/TCP 2001:db8::3 80\n"
262 "address: DGRAM/UDP 2001:db8::3 80\n"
263 "address: RAW/IP 2001:db8::3 80\n");
264 check_ai ("t.alias.example", "80", AF_UNSPEC
,
265 "address: STREAM/TCP 192.0.2.20 80\n"
266 "address: DGRAM/UDP 192.0.2.20 80\n"
267 "address: RAW/IP 192.0.2.20 80\n"
268 "address: STREAM/TCP 2001:db8::4 80\n"
269 "address: DGRAM/UDP 2001:db8::4 80\n"
270 "address: RAW/IP 2001:db8::4 80\n");
271 check_ai ("t.www.example", "80", AF_INET
,
272 "address: STREAM/TCP 192.0.2.19 80\n"
273 "address: DGRAM/UDP 192.0.2.19 80\n"
274 "address: RAW/IP 192.0.2.19 80\n");
275 check_ai ("t.alias.example", "80", AF_INET
,
276 "address: STREAM/TCP 192.0.2.20 80\n"
277 "address: DGRAM/UDP 192.0.2.20 80\n"
278 "address: RAW/IP 192.0.2.20 80\n");
279 check_ai ("t.www.example", "80", AF_INET6
,
280 "address: STREAM/TCP 2001:db8::3 80\n"
281 "address: DGRAM/UDP 2001:db8::3 80\n"
282 "address: RAW/IP 2001:db8::3 80\n");
283 check_ai ("t.alias.example", "80", AF_INET6
,
284 "address: STREAM/TCP 2001:db8::4 80\n"
285 "address: DGRAM/UDP 2001:db8::4 80\n"
286 "address: RAW/IP 2001:db8::4 80\n");
288 check_h ("nxdomain.example", AF_INET
,
289 "error: HOST_NOT_FOUND\n");
290 check_h ("nxdomain.example", AF_INET6
,
291 "error: HOST_NOT_FOUND\n");
292 check_ai ("nxdomain.example", "80", AF_UNSPEC
,
293 "error: Name or service not known\n");
294 check_ai ("nxdomain.example", "80", AF_INET
,
295 "error: Name or service not known\n");
296 check_ai ("nxdomain.example", "80", AF_INET6
,
297 "error: Name or service not known\n");
299 check_h ("t.nxdomain.example", AF_INET
,
300 "error: HOST_NOT_FOUND\n");
301 check_h ("t.nxdomain.example", AF_INET6
,
302 "error: HOST_NOT_FOUND\n");
303 check_ai ("t.nxdomain.example", "80", AF_UNSPEC
,
304 "error: Name or service not known\n");
305 check_ai ("t.nxdomain.example", "80", AF_INET
,
306 "error: Name or service not known\n");
307 check_ai ("t.nxdomain.example", "80", AF_INET6
,
308 "error: Name or service not known\n");
310 resolv_test_end (aux
);
315 #include <support/test-driver.c>