From: "J. Bruce Fields" <bfields@fieldses.org>
To: Chuck Lever <chuck.lever@oracle.com>
Cc: steved@redhat.com, linux-nfs@vger.kernel.org
Subject: Re: [PATCH 04/14] text-based mount command: get_client_address support for IPv6
Date: Thu, 10 Jul 2008 15:30:08 -0400 [thread overview]
Message-ID: <20080710193008.GA27734@fieldses.org> (raw)
In-Reply-To: <20080710003723.6137.51761.stgit-lQeC5l55kZ7wdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
On Wed, Jul 09, 2008 at 08:37:24PM -0400, Chuck Lever wrote:
> Introduce IPv6-enabled version of get_client_address. The legacy mount
> command could use this eventually as well.
>
> I don't remember how to tell an NFSv4 server to disable the callback
> channel: whether an ANY address is passed with SETCLIENTID, or a
> loopback address is passed. The patch allows either to be used with a
> compile-time switch.
I would have thought INADDR_ANY. But in any case we should just pick
one....
--b.
>
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
>
> utils/mount/network.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++
> utils/mount/network.h | 2 +
> 2 files changed, 124 insertions(+), 0 deletions(-)
>
> diff --git a/utils/mount/network.c b/utils/mount/network.c
> index 3f2721b..128d7f7 100644
> --- a/utils/mount/network.c
> +++ b/utils/mount/network.c
> @@ -918,3 +918,125 @@ int get_client_address(struct sockaddr_in *saddr, struct sockaddr_in *caddr)
> }
> return 1;
> }
> +
> +/*
> + * Try a getsockname() on a connected datagram socket.
> + *
> + * Returns 1 and fills in @buf if successful; otherwise, zero.
> + *
> + * A connected datagram socket prevents leaving a socket in TIME_WAIT.
> + * This conserves the ephemeral port number space, helping reduce failed
> + * socket binds during mount storms.
> + */
> +static int nfs_ca_sockname(const struct sockaddr *sap, const socklen_t salen,
> + struct sockaddr *buf, socklen_t *buflen)
> +{
> + struct sockaddr_in sin = {
> + .sin_family = AF_INET,
> + .sin_addr.s_addr = htonl(INADDR_ANY),
> + };
> + struct sockaddr_in6 sin6 = {
> + .sin6_family = AF_INET6,
> + .sin6_addr = IN6ADDR_ANY_INIT,
> + };
> + int sock;
> +
> + sock = socket(sap->sa_family, SOCK_DGRAM, IPPROTO_UDP);
> + if (sock < 0)
> + return 0;
> +
> + switch (sap->sa_family) {
> + case AF_INET:
> + if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
> + close(sock);
> + return 0;
> + }
> + break;
> + case AF_INET6:
> + if (bind(sock, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
> + close(sock);
> + return 0;
> + }
> + break;
> + default:
> + errno = EAFNOSUPPORT;
> + return 0;
> + }
> +
> + if (connect(sock, sap, salen) < 0) {
> + close(sock);
> + return 0;
> + }
> +
> + return !getsockname(sock, buf, buflen);
> +}
> +
> +/*
> + * Try to generate an address that prevents the server from calling us.
> + *
> + * Returns 1 and fills in @buf if successful; otherwise, zero.
> + */
> +static int nfs_ca_gai(const struct sockaddr *sap, const socklen_t salen,
> + struct sockaddr *buf, socklen_t *buflen)
> +{
> + struct addrinfo *gai_results;
> + struct addrinfo gai_hint = {
> + .ai_family = sap->sa_family,
> +#ifdef GENERATE_LOOPBACK_ADDRESS
> + .ai_flags = 0, /* loopback */
> +#else
> + .ai_flags = AI_PASSIVE, /* ANYADDR */
> +#endif
> + };
> +
> + if (getaddrinfo(NULL, "", &gai_hint, &gai_results))
> + return 0;
> +
> + *buflen = gai_results->ai_addrlen;
> + memcpy(buf, gai_results->ai_addr, *buflen);
> +
> + freeaddrinfo(gai_results);
> +
> + return 1;
> +}
> +
> +/**
> + * nfs_callback_address - acquire our local network address
> + * @sap: pointer to address of remote
> + * @sap_len: length of address
> + * @buf: pointer to buffer to be filled in with local network address
> + * @buflen: IN: length of buffer to fill in; OUT: length of filled-in address
> + *
> + * Discover a network address that an NFSv4 server can use to call us back.
> + * On multi-homed clients, this address depends on which NIC we use to
> + * route requests to the server.
> + *
> + * Returns 1 and fills in @buf if an unambiguous local address is
> + * available; returns 1 and fills in an appropriate ANYADDR address
> + * if a local address isn't available; otherwise, returns zero.
> + */
> +int nfs_callback_address(const struct sockaddr *sap, const socklen_t salen,
> + struct sockaddr *buf, socklen_t *buflen)
> +{
> + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)buf;
> +
> + if (nfs_ca_sockname(sap, salen, buf, buflen) == 0)
> + if (nfs_ca_gai(sap, salen, buf, buflen) == 0)
> + goto out_failed;
> +
> + /*
> + * The server can't use an interface ID that was generated
> + * here on the client, so always clear sin6_scope_id.
> + */
> + if (sin6->sin6_family == AF_INET6)
> + sin6->sin6_scope_id = 0;
> +
> + return 1;
> +
> +out_failed:
> + *buflen = 0;
> + if (verbose)
> + nfs_error(_("%s: failed to construct callback address"));
> + return 0;
> +
> +}
> diff --git a/utils/mount/network.h b/utils/mount/network.h
> index 8da7e20..2f4ff3a 100644
> --- a/utils/mount/network.h
> +++ b/utils/mount/network.h
> @@ -58,6 +58,8 @@ int nfs_string_to_sockaddr(const char *, const size_t,
> int nfs_present_sockaddr(const struct sockaddr *,
> const socklen_t, char *, const size_t);
> int get_client_address(struct sockaddr_in *, struct sockaddr_in *);
> +int nfs_callback_address(const struct sockaddr *, const socklen_t,
> + struct sockaddr *, socklen_t *);
> int nfs_call_umount(clnt_addr_t *, dirpath *);
> int clnt_ping(struct sockaddr_in *, const unsigned long,
> const unsigned long, const unsigned int,
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2008-07-10 19:30 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-10 0:37 [PATCH 00/14] Support for mounting NFSv4 servers over IPv6 Chuck Lever
[not found] ` <20080710001725.6137.83845.stgit-lQeC5l55kZ7wdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-07-10 0:37 ` [PATCH 01/14] nfs-utils: Introduce new ./configure option: "--enable-ipv6" Chuck Lever
2008-07-10 0:37 ` [PATCH 02/14] text-based mount command: Add headers needed for IPv6 support Chuck Lever
2008-07-10 0:37 ` [PATCH 03/14] mount command: Add functions to manage addresses in string form Chuck Lever
2008-07-10 0:37 ` [PATCH 04/14] text-based mount command: get_client_address support for IPv6 Chuck Lever
[not found] ` <20080710003723.6137.51761.stgit-lQeC5l55kZ7wdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-07-10 19:30 ` J. Bruce Fields [this message]
2008-07-10 19:36 ` Chuck Lever
2008-07-10 19:43 ` J. Bruce Fields
2008-07-10 20:35 ` Chuck Lever
[not found] ` <76bd70e30807101335y54f8b479v39953a772e08e88c-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2008-07-11 19:06 ` J. Bruce Fields
2008-07-11 19:16 ` Chuck Lever
2008-07-10 0:37 ` [PATCH 05/14] text-based mount command: Add helper to construct network addresses Chuck Lever
2008-07-10 0:37 ` [PATCH 06/14] text-based mount command: "addr=" option support for IPv6 addresses Chuck Lever
2008-07-10 0:37 ` [PATCH 07/14] text-based mount command: "clientaddr=" " Chuck Lever
2008-07-10 0:37 ` [PATCH 08/14] text-based mount command: "mounthost=" " Chuck Lever
2008-07-10 0:37 ` [PATCH 09/14] text-based mount command: Add IPv6 support to set_mandatory_options Chuck Lever
2008-07-10 0:37 ` [PATCH 10/14] text-based mount command: Support raw IPv6 address hostnames Chuck Lever
2008-07-10 0:38 ` [PATCH 11/14] text-based mount command: Remove unused IPv4-only functions Chuck Lever
2008-07-10 0:38 ` [PATCH 12/14] text-based mount options: rename functions in stropts.c Chuck Lever
2008-07-10 0:38 ` [PATCH 13/14] text-based mount command: remove unnecessary headers from stropts.c Chuck Lever
2008-07-10 0:38 ` [PATCH 14/14] mount command: Remove RPC headers from network.h Chuck Lever
-- strict thread matches above, loose matches on Subject: below --
2008-07-11 20:34 [PATCH 00/14] Support for mounting NFSv4 servers over IPv6 Chuck Lever
[not found] ` <20080711203322.478.52095.stgit-lQeC5l55kZ7wdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2008-07-11 20:34 ` [PATCH 04/14] text-based mount command: get_client_address support for IPv6 Chuck Lever
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080710193008.GA27734@fieldses.org \
--to=bfields@fieldses.org \
--cc=chuck.lever@oracle.com \
--cc=linux-nfs@vger.kernel.org \
--cc=steved@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.