1 /* Test _nss_dns_getcanonname_r corner cases.
2 Copyright (C) 2017-2024 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/>. */
21 #include <gnu/lib-names.h>
27 #include <support/check.h>
28 #include <support/resolv_test.h>
29 #include <support/support.h>
31 /* _nss_dns_getcanonname_r is not called during regular operation
32 because nss_dns directly provides a canonical name, so we have to
33 test it directly. The function pointer is initialized by do_test
35 static enum nss_status
36 (*getcanonname
) (const char *name
, char *buffer
, size_t buflen
,
37 char **result
, int *errnop
, int *h_errnop
);
40 response (const struct resolv_response_context
*ctx
,
41 struct resolv_response_builder
*b
,
42 const char *qname
, uint16_t qclass
, uint16_t qtype
)
47 if (sscanf (qname
, "code%d.%ms", &code
, &tail
) != 2
48 || strcmp (tail
, "example") != 0)
49 FAIL_EXIT1 ("error: invalid QNAME: %s\n", qname
);
56 resolv_response_init (b
, (struct resolv_response_flags
) {});
57 resolv_response_add_question (b
, qname
, qclass
, qtype
);
58 resolv_response_section (b
, ns_s_an
);
59 resolv_response_open_record (b
, "www.example", qclass
, qtype
, 0);
60 resolv_response_add_data (b
, "\xC0\x00\x02\x01", 4);
61 resolv_response_close_record (b
);
64 resolv_response_init (b
, (struct resolv_response_flags
) {});
65 resolv_response_add_question (b
, qname
, qclass
, qtype
);
66 resolv_response_section (b
, ns_s_an
);
69 resolv_response_open_record (b
, "www.example", qclass
, qtype
, 0);
70 resolv_response_add_data (b
, "\xC0\x00\x02\x01", 4);
71 resolv_response_close_record (b
);
72 for (int i
= 0; i
< 30000; ++i
)
73 resolv_response_add_data (b
, "", 1);
77 resolv_response_init (b
, (struct resolv_response_flags
) {});
78 resolv_response_add_question (b
, qname
, qclass
, qtype
);
79 resolv_response_section (b
, ns_s_an
);
82 resolv_response_open_record (b
, "www.example", qclass
, qtype
, 0);
83 resolv_response_add_data (b
, "\xC0\x00\x02\x01", 4);
84 resolv_response_close_record (b
);
88 for (int i
= 0; i
< 30000; ++i
)
89 resolv_response_add_data (b
, "", 1);
93 resolv_response_init (b
, (struct resolv_response_flags
) {});
94 resolv_response_add_question (b
, qname
, qclass
, qtype
);
95 resolv_response_section (b
, ns_s_an
);
96 resolv_response_open_record (b
, qname
, qclass
, T_CNAME
, 0);
97 resolv_response_add_name (b
, "www.example");
98 resolv_response_close_record (b
);
99 resolv_response_open_record (b
, "www.example", qclass
, qtype
, 0);
100 resolv_response_add_data (b
, "\xC0\x00\x02\x01", 4);
101 resolv_response_close_record (b
);
104 resolv_response_init (b
, (struct resolv_response_flags
) {});
105 resolv_response_add_question (b
, qname
, qclass
, qtype
);
106 resolv_response_section (b
, ns_s_an
);
107 resolv_response_open_record (b
, qname
, qclass
, T_CNAME
, 0);
108 resolv_response_add_name (b
, "www.example");
109 resolv_response_close_record (b
);
110 resolv_response_open_record (b
, qname
, qclass
, T_CNAME
, 0);
111 resolv_response_add_name (b
, "www1.example");
112 resolv_response_close_record (b
);
113 resolv_response_open_record (b
, "www1.example", qclass
, qtype
, 0);
114 resolv_response_add_data (b
, "\xC0\x00\x02\x01", 4);
115 resolv_response_close_record (b
);
118 resolv_response_init (b
, (struct resolv_response_flags
) {});
119 resolv_response_add_question (b
, qname
, qclass
, qtype
);
120 resolv_response_section (b
, ns_s_an
);
121 resolv_response_open_record (b
, qname
, qclass
, T_CNAME
, 0);
122 resolv_response_add_name (b
, "www.example");
123 resolv_response_close_record (b
);
124 resolv_response_open_record (b
, qname
, qclass
, 46 /* RRSIG */, 0);
125 resolv_response_add_name (b
, ".");
126 resolv_response_close_record (b
);
127 resolv_response_open_record (b
, "www.example", qclass
, qtype
, 0);
128 resolv_response_add_data (b
, "\xC0\x00\x02\x01", 4);
129 resolv_response_close_record (b
);
134 resolv_response_init (b
, (struct resolv_response_flags
) {.tc
= true});
135 resolv_response_add_question (b
, qname
, qclass
, qtype
);
140 (b
, (struct resolv_response_flags
) {.ancount
= 1});
141 resolv_response_add_question (b
, qname
, qclass
, qtype
);
142 resolv_response_section (b
, ns_s_an
);
143 resolv_response_open_record (b
, qname
, qclass
, T_CNAME
, 0);
144 size_t to_fill
= 65535 - resolv_response_length (b
)
145 - 2 /* length, "n" */ - 2 /* compression reference */
147 for (size_t i
= 0; i
< to_fill
; ++i
)
148 resolv_response_add_data (b
, "", 1);
149 resolv_response_close_record (b
);
150 resolv_response_add_name (b
, "n.example");
151 uint16_t rrtype
= htons (T_CNAME
);
152 resolv_response_add_data (b
, &rrtype
, sizeof (rrtype
));
156 /* NODATA response. */
157 resolv_response_init (b
, (struct resolv_response_flags
) {});
158 resolv_response_add_question (b
, qname
, qclass
, qtype
);
161 resolv_response_init (b
, (struct resolv_response_flags
) {.ancount
= 1});
162 resolv_response_add_question (b
, qname
, qclass
, qtype
);
163 /* No RR metadata. */
164 resolv_response_add_name (b
, "www.example");
169 resolv_response_init (b
, (struct resolv_response_flags
) {});
170 resolv_response_add_question (b
, qname
, qclass
, qtype
);
171 /* No data, trigger AAAA query. */
176 (b
, (struct resolv_response_flags
) {.ancount
= 1});
177 resolv_response_add_question (b
, qname
, qclass
, qtype
);
178 /* No RR metadata. */
179 resolv_response_add_name
180 (b
, "long-name-exceed-previously-initialized-buffer.example");
184 resolv_response_init (b
, (struct resolv_response_flags
) {.ancount
= 1});
185 resolv_response_add_question (b
, qname
, qclass
, qtype
);
186 /* No RR metadata. */
187 resolv_response_add_name (b
, "www.example");
188 resolv_response_add_data (b
, "\xff\xff", 2);
193 resolv_response_init (b
, (struct resolv_response_flags
) {});
194 resolv_response_add_question (b
, qname
, qclass
, qtype
);
195 /* No data, trigger AAAA query. */
200 (b
, (struct resolv_response_flags
) {.ancount
= 1});
201 resolv_response_add_question (b
, qname
, qclass
, qtype
);
202 /* No RR metadata. */
203 resolv_response_add_name (b
, "www.example");
204 resolv_response_add_data (b
, "\xff\xff", 2);
208 FAIL_EXIT1 ("error: invalid QNAME: %s (code %d)\n", qname
, code
);
213 check (int code
, const char *expected
)
216 snprintf (qname
, sizeof (qname
), "code%d.example", code
);
218 enum nss_status status
;
220 enum { buffer_size
= 4096 };
221 char *buffer
= xmalloc (buffer_size
);
225 status
= getcanonname
226 (qname
, buffer
, buffer_size
, &temp_result
, &temp_errno
, &temp_herrno
);
227 if (status
== NSS_STATUS_SUCCESS
)
228 result
= xstrdup (temp_result
);
232 h_errno
= temp_herrno
;
237 if (status
== NSS_STATUS_SUCCESS
)
239 if (expected
!= NULL
)
241 if (strcmp (result
, expected
) != 0)
243 support_record_failure ();
244 printf ("error: getcanonname (%s) failed\n", qname
);
245 printf ("error: expected: %s\n", expected
);
246 printf ("error: actual: %s\n", result
);
253 support_record_failure ();
254 printf ("error: getcanonname (%s) unexpected success\n", qname
);
255 printf ("error: actual: %s\n", result
);
263 if (expected
!= NULL
)
265 support_record_failure ();
266 printf ("error: getcanonname (%s) failed\n", qname
);
267 printf ("error: expected: %s\n", expected
);
277 void *nss_dns_handle
= dlopen (LIBNSS_DNS_SO
, RTLD_LAZY
);
278 if (nss_dns_handle
== NULL
)
279 FAIL_EXIT1 ("could not dlopen %s: %s", LIBNSS_DNS_SO
, dlerror ());
281 const char *func
= "_nss_dns_getcanonname_r";
282 void *ptr
= dlsym (nss_dns_handle
, func
);
284 FAIL_EXIT1 ("could not look up %s: %s", func
, dlerror ());
288 struct resolv_test
*aux
= resolv_test_start
289 ((struct resolv_redirect_config
)
291 .response_callback
= response
,
294 check (1, "www.example");
295 check (2, "www.example");
296 check (3, "www.example");
297 check (4, "www.example");
298 check (5, "www1.example");
300 /* This should really result in "www.example", but the fake RRSIG
301 record causes the current implementation to stop parsing. */
304 for (int i
= 102; i
<= 107; ++i
)
307 resolv_test_end (aux
);
309 TEST_VERIFY (dlclose (nss_dns_handle
) == 0);
313 #include <support/test-driver.c>