walters / rpms / nfs-utils

Forked from rpms/nfs-utils 6 years ago
Clone
dcf425e
commit c062f45deebc20dae5eb8cdb50fb03fb1c252b47
dcf425e
Author: Chuck Lever <chuck.lever@oracle.com>
dcf425e
Date:   Sat Apr 18 09:45:46 2009 -0400
dcf425e
dcf425e
    umount.nfs: Fix return value of nfs_mount_protocol()
dcf425e
    
dcf425e
    Fix a copy-paste error introduced in nfs_mount_protocol().  It should
dcf425e
    return an IPPROTO_ number, not an NFS version number.
dcf425e
    
dcf425e
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
dcf425e
    Signed-off-by: Steve Dickson <steved@redhat.com>
dcf425e
dcf425e
commit 879a9b1b2bdd1160571896023d06291a611c4315
dcf425e
Author: Chuck Lever <chuck.lever@oracle.com>
dcf425e
Date:   Sat Apr 18 09:44:56 2009 -0400
dcf425e
dcf425e
    umount.nfs: Use a privileged port when sending UMNT	requests
dcf425e
    
dcf425e
    Turns out we do actually need to use a privileged port for UMNT.  The
dcf425e
    Linux rpc.mountd complains if an ephemeral source port is used:
dcf425e
    
dcf425e
      Apr 17 15:52:19 ingres mountd[2061]: refused unmount request from
dcf425e
        192.168.0.59 for /export (/export): illegal port 60932
dcf425e
    
dcf425e
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
dcf425e
    Signed-off-by: Steve Dickson <steved@redhat.com>
dcf425e
dcf425e
commit 8c94296bc84f3a204f2061c0391a1d2350e4f37e
dcf425e
Author: Chuck Lever <chuck.lever@oracle.com>
dcf425e
Date:   Sat Apr 18 09:43:58 2009 -0400
dcf425e
dcf425e
    support: Provide an API for creating a privileged RPC client
dcf425e
    
dcf425e
    We needed to guarantee that some RPC programs, such as PMAP, got an
dcf425e
    unprivileged port, to prevent exhausting the local privileged port
dcf425e
    space sending RPC requests that don't need such privileges.
dcf425e
    nfs_get_rpcclient() provides that feature.
dcf425e
    
dcf425e
    However, some RPC programs, such as MNT and UMNT, require a privileged
dcf425e
    port.  So, let's provide an additional API for this that also supports
dcf425e
    IPv6 and setting a destination port.
dcf425e
    
dcf425e
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
dcf425e
    Signed-off-by: Steve Dickson <steved@redhat.com>
dcf425e
dcf425e
commit 41eb279c2f46ca020bc3b8d17811555f74b99d2e
dcf425e
Author: Benny Halevy <bhalevy@panasas.com>
dcf425e
Date:   Wed Apr 15 14:16:08 2009 -0400
dcf425e
dcf425e
    utils/nfsd: fix -N optarg error printout
dcf425e
    
dcf425e
    as currently printed c is the version number, not a string char,
dcf425e
    therefore is should be printed as %d not %c.  That said, just print
dcf425e
    optarg as %s since it might be non-numeric.
dcf425e
    
dcf425e
    Signed-off-by: Benny Halevy <bhalevy@panasas.com>
dcf425e
    Signed-off-by: Steve Dickson <steved@redhat.com>
dcf425e
dcf425e
commit d4008af910ba1d527f00f8207fb3f8f5709e943d
dcf425e
Author: Chuck Lever <chuck.lever@oracle.com>
dcf425e
Date:   Wed Apr 15 12:52:48 2009 -0400
dcf425e
dcf425e
    getport.c: fix non-standard C
dcf425e
    
dcf425e
    Squelch a compiler warning in getport.c:
dcf425e
    
dcf425e
      getport.c:65: warning: ┬┐static┬┐ is not at beginning of declaration
dcf425e
    
dcf425e
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
dcf425e
    Signed-off-by: Steve Dickson <steved@redhat.com>
dcf425e
dcf425e
commit c51d826a201095fb3a7c68c3666e2b795a2b687d
dcf425e
Author: Chuck Lever <chuck.lever@oracle.com>
dcf425e
Date:   Wed Apr 15 12:38:40 2009 -0400
dcf425e
dcf425e
    nfs-utils: reverse order of librpcsecgss and libgssglue checks
