186 lines
6.1 KiB
Diff
186 lines
6.1 KiB
Diff
commit daab2a6d19f8360248289840408e7d2e5c203c2e
|
|
Author: Sergey Kolosov <skolosov@redhat.com>
|
|
Date: Tue Jun 3 22:10:20 2025 +0200
|
|
|
|
resolv: Add test for getaddrinfo returning FQDN in ai_canonname
|
|
|
|
Test for BZ #15218. This test verifies that getaddrinfo returns a
|
|
fully-qualified domain name in the ai_canonname field then
|
|
AI_CANONNAME is set and search domains apply.
|
|
|
|
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
|
|
|
diff --git a/resolv/Makefile b/resolv/Makefile
|
|
index 7659862ab257f7d3..9927676edac49e63 100644
|
|
--- a/resolv/Makefile
|
|
+++ b/resolv/Makefile
|
|
@@ -148,6 +148,7 @@ tests += \
|
|
tst-resolv-ai_idn-latin1 \
|
|
tst-resolv-ai_idn-nolibidn2 \
|
|
tst-resolv-canonname \
|
|
+ tst-resolv-getaddrinfo-fqdn \
|
|
tst-resolv-trustad \
|
|
|
|
# Needs resolv_context.
|
|
@@ -331,6 +332,7 @@ $(objpfx)tst-resolv-threads: $(objpfx)libresolv.so $(shared-thread-library)
|
|
$(objpfx)tst-resolv-txnid-collision: $(objpfx)libresolv.a \
|
|
$(static-thread-library)
|
|
$(objpfx)tst-resolv-canonname: $(objpfx)libresolv.so $(shared-thread-library)
|
|
+$(objpfx)tst-resolv-getaddrinfo-fqdn: $(objpfx)libresolv.so $(shared-thread-library)
|
|
$(objpfx)tst-resolv-trustad: $(objpfx)libresolv.so $(shared-thread-library)
|
|
|
|
$(objpfx)tst-ns_name: $(objpfx)libresolv.so
|
|
diff --git a/resolv/tst-resolv-getaddrinfo-fqdn.c b/resolv/tst-resolv-getaddrinfo-fqdn.c
|
|
new file mode 100644
|
|
index 0000000000000000..75bfe7e42a3e7023
|
|
--- /dev/null
|
|
+++ b/resolv/tst-resolv-getaddrinfo-fqdn.c
|
|
@@ -0,0 +1,147 @@
|
|
+/* Test for BZ #15218. Verify that getaddrinfo returns FQDN in
|
|
+ ai_canonname, when AI_CANONNAME is requested and search domain apply.
|
|
+ Copyright (C) 2025 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <https://www.gnu.org/licenses/>. */
|
|
+
|
|
+#include <resolv.h>
|
|
+#include <stdlib.h>
|
|
+#include <string.h>
|
|
+#include <support/check.h>
|
|
+#include <support/check_nss.h>
|
|
+#include <support/resolv_test.h>
|
|
+#include <support/support.h>
|
|
+
|
|
+static void
|
|
+response (const struct resolv_response_context *ctx,
|
|
+ struct resolv_response_builder *b,
|
|
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
|
+{
|
|
+ if (strcmp (qname, "foo.site.example") == 0
|
|
+ || strcmp (qname, "bar.foo.site.example") == 0
|
|
+ || strcmp (qname, "site.example") == 0)
|
|
+ {
|
|
+ struct resolv_response_flags flags = { };
|
|
+ resolv_response_init (b, flags);
|
|
+ resolv_response_add_question (b, qname, qclass, qtype);
|
|
+ resolv_response_section (b, ns_s_an);
|
|
+ if (qtype == T_A)
|
|
+ {
|
|
+ char addr_ipv4[4] = { 127, 126, 125, 124 };
|
|
+ resolv_response_open_record (b, qname, qclass, T_A, 0x12345678);
|
|
+ resolv_response_add_data (b, addr_ipv4, sizeof (addr_ipv4));
|
|
+ resolv_response_close_record (b);
|
|
+ }
|
|
+ else if (qtype == T_AAAA)
|
|
+ {
|
|
+ char addr_ipv6[16] =
|
|
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
|
|
+ resolv_response_open_record (b, qname, qclass, T_AAAA, 0x12345678);
|
|
+ resolv_response_add_data (b, addr_ipv6, sizeof (addr_ipv6));
|
|
+ resolv_response_close_record (b);
|
|
+ }
|
|
+ else
|
|
+ FAIL_EXIT1 ("qtype must be one of A, AAAA");
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ struct resolv_response_flags flags = {.rcode = ns_r_nxdomain, };
|
|
+ resolv_response_init (b, flags);
|
|
+ resolv_response_add_question (b, qname, qclass, qtype);
|
|
+ }
|
|
+}
|
|
+
|
|
+void
|
|
+query_host (const char *host_name, const char *expected_name)
|
|
+{
|
|
+ int family[] = { AF_INET, AF_INET6, AF_UNSPEC };
|
|
+ const char *family_names[] = { "AF_INET", "AF_INET6", "AF_UNSPEC" };
|
|
+
|
|
+ for (int i = 0; i < 3; i++)
|
|
+ {
|
|
+ struct addrinfo hints = {
|
|
+ .ai_socktype = 0,
|
|
+ .ai_protocol = 0,
|
|
+ .ai_family = family[i],
|
|
+ .ai_flags = AI_CANONNAME,
|
|
+ };
|
|
+ struct addrinfo *result, *current;
|
|
+ int res = getaddrinfo (host_name, NULL, &hints, &result);
|
|
+ if (res != 0)
|
|
+ FAIL_EXIT1 ("getaddrinfo (%s, %s): %s\n", host_name, family_names[i],
|
|
+ gai_strerror (res));
|
|
+ else
|
|
+ {
|
|
+ int count = 0;
|
|
+ for (current = result;
|
|
+ current != NULL && current->ai_canonname != NULL;
|
|
+ current = current->ai_next)
|
|
+ {
|
|
+ TEST_COMPARE_STRING (current->ai_canonname, expected_name);
|
|
+ count++;
|
|
+ }
|
|
+ freeaddrinfo (result);
|
|
+ if (count > 1)
|
|
+ FAIL_EXIT1 ("Expected exactly one canonname, but got %d\n", count);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/* test with site.example domain. */
|
|
+void
|
|
+test_search_with_site_example_domain (void)
|
|
+{
|
|
+ struct resolv_test *aux = resolv_test_start
|
|
+ ((struct resolv_redirect_config)
|
|
+ {
|
|
+ .response_callback = response,
|
|
+ .search = { "site.example" },
|
|
+ });
|
|
+
|
|
+ query_host ("foo", "foo.site.example");
|
|
+ query_host ("bar.foo", "bar.foo.site.example");
|
|
+
|
|
+ resolv_test_end (aux);
|
|
+}
|
|
+
|
|
+/* test with example domain. */
|
|
+void
|
|
+test_search_with_example_domain (void)
|
|
+{
|
|
+ struct resolv_test *aux = resolv_test_start
|
|
+ ((struct resolv_redirect_config)
|
|
+ {
|
|
+ .response_callback = response,
|
|
+ .search = { "example" },
|
|
+ });
|
|
+
|
|
+ query_host ("foo.site", "foo.site.example");
|
|
+ query_host ("bar.foo.site", "bar.foo.site.example");
|
|
+ query_host ("site", "site.example");
|
|
+
|
|
+ resolv_test_end (aux);
|
|
+}
|
|
+
|
|
+static int
|
|
+do_test (void)
|
|
+{
|
|
+ test_search_with_site_example_domain ();
|
|
+ test_search_with_example_domain ();
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#include <support/test-driver.c>
|