diff options
Diffstat (limited to 'resolv/tst-resolv-basic.c')
-rw-r--r-- | resolv/tst-resolv-basic.c | 157 |
1 files changed, 119 insertions, 38 deletions
diff --git a/resolv/tst-resolv-basic.c b/resolv/tst-resolv-basic.c index 3dfa1657f5..66a0e8a165 100644 --- a/resolv/tst-resolv-basic.c +++ b/resolv/tst-resolv-basic.c @@ -22,6 +22,7 @@ #include <string.h> #include <support/check.h> #include <support/check_nss.h> +#include <support/format_nss.h> #include <support/resolv_test.h> #include <support/support.h> @@ -49,7 +50,7 @@ response (const struct resolv_response_context *ctx, qname_compare = qname + 2; else qname_compare = qname; - enum {www, alias, nxdomain, long_name} requested_qname; + enum {www, alias, nxdomain, long_name, nodata} requested_qname; if (strcmp (qname_compare, "www.example") == 0) requested_qname = www; else if (strcmp (qname_compare, "alias.example") == 0) @@ -58,6 +59,8 @@ response (const struct resolv_response_context *ctx, requested_qname = nxdomain; else if (strcmp (qname_compare, LONG_NAME) == 0) requested_qname = long_name; + else if (strcmp (qname_compare, "nodata.example") == 0) + requested_qname = nodata; else { support_record_failure (); @@ -86,6 +89,8 @@ response (const struct resolv_response_context *ctx, resolv_response_close_record (b); resolv_response_open_record (b, "www.example", qclass, qtype, 0); break; + case nodata: + return; case nxdomain: FAIL_EXIT1 ("unreachable"); } @@ -204,6 +209,117 @@ check_ai (const char *name, const char *service, expected); } +/* Test for bug 21295: getaddrinfo used to discard address information + instead of merging it. */ +static void +test_bug_21295 (void) +{ + /* The address order is unpredictable. There are two factors which + contribute to that: The stub resolver does not perform proper + response matching for A/AAAA queries (an A response could be + associated with an AAAA query and vice versa), and without + namespaces, system configuration could affect address + ordering. */ + for (int do_tcp = 0; do_tcp < 2; ++do_tcp) + { + const struct addrinfo hints = + { + .ai_family = AF_INET6, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_V4MAPPED | AI_ALL, + }; + const char *qname; + if (do_tcp) + qname = "t.www.example"; + else + qname = "www.example"; + struct addrinfo *ai = NULL; + int ret = getaddrinfo (qname, "80", &hints, &ai); + TEST_VERIFY_EXIT (ret == 0); + + const char *expected_a; + const char *expected_b; + if (do_tcp) + { + expected_a = "flags: AI_V4MAPPED AI_ALL\n" + "address: STREAM/TCP 2001:db8::3 80\n" + "address: STREAM/TCP ::ffff:192.0.2.19 80\n"; + expected_b = "flags: AI_V4MAPPED AI_ALL\n" + "address: STREAM/TCP ::ffff:192.0.2.19 80\n" + "address: STREAM/TCP 2001:db8::3 80\n"; + } + else + { + expected_a = "flags: AI_V4MAPPED AI_ALL\n" + "address: STREAM/TCP 2001:db8::1 80\n" + "address: STREAM/TCP ::ffff:192.0.2.17 80\n"; + expected_b = "flags: AI_V4MAPPED AI_ALL\n" + "address: STREAM/TCP ::ffff:192.0.2.17 80\n" + "address: STREAM/TCP 2001:db8::1 80\n"; + } + + char *actual = support_format_addrinfo (ai, ret); + if (!(strcmp (actual, expected_a) == 0 + || strcmp (actual, expected_b) == 0)) + { + support_record_failure (); + printf ("error: %s: unexpected response (TCP: %d):\n%s\n", + __func__, do_tcp, actual); + } + free (actual); + freeaddrinfo (ai); + } +} + +/* Run tests which do not expect any data. */ +static void +test_nodata_nxdomain (void) +{ + /* Iterate through different address families. */ + int families[] = { AF_UNSPEC, AF_INET, AF_INET6, -1 }; + for (int i = 0; families[i] >= 0; ++i) + /* If do_tcp, prepend "t." to the name to trigger TCP + fallback. */ + for (int do_tcp = 0; do_tcp < 2; ++do_tcp) + /* If do_nxdomain, trigger an NXDOMAIN error (DNS failure), + otherwise use a NODATA response (empty but successful + answer). */ + for (int do_nxdomain = 0; do_nxdomain < 2; ++do_nxdomain) + { + int family = families[i]; + char *name = xasprintf ("%s%s.example", + do_tcp ? "t." : "", + do_nxdomain ? "nxdomain" : "nodata"); + + if (family != AF_UNSPEC) + { + if (do_nxdomain) + check_h (name, family, "error: HOST_NOT_FOUND\n"); + else + check_h (name, family, "error: NO_ADDRESS\n"); + } + + const char *expected; + if (do_nxdomain) + expected = "error: Name or service not known\n"; + else + expected = "error: No address associated with hostname\n"; + + check_ai (name, "80", family, expected); + + struct addrinfo hints = + { + .ai_family = family, + .ai_flags = AI_V4MAPPED | AI_ALL, + }; + check_ai_hints (name, "80", hints, expected); + hints.ai_flags |= AI_CANONNAME; + check_ai_hints (name, "80", hints, expected); + + free (name); + } +} + static int do_test (void) { @@ -376,43 +492,8 @@ do_test (void) "address: DGRAM/UDP 2001:db8::4 80\n" "address: RAW/IP 2001:db8::4 80\n"); - check_h ("nxdomain.example", AF_INET, - "error: HOST_NOT_FOUND\n"); - check_h ("nxdomain.example", AF_INET6, - "error: HOST_NOT_FOUND\n"); - check_ai ("nxdomain.example", "80", AF_UNSPEC, - "error: Name or service not known\n"); - check_ai ("nxdomain.example", "80", AF_INET, - "error: Name or service not known\n"); - check_ai ("nxdomain.example", "80", AF_INET6, - "error: Name or service not known\n"); - - check_h ("t.nxdomain.example", AF_INET, - "error: HOST_NOT_FOUND\n"); - check_h ("t.nxdomain.example", AF_INET6, - "error: HOST_NOT_FOUND\n"); - check_ai ("t.nxdomain.example", "80", AF_UNSPEC, - "error: Name or service not known\n"); - check_ai ("t.nxdomain.example", "80", AF_INET, - "error: Name or service not known\n"); - check_ai ("t.nxdomain.example", "80", AF_INET6, - "error: Name or service not known\n"); - - /* Test for bug 21295. */ - check_ai_hints ("www.example", "80", - (struct addrinfo) { .ai_family = AF_INET6, - .ai_socktype = SOCK_STREAM, - .ai_flags = AI_V4MAPPED | AI_ALL, }, - "flags: AI_V4MAPPED AI_ALL\n" - "address: STREAM/TCP 2001:db8::1 80\n" - "address: STREAM/TCP ::ffff:192.0.2.17 80\n"); - check_ai_hints ("t.www.example", "80", - (struct addrinfo) { .ai_family = AF_INET6, - .ai_socktype = SOCK_STREAM, - .ai_flags = AI_V4MAPPED | AI_ALL, }, - "flags: AI_V4MAPPED AI_ALL\n" - "address: STREAM/TCP 2001:db8::3 80\n" - "address: STREAM/TCP ::ffff:192.0.2.19 80\n"); + test_bug_21295 (); + test_nodata_nxdomain (); resolv_test_end (aux); |