From patchwork Wed Sep 6 11:46:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 810521 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=sourceware.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=libc-alpha-return-84235-incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b="D7im+zDA"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xnMH93YQmz9s9Y for ; Wed, 6 Sep 2017 21:46:13 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:to:subject:mime-version:content-type :content-transfer-encoding:message-id:from; q=dns; s=default; b= Pa52bBHlxIifan4j0aW8Hs00J4OKeceEjikJX4qQbauYCD4WK17b1RS/9D6mKfam rm5pt8dsaLGnu/6LlObeox8Th9p398kP1X1clS391Cc+c9OVzdHjbFZ8l2o5xQ7J 83jToA1cZmHmWX7y5BM29f3A55M5sgIUwTPaDzmU38s= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:to:subject:mime-version:content-type :content-transfer-encoding:message-id:from; s=default; bh=SMrxv6 sAGq8xxRqU+70LKBRwxqI=; b=D7im+zDAIunFzdlTfoKa/XfLinXX/WW4SxbLl+ sUXiPxJIBvpD4PR6jyIbqmDgHYgyYdxTexZ87MKBCSr9tfl3Rm1ZuD9hSRn3IZe2 IcReerkpibrY8SVHJV4VFAR2ha9RlRmM12GROIA8qaRDyL4PkxpUXUfaKhM19N8G 3276I= Received: (qmail 18832 invoked by alias); 6 Sep 2017 11:46:08 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 16407 invoked by uid 89); 6 Sep 2017 11:46:06 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=1944 X-HELO: mx1.redhat.com DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 785E54E4CA Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=fweimer@redhat.com Date: Wed, 06 Sep 2017 13:46:01 +0200 To: libc-alpha@sourceware.org Subject: [PATCH COMMITTED] tst-res_use_inet6: Enhance test to cover IPv4-to-IPv6 address mapping User-Agent: Heirloom mailx 12.5 7/5/10 MIME-Version: 1.0 Message-Id: <20170906114601.222C14194EE14@oldenburg.str.redhat.com> From: fweimer@redhat.com (Florian Weimer) This requires more control over the response data, so it is now determined by flags embedded in the query name. 2017-09-06 Florian Weimer Enhance tst-res_use_inet6 to test IPv4-to-IPv6 address mapping. * resolv/tst-res_use_inet6.c (response): Process flags embedded in the QNAME. (test_gai): Adjust query names. Add additional tests. (test_get2_any, test_get2_no_inet6, test_get2_inet6): Split from test_get2. Adjust query names. Add additional tests. (test_no_inet6): New function, extracted from threadfunc. (threadfunc): Call test_get2_any, test_get2_inet6, test_no_inet6. Add additional tests. diff --git a/resolv/tst-res_use_inet6.c b/resolv/tst-res_use_inet6.c index 6f3db08892..1522d5c5f5 100644 --- a/resolv/tst-res_use_inet6.c +++ b/resolv/tst-res_use_inet6.c @@ -19,18 +19,44 @@ #include #include #include +#include #include #include #include +/* Produce a response based on QNAME: Certain characters in the first + label of QNAME trigger the inclusion of resource records: + + 'a' A record (IPv4 address) + 'q' AAAA record (quad A record, IPv6 address) + 'm' record type must match QTYPE (no additional records) + + QTYPE is ignored for record type selection if 'm' is not + specified. */ static void response (const struct resolv_response_context *ctx, struct resolv_response_builder *b, const char *qname, uint16_t qclass, uint16_t qtype) { - bool include_both = strcmp (qname, "both.example") == 0; - bool include_a = qtype == T_A || include_both; - bool include_aaaa = qtype == T_AAAA || include_both; + bool include_a = false; + bool include_aaaa = false; + bool include_match = false; + for (const char *p = qname; *p != '.' && *p != '\0'; ++p) + { + if (*p == 'a') + include_a = true; + else if (*p == 'q') + include_aaaa = true; + else if (*p == 'm') + include_match = true; + } + if (include_match) + { + if (qtype == T_A) + include_aaaa = false; + else if (qtype == T_AAAA) + include_a = false; + } resolv_response_init (b, (struct resolv_response_flags) {}); resolv_response_add_question (b, qname, qclass, qtype); @@ -64,16 +90,21 @@ test_gai (void) .ai_protocol = IPPROTO_TCP, }; struct addrinfo *ai; - int ret = getaddrinfo ("www1.example", "80", &hints, &ai); - check_addrinfo ("getaddrinfo AF_UNSPEC www1.example", ai, ret, + int ret = getaddrinfo ("qam.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_UNSPEC qam.example", ai, ret, "address: STREAM/TCP 192.0.2.17 80\n" "address: STREAM/TCP 2001:db8::1 80\n"); if (ret == 0) freeaddrinfo (ai); - ret = getaddrinfo ("both.example", "80", &hints, &ai); + ret = getaddrinfo ("am.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_UNSPEC am.example", ai, ret, + "address: STREAM/TCP 192.0.2.17 80\n"); + if (ret == 0) + freeaddrinfo (ai); + ret = getaddrinfo ("qa.example", "80", &hints, &ai); /* Combined A/AAAA responses currently result in address duplication. */ - check_addrinfo ("getaddrinfo AF_UNSPEC both.example", ai, ret, + check_addrinfo ("getaddrinfo AF_UNSPEC qa.example", ai, ret, "address: STREAM/TCP 192.0.2.17 80\n" "address: STREAM/TCP 192.0.2.17 80\n" "address: STREAM/TCP 2001:db8::1 80\n" @@ -89,13 +120,18 @@ test_gai (void) .ai_protocol = IPPROTO_TCP, }; struct addrinfo *ai; - int ret = getaddrinfo ("www1.example", "80", &hints, &ai); - check_addrinfo ("getaddrinfo AF_INET www1.example", ai, ret, + int ret = getaddrinfo ("qam.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET qam.example", ai, ret, "address: STREAM/TCP 192.0.2.17 80\n"); if (ret == 0) freeaddrinfo (ai); - ret = getaddrinfo ("both.example", "80", &hints, &ai); - check_addrinfo ("getaddrinfo AF_INET both.example", ai, ret, + ret = getaddrinfo ("am.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET am.example", ai, ret, + "address: STREAM/TCP 192.0.2.17 80\n"); + if (ret == 0) + freeaddrinfo (ai); + ret = getaddrinfo ("qa.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET qa.example", ai, ret, "address: STREAM/TCP 192.0.2.17 80\n"); if (ret == 0) freeaddrinfo (ai); @@ -108,40 +144,131 @@ test_gai (void) .ai_protocol = IPPROTO_TCP, }; struct addrinfo *ai; - int ret = getaddrinfo ("www1.example", "80", &hints, &ai); + int ret = getaddrinfo ("qa.example", "80", &hints, &ai); check_addrinfo ("getaddrinfo (AF_INET6)", ai, ret, "address: STREAM/TCP 2001:db8::1 80\n"); if (ret == 0) freeaddrinfo (ai); - ret = getaddrinfo ("both.example", "80", &hints, &ai); - check_addrinfo ("getaddrinfo AF_INET6 both.example", ai, ret, + ret = getaddrinfo ("am.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET6 am.example", ai, ret, + "error: No address associated with hostname\n"); + if (ret == 0) + freeaddrinfo (ai); + ret = getaddrinfo ("qam.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET6 qam.example", ai, ret, "address: STREAM/TCP 2001:db8::1 80\n"); if (ret == 0) freeaddrinfo (ai); } } -/* Test that gethostbyname2 is not influenced by RES_USE_INET6. */ +/* Test that gethostbyname2 is mostly not influenced by + RES_USE_INET6. */ static void -test_get2 (void) +test_get2_any (void) { - check_hostent ("gethostbyname2 AF_INET www1.example", - gethostbyname2 ("www1.example", AF_INET), - "name: www1.example\n" + check_hostent ("gethostbyname2 AF_INET am.example", + gethostbyname2 ("am.example", AF_INET), + "name: am.example\n" "address: 192.0.2.17\n"); - check_hostent ("gethostbyname2 AF_INET both.example", - gethostbyname2 ("both.example", AF_INET), - "name: both.example\n" + check_hostent ("gethostbyname2 AF_INET a.example", + gethostbyname2 ("a.example", AF_INET), + "name: a.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname2 AF_INET qm.example", + gethostbyname2 ("qm.example", AF_INET), + "error: NO_ADDRESS\n"); + check_hostent ("gethostbyname2 AF_INET q.example", + gethostbyname2 ("q.example", AF_INET), + "error: NO_RECOVERY\n"); + check_hostent ("gethostbyname2 AF_INET qam.example", + gethostbyname2 ("qam.example", AF_INET), + "name: qam.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname2 AF_INET qa.example", + gethostbyname2 ("qa.example", AF_INET), + "name: qa.example\n" "address: 192.0.2.17\n"); - check_hostent ("gethostbyname2 AF_INET6 www1.example", - gethostbyname2 ("www1.example", AF_INET6), - "name: www1.example\n" + check_hostent ("gethostbyname2 AF_INET6 qm.example", + gethostbyname2 ("qm.example", AF_INET6), + "name: qm.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname2 AF_INET6 q.example", + gethostbyname2 ("q.example", AF_INET6), + "name: q.example\n" "address: 2001:db8::1\n"); - check_hostent ("gethostbyname2 AF_INET6 both.example", - gethostbyname2 ("both.example", AF_INET6), - "name: both.example\n" + check_hostent ("gethostbyname2 AF_INET6 qam.example", + gethostbyname2 ("qam.example", AF_INET6), + "name: qam.example\n" "address: 2001:db8::1\n"); + check_hostent ("gethostbyname2 AF_INET6 qa.example", + gethostbyname2 ("qa.example", AF_INET6), + "name: qa.example\n" + "address: 2001:db8::1\n"); + /* Additional AF_INET6 tests depend on RES_USE_INET6; see below. */ +} + +/* gethostbyname2 tests with RES_USE_INET6 disabled. */ +static void +test_get2_no_inet6 (void) +{ + test_get2_any (); + + check_hostent ("gethostbyname2 AF_INET6 am.example", + gethostbyname2 ("am.example", AF_INET6), + "error: NO_ADDRESS\n"); + check_hostent ("gethostbyname2 AF_INET6 a.example", + gethostbyname2 ("a.example", AF_INET6), + "error: NO_RECOVERY\n"); +} + +/* gethostbyname2 tests with RES_USE_INET6 enabled. */ +static void +test_get2_inet6 (void) +{ + test_get2_any (); + + check_hostent ("gethostbyname2 AF_INET6 am.example", + gethostbyname2 ("am.example", AF_INET6), + "name: am.example\n" + "address: ::ffff:192.0.2.17\n"); + check_hostent ("gethostbyname2 AF_INET6 a.example", + gethostbyname2 ("a.example", AF_INET6), + "error: NO_RECOVERY\n"); +} + +/* Collection of tests which assume no RES_USE_INET6 flag. */ +static void +test_no_inet6 (void) +{ + check_hostent ("gethostbyname (\"a.example\")", + gethostbyname ("a.example"), + "name: a.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname (\"qa.example\")", + gethostbyname ("qa.example"), + "name: qa.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname (\"am.example\")", + gethostbyname ("am.example"), + "name: am.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname (\"qam.example\")", + gethostbyname ("qam.example"), + "name: qam.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname (\"q.example\")", + gethostbyname ("q.example"), + "error: NO_RECOVERY\n"); + check_hostent ("gethostbyname (\"qm.example\")", + gethostbyname ("qm.example"), + "error: NO_ADDRESS\n"); + test_get2_no_inet6 (); + test_get2_no_inet6 (); + test_gai (); + test_get2_no_inet6 (); + test_get2_no_inet6 (); } static void * @@ -153,28 +280,42 @@ threadfunc (void *ignored) .response_callback = response }); - check_hostent ("gethostbyname (\"www1.example\")", - gethostbyname ("www1.example"), - "name: www1.example\n" - "address: 192.0.2.17\n"); - check_hostent ("gethostbyname (\"both.example\")", - gethostbyname ("both.example"), - "name: both.example\n" - "address: 192.0.2.17\n"); - test_get2 (); - test_gai (); + TEST_VERIFY ((_res.options & RES_USE_INET6) == 0); + test_no_inet6 (); _res.options |= RES_USE_INET6; - check_hostent ("gethostbyname (\"www1.example\")", - gethostbyname ("www1.example"), - "name: www1.example\n" + check_hostent ("gethostbyname (\"a.inet6.example\")", + gethostbyname ("a.inet6.example"), + "error: NO_RECOVERY\n"); + check_hostent ("gethostbyname (\"am.inet6.example\")", + gethostbyname ("am.inet6.example"), + "name: am.inet6.example\n" + "address: ::ffff:192.0.2.17\n"); + check_hostent ("gethostbyname (\"qa.inet6.example\")", + gethostbyname ("qa.inet6.example"), + "name: qa.inet6.example\n" "address: 2001:db8::1\n"); - check_hostent ("gethostbyname (\"both.example\")", - gethostbyname ("both.example"), - "name: both.example\n" + check_hostent ("gethostbyname (\"qam.inet6.example\")", + gethostbyname ("qam.inet6.example"), + "name: qam.inet6.example\n" "address: 2001:db8::1\n"); - test_get2 (); + check_hostent ("gethostbyname (\"q.inet6.example\")", + gethostbyname ("q.inet6.example"), + "name: q.inet6.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname (\"qm.inet6.example\")", + gethostbyname ("qm.inet6.example"), + "name: qm.inet6.example\n" + "address: 2001:db8::1\n"); + test_get2_inet6 (); + test_get2_inet6 (); test_gai (); + test_get2_inet6 (); + test_get2_inet6 (); + + TEST_VERIFY (_res.options & RES_USE_INET6); + _res.options &= ~RES_USE_INET6; + test_no_inet6 (); resolv_test_end (obj);