From patchwork Mon Oct 20 16:00:19 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?UGV0ciBNZW7FocOtaw==?= X-Patchwork-Id: 122294 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4AEF73858408 for ; Mon, 20 Oct 2025 16:05:56 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4AEF73858408 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=ar4h60N5 X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 93CB03858402 for ; Mon, 20 Oct 2025 16:00:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 93CB03858402 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 93CB03858402 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1760976059; cv=none; b=kT/2gSiOZ5B2jcDc4CGh43UNyIClqQfNxT0mKEfYgIO27fXxgPlDx/M9cj4GkHug3NstHjKk9SxUl8QoSyei2m5hBVJ5ZJE+H96rtQhINtmP2S2sJ3huaSanSMgQLpDMaIlxy9Rv/XvhSvpffKWQCoJhdwbbbGvwZGLNYVpeAyY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1760976059; c=relaxed/simple; bh=tZYPvD3mcCqjxHIYuYx8ILJ4oQoGBJXd8m8+6si+nmE=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=SPtB4fHYAGA6tAwaHLOUk2JBL0BI7uegJ6erfAxcCBx62DWf7HpZG0d+46HRrDPO9X8vB38iVrdiyrxaIMyDvB+AAw1E3AGqRTFP1/3x9gZaDPtfFGpLDXW3FRxnTLJGmaym77ziuk3Xv0mZVcF04qVikgZx3fFNNOLBEmXOai0= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 93CB03858402 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1760976059; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4st21iT8Hk5mqeDrpaXPVZMbQ47o49DebNJ2UA4lOR0=; b=ar4h60N5Bly5/ONGQhtMYngLReM6Tyyot9KiClps4PFeELrlAjauliktpZvCuLPzqf+uRt jA1nuHAnWcHS698QLlJFY1diBwgh58KX9nSZhihodmA/0Z/bYwwYBCdsB5gtA9RcLHjrW3 HhpjMjG9epdsY+3mDGBUe0NNzD2qpn4= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-645-dHuUuW_IPGKk0XjqQkq9uw-1; Mon, 20 Oct 2025 12:00:57 -0400 X-MC-Unique: dHuUuW_IPGKk0XjqQkq9uw-1 X-Mimecast-MFC-AGG-ID: dHuUuW_IPGKk0XjqQkq9uw_1760976054 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 81D7F1956087 for ; Mon, 20 Oct 2025 16:00:54 +0000 (UTC) Received: from pemensik-thinkpadp1gen4i.brq.csb (unknown [10.44.32.76]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BAC3E1956056; Mon, 20 Oct 2025 16:00:52 +0000 (UTC) From: =?utf-8?b?UGV0ciBNZW7FocOtaw==?= To: libc-alpha@sourceware.org Cc: =?utf-8?b?UGV0ciBNZW7FocOtaw==?= Subject: [PATCH v7 2/2] resolv: Create test for ipv4 and ipv6 resolv.conf flags Date: Mon, 20 Oct 2025 18:00:19 +0200 Message-ID: <20251020160017.1574993-4-pemensik@redhat.com> In-Reply-To: <20251020160017.1574993-2-pemensik@redhat.com> References: <20251020160017.1574993-2-pemensik@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: htSjF_tWw_rpCQIZaguI4o8QQV0eXD3l8zBw3Tp5If8_1760976054 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_PASS, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org Test newly added resolv.conf options ipv4 and ipv6. Derived from noaaa test. Count query counts after the test, because it varies depending on used flags. Fixed ai re-initialization on each attempt. Signed-off-by: Petr Menšík --- resolv/Makefile | 2 + resolv/tst-resolv-ipv4-ipv6.c | 639 ++++++++++++++++++++++++++++++++++ 2 files changed, 641 insertions(+) create mode 100644 resolv/tst-resolv-ipv4-ipv6.c diff --git a/resolv/Makefile b/resolv/Makefile index 8fa3398d76..36cd6f76c8 100644 --- a/resolv/Makefile +++ b/resolv/Makefile @@ -105,6 +105,7 @@ tests += \ tst-resolv-binary \ tst-resolv-byaddr \ tst-resolv-edns \ + tst-resolv-ipv4-ipv6 \ tst-resolv-invalid-cname \ tst-resolv-network \ tst-resolv-noaaaa \ @@ -300,6 +301,7 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \ $(shared-thread-library) $(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \ $(shared-thread-library) +$(objpfx)tst-resolv-ipv4-ipv6: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-resolv-invalid-cname: $(objpfx)libresolv.so \ $(shared-thread-library) $(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library) diff --git a/resolv/tst-resolv-ipv4-ipv6.c b/resolv/tst-resolv-ipv4-ipv6.c new file mode 100644 index 0000000000..d375a0989e --- /dev/null +++ b/resolv/tst-resolv-ipv4-ipv6.c @@ -0,0 +1,639 @@ +/* Test RES_IPV4 and RES_IPV6 resolver option. + 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 + . */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Used to keep track of the number of queries. */ +static volatile unsigned int queries; + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + /* Each test should only send one query. */ + ++queries; + if (queries < 1 || queries > 2) + FAIL_EXIT1 ("Unexpected number of queries %d on %s\n", queries, qname); + TEST_COMPARE (qclass, C_IN); + + /* The only other query type besides A is PTR. */ + if (qtype != T_A && qtype != T_AAAA) + TEST_COMPARE (qtype, T_PTR); + + int an, ns, ar; + char *tail; + if (sscanf (qname, "an%d.ns%d.ar%d.%ms", &an, &ns, &ar, &tail) != 4) + FAIL_EXIT1 ("invalid QNAME: %s\n", qname); + TEST_COMPARE_STRING (tail, "example"); + free (tail); + + if (an < 0 || ns < 0 || ar < 0) + { + struct resolv_response_flags flags = { .rcode = NXDOMAIN, }; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + return; + } + + 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); + for (int i = 0; i < an; ++i) + { + resolv_response_open_record (b, qname, qclass, qtype, 60); + switch (qtype) + { + case T_A: + { + char ipv4[4] = {192, 0, 2, i + 1}; + resolv_response_add_data (b, &ipv4, sizeof (ipv4)); + } + break; + + case T_AAAA: + { + char addr_ipv6[16] = + { 0x20, 1, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, i + 1 }; + resolv_response_add_data (b, addr_ipv6, sizeof (addr_ipv6)); + } + break; + + case T_PTR: + { + char *name = xasprintf ("ptr-%d", i); + resolv_response_add_name (b, name); + free (name); + } + break; + } + resolv_response_close_record (b); + } + + resolv_response_section (b, ns_s_ns); + for (int i = 0; i < ns; ++i) + { + resolv_response_open_record (b, qname, qclass, T_NS, 60); + char *name = xasprintf ("ns%d.example.net", i); + resolv_response_add_name (b, name); + free (name); + resolv_response_close_record (b); + } + + resolv_response_section (b, ns_s_ar); + int addr = 1; + for (int i = 0; i < ns; ++i) + { + char *name = xasprintf ("ns%d.example.net", i); + for (int j = 0; j < ar; ++j) + { + resolv_response_open_record (b, name, qclass, T_A, 60); + char ipv4[4] = {192, 0, 2, addr}; + resolv_response_add_data (b, &ipv4, sizeof (ipv4)); + resolv_response_close_record (b); + + resolv_response_open_record (b, name, qclass, T_AAAA, 60); + char ipv6[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, addr}; + resolv_response_add_data (b, &ipv6, sizeof (ipv6)); + resolv_response_close_record (b); + + ++addr; + } + free (name); + } +} + +/* Number of modes. Lowest bit encodes *n* function vs implicit _res + argument. The mode numbers themselves are arbitrary. */ +enum { mode_count = 8 }; + +/* res_send-like modes do not perform error translation. */ +enum { first_send_mode = 6 }; + +static int +libresolv_query (unsigned int mode, const char *qname, uint16_t qtype, + unsigned char *buf, size_t buflen) +{ + int saved_errno = errno; + + TEST_VERIFY_EXIT (mode < mode_count); + + switch (mode) + { + case 0: + return res_query (qname, C_IN, qtype, buf, buflen); + case 1: + return res_nquery (&_res, qname, C_IN, qtype, buf, buflen); + case 2: + return res_search (qname, C_IN, qtype, buf, buflen); + case 3: + return res_nsearch (&_res, qname, C_IN, qtype, buf, buflen); + case 4: + return res_querydomain (qname, "", C_IN, qtype, buf, buflen); + case 5: + return res_nquerydomain (&_res, qname, "", C_IN, qtype, buf, buflen); + case 6: + { + unsigned char querybuf[512]; + int ret = res_mkquery (QUERY, qname, C_IN, qtype, + NULL, 0, NULL, querybuf, sizeof (querybuf)); + TEST_VERIFY_EXIT (ret > 0); + errno = saved_errno; + return res_send (querybuf, ret, buf, buflen); + } + case 7: + { + unsigned char querybuf[512]; + int ret = res_nmkquery (&_res, QUERY, qname, C_IN, qtype, + NULL, 0, NULL, querybuf, sizeof (querybuf)); + TEST_VERIFY_EXIT (ret > 0); + errno = saved_errno; + return res_nsend (&_res, querybuf, ret, buf, buflen); + } + } + __builtin_unreachable (); +} + +/* Common parts should not change behaviour whatever flag is used. */ +static int +do_test_common(void) +{ + queries = 0; + + /* getaddrinfo checks with one address. */ + struct addrinfo *ai = NULL; + int ret; + ret = getaddrinfo ("an1.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an1.ns2.ar1.example (AF_INET)", ai, ret, + "address: STREAM/TCP 192.0.2.1 80\n"); + freeaddrinfo (ai); + ai = NULL; + TEST_COMPARE (queries, 1); + + queries = 0; + ret = getaddrinfo ("an1.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_INET6, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an1.ns2.ar1.example (AF_INET6)", ai, ret, + "address: STREAM/TCP 2001:db8::1 80\n"); + freeaddrinfo (ai); + ai = NULL; + TEST_COMPARE (queries, 1); + queries = 0; + + /* getaddrinfo checks with three addresses. */ + ret = getaddrinfo ("an3.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an3.ns2.ar1.example (AF_INET)", ai, ret, + "address: STREAM/TCP 192.0.2.1 80\n" + "address: STREAM/TCP 192.0.2.2 80\n" + "address: STREAM/TCP 192.0.2.3 80\n"); + freeaddrinfo (ai); + ai = NULL; + TEST_COMPARE (queries, 1); + queries = 0; + ret = getaddrinfo ("an3.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_INET6, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an3.ns2.ar1.example (AF_INET6)", ai, ret, + "address: STREAM/TCP 2001:db8::1 80\n" + "address: STREAM/TCP 2001:db8::2 80\n" + "address: STREAM/TCP 2001:db8::3 80\n"); + freeaddrinfo (ai); + ai = NULL; + TEST_COMPARE (queries, 1); + queries = 0; + + return ret; +} + +/* test IPV4 flag */ +static int +do_test_ipv4 (int options) +{ + int ret; + struct addrinfo *ai = NULL; + + _res.options = options; + queries = 0; + + ret = do_test_common(); + + /* getaddrinfo checks with one address. */ + ret = getaddrinfo ("an1.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an1.ns2.ar1.example (AF_UNSPEC) ipv4", ai, ret, + "address: STREAM/TCP 192.0.2.1 80\n"); + freeaddrinfo (ai); + ai = NULL; + TEST_COMPARE (queries, 1); + + queries = 0; + ret = getaddrinfo ("an3.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an3.ns2.ar1.example (AF_UNSPEC) ipv4", ai, ret, + "address: STREAM/TCP 192.0.2.1 80\n" + "address: STREAM/TCP 192.0.2.2 80\n" + "address: STREAM/TCP 192.0.2.3 80\n"); + freeaddrinfo (ai); + ai = NULL; + TEST_COMPARE (queries, 1); + queries = 0; + + return ret; +} + +static int +do_test_ipv6 (int options) +{ + int ret; + struct addrinfo *ai = NULL; + + _res.options = options; + queries = 0; + + ret = do_test_common(); + + /* getaddrinfo checks with one address. */ + ret = getaddrinfo ("an1.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an1.ns2.ar1.example (AF_UNSPEC) ipv6", ai, ret, + "address: STREAM/TCP 2001:db8::1 80\n"); + freeaddrinfo (ai); + ai = NULL; + TEST_COMPARE (queries, 1); + queries = 0; + + /* getaddrinfo checks with three addresses. */ + ret = getaddrinfo ("an3.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an3.ns2.ar1.example (AF_UNSPEC) ipv6", ai, ret, + "address: STREAM/TCP 2001:db8::1 80\n" + "address: STREAM/TCP 2001:db8::2 80\n" + "address: STREAM/TCP 2001:db8::3 80\n"); + freeaddrinfo (ai); + ai = NULL; + TEST_COMPARE (queries, 1); + queries = 0; + + return ret; +} + +/* When both flags are applied */ +static int +do_test_ipv4_ipv6 (int options) +{ + int ret; + struct addrinfo *ai = NULL; + + _res.options = options; + queries = 0; + + ret = do_test_common(); + + /* getaddrinfo checks with one address. */ + ret = getaddrinfo ("an1.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an1.ns2.ar1.example (AF_UNSPEC) ipv4 ipv6", ai, ret, + "address: STREAM/TCP 192.0.2.1 80\n" + "address: STREAM/TCP 2001:db8::1 80\n"); + freeaddrinfo (ai); + ai = NULL; + TEST_COMPARE (queries, 2); + queries = 0; + + /* getaddrinfo checks with three addresses. */ + ret = getaddrinfo ("an3.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an3.ns2.ar1.example (AF_UNSPEC) ipv4 ipv6", ai, ret, + "address: STREAM/TCP 192.0.2.1 80\n" + "address: STREAM/TCP 192.0.2.2 80\n" + "address: STREAM/TCP 192.0.2.3 80\n" + "address: STREAM/TCP 2001:db8::1 80\n" + "address: STREAM/TCP 2001:db8::2 80\n" + "address: STREAM/TCP 2001:db8::3 80\n"); + freeaddrinfo (ai); + ai = NULL; + TEST_COMPARE (queries, 2); + queries = 0; + + return ret; +} + +static int +do_test (void) +{ + int baseoptions; + int ret; + struct addrinfo *ai = NULL; + struct resolv_test *obj = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response + }); + + baseoptions = _res.options; + + ret = do_test_ipv4(baseoptions | RES_IPV4); + ret = do_test_ipv6(baseoptions | RES_IPV6); + ret = do_test_ipv4_ipv6(baseoptions); + ret = do_test_ipv4_ipv6(baseoptions | RES_IPV4 | RES_IPV6); + + /* getaddrinfo checks with no address. */ + ret = getaddrinfo ("an0.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an0.ns2.ar1.example (AF_INET)", ai, ret, + "error: No address associated with hostname\n"); + freeaddrinfo (ai); + ai = NULL; + queries = 0; + ret = getaddrinfo ("an0.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_INET6, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an0.ns2.ar1.example (AF_INET6)", ai, ret, + "error: No address associated with hostname\n"); + freeaddrinfo (ai); + ai = NULL; + queries = 0; + ret = getaddrinfo ("an0.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai, ret, + "error: No address associated with hostname\n"); + freeaddrinfo (ai); + ai = NULL; + queries = 0; + + /* getaddrinfo checks with NXDOMAIN. */ + ret = getaddrinfo ("an-1.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an-1.ns2.ar1.example (AF_INET)", ai, ret, + "error: Name or service not known\n"); + freeaddrinfo (ai); + ai = NULL; + queries = 0; + ret = getaddrinfo ("an-1.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_INET6, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an-1.ns2.ar1.example (AF_INET6)", ai, ret, + "error: Name or service not known\n"); + freeaddrinfo (ai); + ai = NULL; + queries = 0; + ret = getaddrinfo ("an-1.ns2.ar1.example", "80", + &(struct addrinfo) + { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }, &ai); + check_addrinfo ("an-1.ns2.ar1.example (AF_UNSPEC)", ai, ret, + "error: Name or service not known\n"); + freeaddrinfo (ai); + ai = NULL; + queries = 0; + + for (unsigned int mode = 0; mode < mode_count; ++mode) + { + unsigned char *buf; + int ret; + + /* Response for A. */ + buf = malloc (512); + ret = libresolv_query (mode, "an1.ns2.ar1.example", T_A, buf, 512); + TEST_VERIFY_EXIT (ret > 0); + check_dns_packet ("an1.ns2.ar1.example A", buf, ret, + "name: an1.ns2.ar1.example\n" + "address: 192.0.2.1\n"); + free (buf); + queries = 0; + + /* NODATA response for A. */ + buf = malloc (512); + errno = 0; + ret = libresolv_query (mode, "an0.ns2.ar1.example", T_A, buf, 512); + if (mode < first_send_mode) + { + TEST_COMPARE (ret, -1); + TEST_COMPARE (errno, 0); + TEST_COMPARE (h_errno, NO_ADDRESS); + } + else + { + TEST_VERIFY_EXIT (ret > 0); + TEST_COMPARE (((HEADER *)buf)->rcode, 0); + check_dns_packet ("an1.ns2.ar1.example A", buf, ret, + "name: an0.ns2.ar1.example\n"); + } + free (buf); + queries = 0; + + /* NXDOMAIN response for A. */ + buf = malloc (512); + errno = 0; + ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_A, buf, 512); + if (mode < first_send_mode) + { + TEST_COMPARE (ret, -1); + TEST_COMPARE (errno, 0); + TEST_COMPARE (h_errno, HOST_NOT_FOUND); + } + else + { + TEST_VERIFY_EXIT (ret > 0); + TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); + check_dns_packet ("an1.ns2.ar1.example A", buf, ret, + "name: an-1.ns2.ar1.example\n"); + } + free (buf); + queries = 0; + + /* Response for PTR. */ + buf = malloc (512); + ret = libresolv_query (mode, "an1.ns2.ar1.example", T_PTR, buf, 512); + TEST_VERIFY_EXIT (ret > 0); + check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, + "name: an1.ns2.ar1.example\n" + "data: an1.ns2.ar1.example PTR ptr-0\n"); + free (buf); + queries = 0; + + /* NODATA response for PTR. */ + buf = malloc (512); + errno = 0; + ret = libresolv_query (mode, "an0.ns2.ar1.example", T_PTR, buf, 512); + if (mode < first_send_mode) + { + TEST_COMPARE (ret, -1); + TEST_COMPARE (errno, 0); + TEST_COMPARE (h_errno, NO_ADDRESS); + } + else + { + TEST_VERIFY_EXIT (ret > 0); + TEST_COMPARE (((HEADER *)buf)->rcode, 0); + check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, + "name: an0.ns2.ar1.example\n"); + } + free (buf); + queries = 0; + + /* NXDOMAIN response for PTR. */ + buf = malloc (512); + errno = 0; + ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_PTR, buf, 512); + if (mode < first_send_mode) + { + TEST_COMPARE (ret, -1); + TEST_COMPARE (errno, 0); + TEST_COMPARE (h_errno, HOST_NOT_FOUND); + } + else + { + TEST_VERIFY_EXIT (ret > 0); + TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); + check_dns_packet ("an1.ns2.ar1.example PTR", buf, ret, + "name: an-1.ns2.ar1.example\n"); + } + free (buf); + queries = 0; + + /* NODATA response for AAAA. */ + buf = malloc (512); + errno = 0; + ret = libresolv_query (mode, "an1.ns2.ar1.example", T_AAAA, buf, 512); + TEST_VERIFY_EXIT (ret > 0); + check_dns_packet ("an1.ns2.ar1.example AAAA", buf, ret, + "name: an1.ns2.ar1.example\n" + "address: 2001:db8::1\n"); + TEST_VERIFY_EXIT (ret > 0); + free (buf); + queries = 0; + + /* NODATA response for AAAA (original is already NODATA). */ + buf = malloc (512); + errno = 0; + ret = libresolv_query (mode, "an0.ns2.ar1.example", T_AAAA, buf, 512); + if (mode < first_send_mode) + { + TEST_COMPARE (ret, -1); + TEST_COMPARE (errno, 0); + TEST_COMPARE (h_errno, NO_ADDRESS); + } + else + { + TEST_VERIFY_EXIT (ret > 0); + TEST_COMPARE (((HEADER *)buf)->rcode, 0); + check_dns_packet ("an0.ns2.ar1.example A", buf, ret, + "name: an0.ns2.ar1.example\n"); + } + free (buf); + queries = 0; + + /* NXDOMAIN response. */ + buf = malloc (512); + errno = 0; + ret = libresolv_query (mode, "an-1.ns2.ar1.example", T_AAAA, buf, 512); + if (mode < first_send_mode) + { + TEST_COMPARE (ret, -1); + TEST_COMPARE (errno, 0); + TEST_COMPARE (h_errno, HOST_NOT_FOUND); + } + else + { + TEST_VERIFY_EXIT (ret > 0); + TEST_COMPARE (((HEADER *)buf)->rcode, NXDOMAIN); + check_dns_packet ("an-1.ns2.ar1.example A", buf, ret, + "name: an-1.ns2.ar1.example\n"); + } + free (buf); + queries = 0; + } + + resolv_test_end (obj); + + return 0; +} + +#include