dcf425e
    
dcf425e
    The check that validates the version of librpcsecgss also needs to
dcf425e
    have libgssglue installed.  Without libgssglue, ./configure complains
dcf425e
    that it can't find rpcsecgss, even though it's installed.
dcf425e
    
dcf425e
    It also turns out that the error message generated by pkg-config is
dcf425e
    more complete than the one we have in aclocal/rpcsec_vers.m4, so just
dcf425e
    let those PKG_CHECK_MODULES m4 macros use the default error message.
dcf425e
    
dcf425e
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
dcf425e
    Signed-off-by: Steve Dickson <steved@redhat.com>
dcf425e
---------------------------------------------------------------
dcf425e
diff --git a/aclocal/rpcsec_vers.m4 b/aclocal/rpcsec_vers.m4
dcf425e
index e59c0aa..25902ca 100644
dcf425e
--- a/aclocal/rpcsec_vers.m4
dcf425e
+++ b/aclocal/rpcsec_vers.m4
dcf425e
@@ -1,12 +1,11 @@
dcf425e
 dnl Checks librpcsec version
dcf425e
 AC_DEFUN([AC_RPCSEC_VERSION], [
dcf425e
 
dcf425e
-  dnl TI-RPC replaces librpcsecgss, but we still need libgssglue
dcf425e
+  PKG_CHECK_MODULES([GSSGLUE], [libgssglue >= 0.1])
dcf425e
+
dcf425e
+  dnl TI-RPC replaces librpcsecgss
dcf425e
   if test "$enable_tirpc" = no; then
dcf425e
-    PKG_CHECK_MODULES([RPCSECGSS], [librpcsecgss >= 0.16], ,
dcf425e
-                      [AC_MSG_ERROR([Unable to locate information required to use librpcsecgss.  If you have pkgconfig installed, you might try setting environment variable PKG_CONFIG_PATH to /usr/local/lib/pkgconfig])])
dcf425e
-  else
dcf425e
-    PKG_CHECK_MODULES([GSSGLUE], [libgssglue >= 0.1])
dcf425e
+    PKG_CHECK_MODULES([RPCSECGSS], [librpcsecgss >= 0.16])
dcf425e
   fi
dcf425e
 
dcf425e
 ])dnl
dcf425e
diff --git a/support/include/nfsrpc.h b/support/include/nfsrpc.h
dcf425e
index 097debb..543c35b 100644
dcf425e
--- a/support/include/nfsrpc.h
dcf425e
+++ b/support/include/nfsrpc.h
dcf425e
@@ -24,6 +24,7 @@
dcf425e
 #define __NFS_UTILS_NFSRPC_H
dcf425e
 
dcf425e
 #include <rpc/types.h>
dcf425e
+#include <rpc/clnt.h>
dcf425e
 
dcf425e
 /*
dcf425e
  * Conventional RPC program numbers
dcf425e
@@ -54,7 +55,7 @@
dcf425e
 extern rpcprog_t	nfs_getrpcbyname(const rpcprog_t, const char *table[]);
dcf425e
 
dcf425e
 /*
dcf425e
- * Acquire an RPC CLIENT *
dcf425e
+ * Acquire an RPC CLIENT * with an ephemeral source port
dcf425e
  */
