af76049a94
- mount command: support AF_INET6 in probe_nfsport() and probe_mntport() - mount command: full support for AF_INET6 addresses in probe_port()
408 lines
15 KiB
Diff
408 lines
15 KiB
Diff
commit 71433fbcb0e3142e2b555727197f480d24761d7e
|
|
Author: Chuck Lever <chuck.lever@oracle.com>
|
|
Date: Thu Dec 11 10:27:34 2008 -0500
|
|
|
|
mount command: full support for AF_INET6 addresses in probe_port()
|
|
|
|
Now that probe_port() uses an AF_INET6-capable rpcbind query and RPC ping,
|
|
finish updating probe_port() to support AF_INET6 addresses fully.
|
|
|
|
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
|
|
|
commit 299a990de1b16ff769201fa0ed38249853254497
|
|
Author: Chuck Lever <chuck.lever@oracle.com>
|
|
Date: Thu Dec 11 10:28:57 2008 -0500
|
|
|
|
mount command: support AF_INET6 in probe_nfsport() and probe_mntport()
|
|
|
|
Flesh out support for AF_INET6 in the intermediate helper functions
|
|
probe_nfsport() and probe_mntport().
|
|
|
|
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
|
|
|
commit 8a5ef964599438ea45f849a0cd1431a0c26bf054
|
|
Author: Chuck Lever <chuck.lever@oracle.com>
|
|
Date: Thu Dec 11 10:30:20 2008 -0500
|
|
|
|
mount command: AF_INET6 support for probe_bothports()
|
|
|
|
Introduce an AF_INET6 capable probe_bothports() API. This means replacing
|
|
"struct sockaddr_in *" arguments with a "struct sockaddr *" and a socklen_t
|
|
arguments.
|
|
|
|
These functions often combine a "struct sockaddr_in" and a "struct pmap" into
|
|
a single "clnt_addr_t" argument. Instead of modifying "clnt_addr_t" and all
|
|
the legacy code that uses it, I'm going to create a new probe_bothports() API
|
|
for the text-based mount command that takes a "struct sockaddr *" and
|
|
sockaddr length, and leave the existing probe_bothports() interface, which
|
|
takes "clnt_addr_t" arguments, for legacy use.
|
|
|
|
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
|
Signed-off-by: Steve Dickson <steved@redhat.com>
|
|
|
|
diff --git a/utils/mount/network.c b/utils/mount/network.c
|
|
index 0c68993..e50bc28 100644
|
|
--- a/utils/mount/network.c
|
|
+++ b/utils/mount/network.c
|
|
@@ -160,6 +160,21 @@ static const unsigned long probe_mnt3_first[] = {
|
|
0,
|
|
};
|
|
|
|
+static void nfs_set_port(struct sockaddr *sap, const unsigned short port)
|
|
+{
|
|
+ switch (sap->sa_family) {
|
|
+ case AF_INET:
|
|
+ ((struct sockaddr_in *)sap)->sin_port = htons(port);
|
|
+ break;
|
|
+ case AF_INET6:
|
|
+ ((struct sockaddr_in6 *)sap)->sin6_port = htons(port);
|
|
+ break;
|
|
+ default:
|
|
+ nfs_error(_("%s: unrecognized address family in %s"),
|
|
+ progname, __func__);
|
|
+ }
|
|
+}
|
|
+
|
|
/**
|
|
* nfs_name_to_address - resolve hostname to an IPv4 or IPv6 socket address
|
|
* @hostname: pointer to C string containing DNS hostname to resolve
|
|
@@ -474,27 +489,38 @@ static void nfs_pp_debug(const struct sockaddr *sap, const socklen_t salen,
|
|
* Use the portmapper to discover whether or not the service we want is
|
|
* available. The lists 'versions' and 'protos' define ordered sequences
|
|
* of service versions and udp/tcp protocols to probe for.
|
|
+ *
|
|
+ * Returns 1 if the requested service port is unambiguous and pingable;
|
|
+ * @pmap is filled in with the version, port, and transport protocol used
|
|
+ * during the successful ping. Note that if a port is already specified
|
|
+ * in @pmap and it matches the rpcbind query result, nfs_probe_port() does
|
|
+ * not perform an RPC ping.
|
|
+ *
|
|
+ * If an error occurs or the requested service isn't available, zero is
|
|
+ * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
|
|
*/
|
|
-static int probe_port(clnt_addr_t *server, const unsigned long *versions,
|
|
- const unsigned int *protos)
|
|
+static int nfs_probe_port(const struct sockaddr *sap, const socklen_t salen,
|
|
+ struct pmap *pmap, const unsigned long *versions,
|
|
+ const unsigned int *protos)
|
|
{
|
|
- const struct sockaddr *saddr = (struct sockaddr *)&server->saddr;
|
|
- const socklen_t salen = sizeof(server->saddr);
|
|
- struct pmap *pmap = &server->pmap;
|
|
+ struct sockaddr_storage address;
|
|
+ struct sockaddr *saddr = (struct sockaddr *)&address;
|
|
const unsigned long prog = pmap->pm_prog, *p_vers;
|
|
const unsigned int prot = (u_int)pmap->pm_prot, *p_prot;
|
|
const u_short port = (u_short) pmap->pm_port;
|
|
unsigned long vers = pmap->pm_vers;
|
|
unsigned short p_port;
|
|
|
|
+ memcpy(saddr, sap, salen);
|
|
p_prot = prot ? &prot : protos;
|
|
p_vers = vers ? &vers : versions;
|
|
rpc_createerr.cf_stat = 0;
|
|
+
|
|
for (;;) {
|
|
p_port = nfs_getport(saddr, salen, prog, *p_vers, *p_prot);
|
|
if (p_port) {
|
|
if (!port || port == p_port) {
|
|
- server->saddr.sin_port = htons(p_port);
|
|
+ nfs_set_port(saddr, p_port);
|
|
nfs_pp_debug(saddr, salen, prog, *p_vers,
|
|
*p_prot, p_port);
|
|
if (nfs_rpc_ping(saddr, salen, prog,
|
|
@@ -537,28 +563,36 @@ out_ok:
|
|
|
|
static int probe_nfsport(clnt_addr_t *nfs_server)
|
|
{
|
|
+ struct sockaddr *sap = (struct sockaddr *)&nfs_server->saddr;
|
|
+ socklen_t salen = sizeof(nfs_server->saddr);
|
|
struct pmap *pmap = &nfs_server->pmap;
|
|
|
|
if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
|
|
return 1;
|
|
|
|
if (nfs_mount_data_version >= 4)
|
|
- return probe_port(nfs_server, probe_nfs3_first, probe_tcp_first);
|
|
+ return nfs_probe_port(sap, salen, pmap,
|
|
+ probe_nfs3_first, probe_tcp_first);
|
|
else
|
|
- return probe_port(nfs_server, probe_nfs2_only, probe_udp_only);
|
|
+ return nfs_probe_port(sap, salen, pmap,
|
|
+ probe_nfs2_only, probe_udp_only);
|
|
}
|
|
|
|
static int probe_mntport(clnt_addr_t *mnt_server)
|
|
{
|
|
+ struct sockaddr *sap = (struct sockaddr *)&mnt_server->saddr;
|
|
+ socklen_t salen = sizeof(mnt_server->saddr);
|
|
struct pmap *pmap = &mnt_server->pmap;
|
|
|
|
if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
|
|
return 1;
|
|
|
|
if (nfs_mount_data_version >= 4)
|
|
- return probe_port(mnt_server, probe_mnt3_first, probe_udp_first);
|
|
+ return nfs_probe_port(sap, salen, pmap,
|
|
+ probe_mnt3_first, probe_udp_first);
|
|
else
|
|
- return probe_port(mnt_server, probe_mnt1_first, probe_udp_only);
|
|
+ return nfs_probe_port(sap, salen, pmap,
|
|
+ probe_mnt1_first, probe_udp_only);
|
|
}
|
|
|
|
/**
|
|
diff --git a/utils/mount/network.c b/utils/mount/network.c
|
|
index e50bc28..55b2cab 100644
|
|
--- a/utils/mount/network.c
|
|
+++ b/utils/mount/network.c
|
|
@@ -561,12 +561,22 @@ out_ok:
|
|
return 1;
|
|
}
|
|
|
|
-static int probe_nfsport(clnt_addr_t *nfs_server)
|
|
+/*
|
|
+ * Probe a server's NFS service to determine which versions and
|
|
+ * transport protocols are supported.
|
|
+ *
|
|
+ * Returns 1 if the requested service port is unambiguous and pingable;
|
|
+ * @pmap is filled in with the version, port, and transport protocol used
|
|
+ * during the successful ping. If all three are already specified, simply
|
|
+ * return success without an rpcbind query or RPC ping (we may be trying
|
|
+ * to mount an NFS service that is not advertised via rpcbind).
|
|
+ *
|
|
+ * If an error occurs or the requested service isn't available, zero is
|
|
+ * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
|
|
+ */
|
|
+static int nfs_probe_nfsport(const struct sockaddr *sap, const socklen_t salen,
|
|
+ struct pmap *pmap)
|
|
{
|
|
- struct sockaddr *sap = (struct sockaddr *)&nfs_server->saddr;
|
|
- socklen_t salen = sizeof(nfs_server->saddr);
|
|
- struct pmap *pmap = &nfs_server->pmap;
|
|
-
|
|
if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
|
|
return 1;
|
|
|
|
@@ -578,12 +588,22 @@ static int probe_nfsport(clnt_addr_t *nfs_server)
|
|
probe_nfs2_only, probe_udp_only);
|
|
}
|
|
|
|
-static int probe_mntport(clnt_addr_t *mnt_server)
|
|
+/*
|
|
+ * Probe a server's mountd service to determine which versions and
|
|
+ * transport protocols are supported.
|
|
+ *
|
|
+ * Returns 1 if the requested service port is unambiguous and pingable;
|
|
+ * @pmap is filled in with the version, port, and transport protocol used
|
|
+ * during the successful ping. If all three are already specified, simply
|
|
+ * return success without an rpcbind query or RPC ping (we may be trying
|
|
+ * to mount an NFS service that is not advertised via rpcbind).
|
|
+ *
|
|
+ * If an error occurs or the requested service isn't available, zero is
|
|
+ * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
|
|
+ */
|
|
+static int nfs_probe_mntport(const struct sockaddr *sap, const socklen_t salen,
|
|
+ struct pmap *pmap)
|
|
{
|
|
- struct sockaddr *sap = (struct sockaddr *)&mnt_server->saddr;
|
|
- socklen_t salen = sizeof(mnt_server->saddr);
|
|
- struct pmap *pmap = &mnt_server->pmap;
|
|
-
|
|
if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
|
|
return 1;
|
|
|
|
@@ -607,10 +627,13 @@ static int probe_mntport(clnt_addr_t *mnt_server)
|
|
*/
|
|
int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
|
{
|
|
+ struct sockaddr *nfs_saddr = (struct sockaddr *)&nfs_server->saddr;
|
|
+ socklen_t nfs_salen = sizeof(nfs_server->saddr);
|
|
+ struct sockaddr *mnt_saddr = (struct sockaddr *)&mnt_server->saddr;
|
|
+ socklen_t mnt_salen = sizeof(mnt_server->saddr);
|
|
struct pmap *nfs_pmap = &nfs_server->pmap;
|
|
struct pmap *mnt_pmap = &mnt_server->pmap;
|
|
struct pmap save_nfs, save_mnt;
|
|
- int res;
|
|
const unsigned long *probe_vers;
|
|
|
|
if (mnt_pmap->pm_vers && !nfs_pmap->pm_vers)
|
|
@@ -627,9 +650,9 @@ int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
|
|
|
for (; *probe_vers; probe_vers++) {
|
|
nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
|
|
- if ((res = probe_nfsport(nfs_server) != 0)) {
|
|
+ if (nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap) != 0) {
|
|
mnt_pmap->pm_vers = *probe_vers;
|
|
- if ((res = probe_mntport(mnt_server)) != 0)
|
|
+ if (nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap) != 0)
|
|
return 1;
|
|
memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
|
|
}
|
|
@@ -647,9 +670,9 @@ out_bad:
|
|
return 0;
|
|
|
|
version_fixed:
|
|
- if (!probe_nfsport(nfs_server))
|
|
+ if (!nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap))
|
|
goto out_bad;
|
|
- return probe_mntport(mnt_server);
|
|
+ return nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap);
|
|
}
|
|
|
|
static int nfs_probe_statd(void)
|
|
@@ -716,11 +739,14 @@ int start_statd(void)
|
|
*/
|
|
int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
|
|
{
|
|
+ struct sockaddr *sap = (struct sockaddr *)&mnt_server->saddr;
|
|
+ socklen_t salen = sizeof(mnt_server->saddr);
|
|
+ struct pmap *pmap = &mnt_server->pmap;
|
|
CLIENT *clnt;
|
|
enum clnt_stat res = 0;
|
|
int msock;
|
|
|
|
- if (!probe_mntport(mnt_server))
|
|
+ if (!nfs_probe_mntport(sap, salen, pmap))
|
|
return 0;
|
|
clnt = mnt_openclnt(mnt_server, &msock);
|
|
if (!clnt)
|
|
diff --git a/utils/mount/network.c b/utils/mount/network.c
|
|
index 55b2cab..6a9a41a 100644
|
|
--- a/utils/mount/network.c
|
|
+++ b/utils/mount/network.c
|
|
@@ -615,24 +615,49 @@ static int nfs_probe_mntport(const struct sockaddr *sap, const socklen_t salen,
|
|
probe_mnt1_first, probe_udp_only);
|
|
}
|
|
|
|
-/**
|
|
- * probe_bothports - discover the RPC endpoints of mountd and NFS server
|
|
- * @mnt_server: pointer to address and pmap argument for mountd results
|
|
- * @nfs_server: pointer to address and pmap argument for NFS server
|
|
+/*
|
|
+ * Probe a server's mountd service to determine which versions and
|
|
+ * transport protocols are supported. Invoked when the protocol
|
|
+ * version is already known for both the NFS and mountd service.
|
|
*
|
|
- * Returns 1 if successful, otherwise zero if some error occurred.
|
|
- * Note that the arguments are both input and output arguments.
|
|
+ * Returns 1 and fills in both @pmap structs if the requested service
|
|
+ * ports are unambiguous and pingable. Otherwise zero is returned;
|
|
+ * rpccreateerr.cf_stat is set to reflect the nature of the error.
|
|
+ */
|
|
+static int nfs_probe_version_fixed(const struct sockaddr *mnt_saddr,
|
|
+ const socklen_t mnt_salen,
|
|
+ struct pmap *mnt_pmap,
|
|
+ const struct sockaddr *nfs_saddr,
|
|
+ const socklen_t nfs_salen,
|
|
+ struct pmap *nfs_pmap)
|
|
+{
|
|
+ if (!nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap))
|
|
+ return 0;
|
|
+ return nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * nfs_probe_bothports - discover the RPC endpoints of mountd and NFS server
|
|
+ * @mnt_saddr: pointer to socket address of mountd server
|
|
+ * @mnt_salen: length of mountd server's address
|
|
+ * @mnt_pmap: IN: partially filled-in mountd RPC service tuple;
|
|
+ * OUT: fully filled-in mountd RPC service tuple
|
|
+ * @nfs_saddr: pointer to socket address of NFS server
|
|
+ * @nfs_salen: length of NFS server's address
|
|
+ * @nfs_pmap: IN: partially filled-in NFS RPC service tuple;
|
|
+ * OUT: fully filled-in NFS RPC service tuple
|
|
*
|
|
- * A side effect of calling this function is that rpccreateerr is set.
|
|
+ * Returns 1 and fills in both @pmap structs if the requested service
|
|
+ * ports are unambiguous and pingable. Otherwise zero is returned;
|
|
+ * rpccreateerr.cf_stat is set to reflect the nature of the error.
|
|
*/
|
|
-int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
|
+int nfs_probe_bothports(const struct sockaddr *mnt_saddr,
|
|
+ const socklen_t mnt_salen,
|
|
+ struct pmap *mnt_pmap,
|
|
+ const struct sockaddr *nfs_saddr,
|
|
+ const socklen_t nfs_salen,
|
|
+ struct pmap *nfs_pmap)
|
|
{
|
|
- struct sockaddr *nfs_saddr = (struct sockaddr *)&nfs_server->saddr;
|
|
- socklen_t nfs_salen = sizeof(nfs_server->saddr);
|
|
- struct sockaddr *mnt_saddr = (struct sockaddr *)&mnt_server->saddr;
|
|
- socklen_t mnt_salen = sizeof(mnt_server->saddr);
|
|
- struct pmap *nfs_pmap = &nfs_server->pmap;
|
|
- struct pmap *mnt_pmap = &mnt_server->pmap;
|
|
struct pmap save_nfs, save_mnt;
|
|
const unsigned long *probe_vers;
|
|
|
|
@@ -640,8 +665,10 @@ int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
|
nfs_pmap->pm_vers = mntvers_to_nfs(mnt_pmap->pm_vers);
|
|
else if (nfs_pmap->pm_vers && !mnt_pmap->pm_vers)
|
|
mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
|
|
+
|
|
if (nfs_pmap->pm_vers)
|
|
- goto version_fixed;
|
|
+ return nfs_probe_version_fixed(mnt_saddr, mnt_salen, mnt_pmap,
|
|
+ nfs_saddr, nfs_salen, nfs_pmap);
|
|
|
|
memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
|
|
memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
|
|
@@ -661,18 +688,35 @@ int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
|
case RPC_PROGNOTREGISTERED:
|
|
break;
|
|
default:
|
|
- goto out_bad;
|
|
+ return 0;
|
|
}
|
|
memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
|
|
}
|
|
|
|
-out_bad:
|
|
return 0;
|
|
+}
|
|
|
|
-version_fixed:
|
|
- if (!nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap))
|
|
- goto out_bad;
|
|
- return nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap);
|
|
+/**
|
|
+ * probe_bothports - discover the RPC endpoints of mountd and NFS server
|
|
+ * @mnt_server: pointer to address and pmap argument for mountd results
|
|
+ * @nfs_server: pointer to address and pmap argument for NFS server
|
|
+ *
|
|
+ * This is the legacy API that takes "clnt_addr_t" for both servers,
|
|
+ * but supports only AF_INET addresses.
|
|
+ *
|
|
+ * Returns 1 and fills in the pmap field in both clnt_addr_t structs
|
|
+ * if the requested service ports are unambiguous and pingable.
|
|
+ * Otherwise zero is returned; rpccreateerr.cf_stat is set to reflect
|
|
+ * the nature of the error.
|
|
+ */
|
|
+int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
|
+{
|
|
+ return nfs_probe_bothports((struct sockaddr *)&mnt_server->saddr,
|
|
+ sizeof(mnt_server->saddr),
|
|
+ &mnt_server->pmap,
|
|
+ (struct sockaddr *)&nfs_server->saddr,
|
|
+ sizeof(nfs_server->saddr),
|
|
+ &nfs_server->pmap);
|
|
}
|
|
|
|
static int nfs_probe_statd(void)
|
|
diff --git a/utils/mount/network.h b/utils/mount/network.h
|
|
index a4dba1b..075093d 100644
|
|
--- a/utils/mount/network.h
|
|
+++ b/utils/mount/network.h
|
|
@@ -40,6 +40,9 @@ static const struct timeval TIMEOUT = { 20, 0 };
|
|
static const struct timeval RETRY_TIMEOUT = { 3, 0 };
|
|
|
|
int probe_bothports(clnt_addr_t *, clnt_addr_t *);
|
|
+int nfs_probe_bothports(const struct sockaddr *, const socklen_t,
|
|
+ struct pmap *, const struct sockaddr *,
|
|
+ const socklen_t, struct pmap *);
|
|
int nfs_gethostbyname(const char *, struct sockaddr_in *);
|
|
int nfs_name_to_address(const char *, const sa_family_t,
|
|
struct sockaddr *, socklen_t *);
|