From nobody Mon Oct 04 17:46:59 2021 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id BF19D10FD17E; Mon, 4 Oct 2021 17:46:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4HNSpC4FXRz3pgZ; Mon, 4 Oct 2021 17:46:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 6449C1D07B; Mon, 4 Oct 2021 17:46:59 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 194Hkxrt029860; Mon, 4 Oct 2021 17:46:59 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 194Hkxrn029859; Mon, 4 Oct 2021 17:46:59 GMT (envelope-from git) Date: Mon, 4 Oct 2021 17:46:59 GMT Message-Id: <202110041746.194Hkxrn029859@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: David Bright Subject: git: d18c9a919795 - main - RPCBIND: skip ipv6 link local when request is not from link local address List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: dab X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: d18c9a91979543adc182c7b28819691b64fda388 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by dab: URL: https://cgit.FreeBSD.org/src/commit/?id=d18c9a91979543adc182c7b28819691b64fda388 commit d18c9a91979543adc182c7b28819691b64fda388 Author: David Bright AuthorDate: 2021-10-04 15:43:41 +0000 Commit: David Bright CommitDate: 2021-10-04 17:45:26 +0000 RPCBIND: skip ipv6 link local when request is not from link local address RPCINFO on macOS behaves different compared to other linux clients and doesn't provide request address in rpcb structure of the RPCBPROC_GETADDRLIST call which doesn't seem to be forbidden. In this case RPCBIND uses RPC call's source address and picks a closest corresponding local address. If there are no addresses in the same subnet as the source address, return of RPCBIND may vary depending on the order of addresses returned in getifaddrs. If a link local precedes global address it may be returned even if the request comes from neither a link local nor from link local in a different scope, which will prevent services like nfs from working in tpc6 scenario on macOS clients. Issue can be seen only on FreeBSD rpcbind port due to changes in workflow of addrmerge call. Submitted by: Dmitry Ovsyannikov (Dmitry.Ovsyannikov@dell.com) Reviewers: dab Differential Revision: https://reviews.freebsd.org/D31491 Sponsored by: Dell EMC MFC to: stable/12, stable/13 MFC after: 1 week --- usr.sbin/rpcbind/tests/addrmerge_test.c | 34 +++++++++++++++++++++++++++++++++ usr.sbin/rpcbind/util.c | 12 +++++++----- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/usr.sbin/rpcbind/tests/addrmerge_test.c b/usr.sbin/rpcbind/tests/addrmerge_test.c index e1600f1a4837..a29dc30fdde8 100644 --- a/usr.sbin/rpcbind/tests/addrmerge_test.c +++ b/usr.sbin/rpcbind/tests/addrmerge_test.c @@ -257,6 +257,22 @@ mock_tun0(void) IFF_UP | IFF_RUNNING | IFF_POINTOPOINT | IFF_MULTICAST, 0, false); } +static void +mock_mlxen0(void) +{ + mock_ifaddr4("mlxen0", "192.0.3.1", "255.255.255.128", "192.0.3.127", + IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, + false); + /* Setting link local address before ipv6 address*/ + mock_ifaddr6("mlxen0", "fe80::4", "ffff:ffff:ffff:ffff::", + "fe80::ffff:ffff:ffff:ffff", + IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, + 3, false); + mock_ifaddr6("mlxen0", "2001:db8::7", "ffff:ffff:ffff:ffff::", + "2001:db8::ffff:ffff:ffff:ffff", + IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_SIMPLEX | IFF_MULTICAST, + 0, false); +} /* Stub rpcbind functions */ int @@ -835,6 +851,23 @@ ATF_TC_BODY(addrmerge_recvdstaddr6_rev, tc) ATF_CHECK_STREQ("2001:db8::2.3.46", maddr); free(maddr); } + +ATF_TC_WITHOUT_HEAD(addrmerge_ipv6_other_subnet); +ATF_TC_BODY(addrmerge_ipv6_other_subnet, tc) +{ + char *maddr; + + /* getifaddrs will return link local before normal ipv6 */ + mock_lo0(); + mock_mlxen0(); + + maddr = do_addrmerge6("2001:db8:1::1.3.46"); + + /* We must return the closest ipv6 address*/ + ATF_REQUIRE(maddr != NULL); + ATF_CHECK_STREQ("2001:db8::7.3.46", maddr); + free(maddr); +} #endif /* INET6 */ @@ -864,6 +897,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, addrmerge_ipv6_linklocal_rev); ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr6); ATF_TP_ADD_TC(tp, addrmerge_recvdstaddr6_rev); + ATF_TP_ADD_TC(tp, addrmerge_ipv6_other_subnet); #endif return (atf_no_error()); diff --git a/usr.sbin/rpcbind/util.c b/usr.sbin/rpcbind/util.c index 455578b657fb..e497e9227690 100644 --- a/usr.sbin/rpcbind/util.c +++ b/usr.sbin/rpcbind/util.c @@ -229,17 +229,19 @@ addrmerge(struct netbuf *caller, const char *serv_uaddr, const char *clnt_uaddr, * a link-local address then use the scope id to see * which one. */ - if (IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(ifsa)) && - IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(caller_sa)) && - IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(hint_sa))) { - if (SA2SIN6(ifsa)->sin6_scope_id == - SA2SIN6(caller_sa)->sin6_scope_id) { + if (IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(ifsa))) { + if (IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(caller_sa)) && + IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(hint_sa)) && + (SA2SIN6(ifsa)->sin6_scope_id == + SA2SIN6(caller_sa)->sin6_scope_id)) { const int goodness = 3; if (bestif_goodness < goodness) { bestif = ifap; bestif_goodness = goodness; } + } else { + continue; } } }