dcf425e
 extern CLIENT		*nfs_get_rpcclient(const struct sockaddr *,
dcf425e
 				const socklen_t, const unsigned short,
dcf425e
@@ -62,6 +63,14 @@ extern CLIENT		*nfs_get_rpcclient(const struct sockaddr *,
dcf425e
 				struct timeval *);
dcf425e
 
dcf425e
 /*
dcf425e
+ * Acquire an RPC CLIENT * with a privileged source port
dcf425e
+ */
dcf425e
+extern CLIENT		*nfs_get_priv_rpcclient( const struct sockaddr *,
dcf425e
+				const socklen_t, const unsigned short,
dcf425e
+				const rpcprog_t, const rpcvers_t,
dcf425e
+				struct timeval *);
dcf425e
+
dcf425e
+/*
dcf425e
  * Convert a socket address to a universal address
dcf425e
  */
dcf425e
 extern char		*nfs_sockaddr2universal(const struct sockaddr *,
dcf425e
diff --git a/support/nfs/getport.c b/support/nfs/getport.c
dcf425e
index 734d21a..cf1677e 100644
dcf425e
--- a/support/nfs/getport.c
dcf425e
+++ b/support/nfs/getport.c
dcf425e
@@ -60,9 +60,9 @@
dcf425e
 #endif	/* !HAVE_LIBTIRPC */
dcf425e
 
dcf425e
 #ifdef HAVE_LIBTIRPC
dcf425e
-const static rpcvers_t default_rpcb_version = RPCBVERS_4;
dcf425e
+static const rpcvers_t default_rpcb_version = RPCBVERS_4;
dcf425e
 #else	/* !HAVE_LIBTIRPC */
dcf425e
-const static rpcvers_t default_rpcb_version = PMAPVERS;
dcf425e
+static const rpcvers_t default_rpcb_version = PMAPVERS;
dcf425e
 #endif	/* !HAVE_LIBTIRPC */
dcf425e
 
dcf425e
 #ifdef HAVE_DECL_AI_ADDRCONFIG
dcf425e
diff --git a/support/nfs/rpc_socket.c b/support/nfs/rpc_socket.c
dcf425e
index 2b11e35..85e6064 100644
dcf425e
--- a/support/nfs/rpc_socket.c
dcf425e
+++ b/support/nfs/rpc_socket.c
dcf425e
@@ -132,6 +132,58 @@ static int nfs_bind(const int sock, const sa_family_t family)
dcf425e
 	return -1;
dcf425e
 }
dcf425e
 
dcf425e
+#ifdef IPV6_SUPPORT
dcf425e
+
dcf425e
+/*
dcf425e
+ * Bind a socket using an unused privileged source port.
dcf425e
+ *
dcf425e
+ * Returns zero on success, or returns -1 on error.  errno is
dcf425e
+ * set to reflect the nature of the error.
dcf425e
+ */
dcf425e
+static int nfs_bindresvport(const int sock, const sa_family_t family)
dcf425e
+{
dcf425e
+	struct sockaddr_in sin = {
dcf425e
+		.sin_family		= AF_INET,
dcf425e
+		.sin_addr.s_addr	= htonl(INADDR_ANY),
dcf425e
+	};
dcf425e
+	struct sockaddr_in6 sin6 = {
dcf425e
+		.sin6_family		= AF_INET6,
dcf425e
+		.sin6_addr		= IN6ADDR_ANY_INIT,
dcf425e
+	};
dcf425e
+
dcf425e
+	switch (family) {
dcf425e
+	case AF_INET:
dcf425e
+		return bindresvport_sa(sock, (struct sockaddr *)&sin,
dcf425e
+					(socklen_t)sizeof(sin));
dcf425e
+	case AF_INET6:
dcf425e
+		return bindresvport_sa(sock, (struct sockaddr *)&sin6,
dcf425e
+					(socklen_t)sizeof(sin6));
dcf425e
+	}
dcf425e
+
dcf425e
+	errno = EAFNOSUPPORT;
dcf425e
+	return -1;
dcf425e
+}
dcf425e
+
dcf425e
+#else	/* !IPV6_SUPPORT */
dcf425e
+
dcf425e
+/*
dcf425e
+ * Bind a socket using an unused privileged source port.
dcf425e
+ *
dcf425e
+ * Returns zero on success, or returns -1 on error.  errno is
dcf425e
+ * set to reflect the nature of the error.
dcf425e
+ */
dcf425e
+static int nfs_bindresvport(const int sock, const sa_family_t family)
dcf425e
+{
dcf425e
+	if (family != AF_INET) {
dcf425e
+		errno = EAFNOSUPPORT;
dcf425e
+		return -1;
dcf425e
+	}
dcf425e
+
dcf425e
+	return bindresvport(sock, NULL);
dcf425e
+}
dcf425e
+
dcf425e
+#endif	/* !IPV6_SUPPORT */
dcf425e
+
dcf425e
 /*
dcf425e
  * Perform a non-blocking connect on the socket fd.
dcf425e
  *
dcf425e
@@ -218,7 +270,8 @@ static CLIENT *nfs_get_udpclient(const struct sockaddr *sap,
dcf425e
 				 const socklen_t salen,
dcf425e
 				 const rpcprog_t program,
dcf425e
 				 const rpcvers_t version,
dcf425e
-				 struct timeval *timeout)
dcf425e
+				 struct timeval *timeout,
dcf425e
+				 const int resvport)
dcf425e
 {
dcf425e
 	CLIENT *client;
dcf425e
 	int ret, sock;
dcf425e
@@ -245,7 +298,10 @@ static CLIENT *nfs_get_udpclient(const struct sockaddr *sap,
dcf425e
 		return NULL;
dcf425e
 	}
dcf425e
 
dcf425e
-	ret = nfs_bind(sock, sap->sa_family);
dcf425e
+	if (resvport)
dcf425e
+		ret = nfs_bindresvport(sock, sap->sa_family);
dcf425e
+	else
dcf425e
+		ret = nfs_bind(sock, sap->sa_family);
dcf425e
 	if (ret < 0) {
dcf425e
 		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
dcf425e
 		rpc_createerr.cf_error.re_errno = errno;
dcf425e
@@ -294,7 +350,8 @@ static CLIENT *nfs_get_tcpclient(const struct sockaddr *sap,
dcf425e
 				 const socklen_t salen,
dcf425e
 				 const rpcprog_t program,
dcf425e
 				 const rpcvers_t version,
dcf425e
-				 struct timeval *timeout)
dcf425e
+				 struct timeval *timeout,
dcf425e
+				 const int resvport)
dcf425e
 {
dcf425e
 	CLIENT *client;
dcf425e
 	int ret, sock;
dcf425e
@@ -321,7 +378,10 @@ static CLIENT *nfs_get_tcpclient(const struct sockaddr *sap,
dcf425e
 		return NULL;
dcf425e
 	}
dcf425e
 
dcf425e
-	ret = nfs_bind(sock, sap->sa_family);
dcf425e
+	if (resvport)
dcf425e
+		ret = nfs_bindresvport(sock, sap->sa_family);
dcf425e
+	else
dcf425e
+		ret = nfs_bind(sock, sap->sa_family);
dcf425e
 	if (ret < 0) {
dcf425e
 		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
dcf425e
 		rpc_createerr.cf_error.re_errno = errno;
dcf425e
@@ -365,7 +425,8 @@ static CLIENT *nfs_get_tcpclient(const struct sockaddr *sap,
dcf425e
  * @timeout: pointer to request timeout (must not be NULL)
dcf425e
  *
dcf425e
  * Set up an RPC client for communicating with an RPC program @program
dcf425e
- * and @version on the server @sap over @transport.
dcf425e
+ * and @version on the server @sap over @transport.  An unprivileged
dcf425e
+ * source port is used.
dcf425e
  *
dcf425e
  * Returns a pointer to a prepared RPC client if successful, and
dcf425e
  * @timeout is initialized; caller must destroy a non-NULL returned RPC
dcf425e
@@ -405,10 +466,75 @@ CLIENT *nfs_get_rpcclient(const struct sockaddr *sap,
dcf425e
 
dcf425e
 	switch (transport) {
dcf425e
 	case IPPROTO_TCP:
dcf425e
-		return nfs_get_tcpclient(sap, salen, program, version, timeout);
dcf425e
+		return nfs_get_tcpclient(sap, salen, program, version,
dcf425e
+						timeout, 0);
dcf425e
+	case 0:
dcf425e
+	case IPPROTO_UDP:
dcf425e
+		return nfs_get_udpclient(sap, salen, program, version,
dcf425e
+						timeout, 0);
dcf425e
+	}
dcf425e
+
dcf425e
+	rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
dcf425e
+	return NULL;
dcf425e
+}
dcf425e
+
dcf425e
+/**
dcf425e
+ * nfs_get_priv_rpcclient - acquire an RPC client
dcf425e
+ * @sap: pointer to socket address of RPC server
dcf425e
+ * @salen: length of socket address
dcf425e
+ * @transport: IPPROTO_ value of transport protocol to use
dcf425e
+ * @program: RPC program number
dcf425e
+ * @version: RPC version number
dcf425e
+ * @timeout: pointer to request timeout (must not be NULL)
dcf425e
+ *
dcf425e
+ * Set up an RPC client for communicating with an RPC program @program
dcf425e
+ * and @version on the server @sap over @transport.  A privileged
dcf425e
+ * source port is used.
dcf425e
+ *
dcf425e
+ * Returns a pointer to a prepared RPC client if successful, and
dcf425e
+ * @timeout is initialized; caller must destroy a non-NULL returned RPC
dcf425e
+ * client.  Otherwise returns NULL, and rpc_createerr.cf_stat is set to
dcf425e
+ * reflect the error.
dcf425e
+ */
dcf425e
+CLIENT *nfs_get_priv_rpcclient(const struct sockaddr *sap,
dcf425e
+			       const socklen_t salen,
dcf425e
+			       const unsigned short transport,
dcf425e
+			       const rpcprog_t program,
dcf425e
+			       const rpcvers_t version,
dcf425e
+			       struct timeval *timeout)
dcf425e
+{
dcf425e
+	struct sockaddr_in *sin = (struct sockaddr_in *)sap;
dcf425e
+	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
dcf425e
+
dcf425e
+	switch (sap->sa_family) {
dcf425e
+	case AF_LOCAL:
dcf425e
+		return nfs_get_localclient(sap, salen, program,
dcf425e
+						version, timeout);
dcf425e
+	case AF_INET:
dcf425e
+		if (sin->sin_port == 0) {
dcf425e
+			rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
dcf425e
+			return NULL;
dcf425e
+		}
dcf425e
+		break;
dcf425e
+	case AF_INET6:
dcf425e
+		if (sin6->sin6_port == 0) {
dcf425e
+			rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
dcf425e
+			return NULL;
dcf425e
+		}
dcf425e
+		break;
dcf425e
+	default:
dcf425e
+		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
dcf425e
+		return NULL;
dcf425e
+	}
dcf425e
+
dcf425e
+	switch (transport) {
dcf425e
+	case IPPROTO_TCP:
dcf425e
+		return nfs_get_tcpclient(sap, salen, program, version,
dcf425e
+						timeout, 1);
dcf425e
 	case 0:
dcf425e
 	case IPPROTO_UDP:
dcf425e
-		return nfs_get_udpclient(sap, salen, program, version, timeout);
dcf425e
+		return nfs_get_udpclient(sap, salen, program, version,
dcf425e
+						timeout, 1);
dcf425e
 	}
dcf425e
 
dcf425e
 	rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
dcf425e
diff --git a/utils/mount/network.c b/utils/mount/network.c
dcf425e
index bcd0c0f..72f4b84 100644
dcf425e
--- a/utils/mount/network.c
dcf425e
+++ b/utils/mount/network.c
dcf425e
@@ -869,7 +869,7 @@ int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen,
dcf425e
 	memcpy(saddr, sap, salen);
dcf425e
 	nfs_set_port(saddr, mnt_pmap.pm_port);
dcf425e
 
dcf425e
-	client = nfs_get_rpcclient(saddr, salen, mnt_pmap.pm_prot,
dcf425e
+	client = nfs_get_priv_rpcclient(saddr, salen, mnt_pmap.pm_prot,
dcf425e
 					mnt_pmap.pm_prog, mnt_pmap.pm_vers,
dcf425e
 					&timeout);
dcf425e
 	if (client == NULL)
dcf425e
@@ -1337,7 +1337,7 @@ static unsigned short nfs_mount_protocol(struct mount_options *options)
dcf425e
 			return IPPROTO_UDP;
dcf425e
 	}
dcf425e
 
dcf425e
-	return nfs_nfs_version(options);
dcf425e
+	return nfs_nfs_protocol(options);
dcf425e
 }
dcf425e
 
dcf425e
 /*
dcf425e
diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c
dcf425e
index aaf8d29..c97c81f 100644
dcf425e
--- a/utils/nfsd/nfsd.c
dcf425e
+++ b/utils/nfsd/nfsd.c
dcf425e
@@ -86,7 +86,7 @@ main(int argc, char **argv)
dcf425e
 				NFSCTL_VERUNSET(versbits, c);
dcf425e
 				break;
dcf425e
 			default:
dcf425e
-				fprintf(stderr, "%c: Unsupported version\n", c);
dcf425e
+				fprintf(stderr, "%s: Unsupported version\n", optarg);
dcf425e
 				exit(1);
dcf425e
 			}
dcf425e
 			break;