All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/6] nfs-utils:  Support binding to source address.
@ 2011-06-10 21:08 greearb
  2011-06-10 21:08 ` [PATCH v3 1/6] nfs-utils: Add structure for passing local binding info greearb
                   ` (5 more replies)
  0 siblings, 6 replies; 15+ messages in thread
From: greearb @ 2011-06-10 21:08 UTC (permalink / raw)
  To: linux-nfs; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

This lets one specify the source IP address for
sockets, allowing users to leverage routing rules
on multi-homed systems.

Kernel patches to RPC and NFS are needed to complete
full functionality.

v5:  Fix compile error with ipv6 enabled.  One minor
       change to patch 1.

v4:  Remove get_socket() modifications: stropt mount doesn't use them.
       (This removed old patch 4, and modified patch 1)
     Remove open-parsing of srcaddr= in mount logic.  Move parsing
       to nfs_validate_options()

Ben Greear (6):
  nfs-utils:  Add structure for passing local binding info.
  nfs-utils:  Add patch to parse srcaddr= option.
  nfs-utils:  Implement srcaddr binding in rpc_socket
  nfs-utils:  Support srcaddr=n option for string mount.
  nfs-utils:  Implement srcaddr=n binding for unmount.
  nfs-utils:  Update man page for srcaddr= option.

 support/include/nfsrpc.h   |   23 ++++++---
 support/include/sockaddr.h |    6 ++
 support/nfs/getport.c      |   39 ++++++++++------
 support/nfs/rpc_socket.c   |   96 +++++++++++++++++++++++++++-----------
 utils/gssd/gssd.h          |    2 +
 utils/gssd/gssd_proc.c     |   33 ++++++++------
 utils/mount/network.c      |  111 ++++++++++++++++++++++++++++++++++----------
 utils/mount/network.h      |   16 ++++--
 utils/mount/nfs.man        |    7 +++
 utils/mount/nfsmount.c     |    2 +-
 utils/mount/nfsumount.c    |   26 +++++++++-
 utils/mount/stropts.c      |   29 ++++++++++--
 utils/mount/utils.c        |    6 ++-
 utils/mount/utils.h        |    4 +-
 14 files changed, 296 insertions(+), 104 deletions(-)

-- 
1.7.3.4


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v3 1/6] nfs-utils:  Add structure for passing local binding info.
  2011-06-10 21:08 [PATCH v3 0/6] nfs-utils: Support binding to source address greearb
@ 2011-06-10 21:08 ` greearb
  2011-06-10 21:08 ` [PATCH v3 2/6] nfs-utils: Add patch to parse srcaddr= option greearb
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: greearb @ 2011-06-10 21:08 UTC (permalink / raw)
  To: linux-nfs; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

Create a struct local_bind_info that will hold an IP
address to be used for binding to a local IP address.
Pass this down to the code that needs it.

There are no functional changes in this patch, just passing
around un-used variables which are always NULL.  Future
patches will use this.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 d50fe94... d8ef257... M	support/include/nfsrpc.h
:100644 100644 9af2543... b1089ce... M	support/include/sockaddr.h
:100644 100644 d74400b... 924ea80... M	support/nfs/getport.c
:100644 100644 c14efe8... 5652f6c... M	support/nfs/rpc_socket.c
:100644 100644 b1b5793... ccd44a2... M	utils/gssd/gssd.h
:100644 100644 41328c9... e584d20... M	utils/gssd/gssd_proc.c
:100644 100644 d1f91dc... 5ba6967... M	utils/mount/network.c
:100644 100644 81c6f22... a832e76... M	utils/mount/network.h
:100644 100644 1298fe4... 960cbaa... M	utils/mount/nfsmount.c
:100644 100644 f1aa503... 71417df... M	utils/mount/stropts.c
:100644 100644 298db39... eb50074... M	utils/mount/utils.c
 support/include/nfsrpc.h   |   23 ++++++++++----
 support/include/sockaddr.h |    6 ++++
 support/nfs/getport.c      |   39 ++++++++++++++++---------
 support/nfs/rpc_socket.c   |   37 ++++++++++++++----------
 utils/gssd/gssd.h          |    2 +
 utils/gssd/gssd_proc.c     |   33 ++++++++++++---------
 utils/mount/network.c      |   66 +++++++++++++++++++++++++++----------------
 utils/mount/network.h      |   14 ++++++---
 utils/mount/nfsmount.c     |    2 +-
 utils/mount/stropts.c      |    2 +-
 utils/mount/utils.c        |    2 +-
 11 files changed, 143 insertions(+), 83 deletions(-)

diff --git a/support/include/nfsrpc.h b/support/include/nfsrpc.h
index d50fe94..d8ef257 100644
--- a/support/include/nfsrpc.h
+++ b/support/include/nfsrpc.h
@@ -55,6 +55,8 @@
 #define NSMPROG		((rpcprog_t)100024)
 #endif
 
+struct local_bind_info;
+
 /**
  * nfs_clear_rpc_createerr - zap all error reporting fields
  *
@@ -75,7 +77,8 @@ extern rpcprog_t	nfs_getrpcbyname(const rpcprog_t, const char *table[]);
 extern CLIENT		*nfs_get_rpcclient(const struct sockaddr *,
 				const socklen_t, const unsigned short,
 				const rpcprog_t, const rpcvers_t,
-				struct timeval *);
+				struct timeval *,
+				struct local_bind_info *);
 
 /*
  * Acquire an RPC CLIENT * with a privileged source port
@@ -83,7 +86,8 @@ extern CLIENT		*nfs_get_rpcclient(const struct sockaddr *,
 extern CLIENT		*nfs_get_priv_rpcclient( const struct sockaddr *,
 				const socklen_t, const unsigned short,
 				const rpcprog_t, const rpcvers_t,
-				struct timeval *);
+				struct timeval *,
+				struct local_bind_info *);
 
 /*
  * Convert a netid to a protocol number and protocol family
@@ -116,7 +120,8 @@ extern int		nfs_getport_ping(struct sockaddr *sap,
 				const socklen_t salen,
 				const rpcprog_t program,
 				const rpcvers_t version,
-				const unsigned short protocol);
+				const unsigned short protocol,
+				struct local_bind_info *local_ip);
 
 /*
  * Generic function that maps an RPC service tuple to an IP port
@@ -124,14 +129,16 @@ extern int		nfs_getport_ping(struct sockaddr *sap,
  */
 extern unsigned short	nfs_getport(const struct sockaddr *,
 				const socklen_t, const rpcprog_t,
-				const rpcvers_t, const unsigned short);
+				const rpcvers_t, const unsigned short,
+				struct local_bind_info *local_ip);
 
 /*
  * Generic function that maps an RPC service tuple to an IP port
  * number of the service on the local host
  */
 extern unsigned short	nfs_getlocalport(const rpcprot_t,
-				const rpcvers_t, const unsigned short);
+				const rpcvers_t, const unsigned short,
+				struct local_bind_info *local_ip);
 
 /*
  * Function to invoke an rpcbind v3/v4 GETADDR request
@@ -153,7 +160,8 @@ extern unsigned long	nfs_pmap_getport(const struct sockaddr_in *,
 				const unsigned long,
 				const unsigned long,
 				const unsigned long,
-				const struct timeval *);
+				const struct timeval *,
+				struct local_bind_info *local_ip);
 
 /*
  * Contact a remote RPC service to discover whether it is responding
@@ -164,7 +172,8 @@ extern int		nfs_rpc_ping(const struct sockaddr *sap,
 				const rpcprog_t program,
 				const rpcvers_t version,
 				const unsigned short protocol,
-				const struct timeval *timeout);
+				const struct timeval *timeout,
+				struct local_bind_info *local_ip);
 
 /* create AUTH_SYS handle with no supplemental groups */
 extern AUTH *			 nfs_authsys_create(void);
diff --git a/support/include/sockaddr.h b/support/include/sockaddr.h
index 9af2543..b1089ce 100644
--- a/support/include/sockaddr.h
+++ b/support/include/sockaddr.h
@@ -46,6 +46,12 @@ union nfs_sockaddr {
 	struct sockaddr_in6	s6;
 };
 
+struct local_bind_info {
+	union nfs_sockaddr addr;
+	socklen_t addrlen;
+	bool is_set;
+};
+
 #if SIZEOF_SOCKLEN_T - 0 == 0
 #define socklen_t unsigned int
 #endif
diff --git a/support/nfs/getport.c b/support/nfs/getport.c
index d74400b..924ea80 100644
--- a/support/nfs/getport.c
+++ b/support/nfs/getport.c
@@ -181,7 +181,8 @@ static CLIENT *nfs_gp_get_rpcbclient(struct sockaddr *sap,
 				     const socklen_t salen,
 				     const unsigned short transport,
 				     const rpcvers_t version,
-				     struct timeval *timeout)
+				     struct timeval *timeout,
+				     struct local_bind_info *local_ip)
 {
 	static const char *rpcb_pgmtbl[] = {
 		"rpcbind",
@@ -195,7 +196,7 @@ static CLIENT *nfs_gp_get_rpcbclient(struct sockaddr *sap,
 
 	nfs_set_port(sap, ntohs(nfs_gp_get_rpcb_port(transport)));
 	clnt = nfs_get_rpcclient(sap, salen, transport, rpcb_prog,
-							version, timeout);
+				 version, timeout, local_ip);
 	nfs_gp_map_tcp_errorcodes(transport);
 	return clnt;
 }
@@ -729,7 +730,8 @@ static unsigned short nfs_gp_getport(CLIENT *client,
  */
 int nfs_rpc_ping(const struct sockaddr *sap, const socklen_t salen,
 		 const rpcprog_t program, const rpcvers_t version,
-		 const unsigned short protocol, const struct timeval *timeout)
+		 const unsigned short protocol, const struct timeval *timeout,
+		 struct local_bind_info *local_ip)
 {
 	union nfs_sockaddr address;
 	struct sockaddr *saddr = &address.sa;
@@ -744,7 +746,7 @@ int nfs_rpc_ping(const struct sockaddr *sap, const socklen_t salen,
 
 	memcpy(saddr, sap, (size_t)salen);
 	client = nfs_get_rpcclient(saddr, salen, protocol,
-						program, version, &tout);
+				   program, version, &tout, local_ip);
 	if (client != NULL) {
 		result = nfs_gp_ping(client, tout);
 		nfs_gp_map_tcp_errorcodes(protocol);
@@ -798,7 +800,8 @@ unsigned short nfs_getport(const struct sockaddr *sap,
 			   const socklen_t salen,
 			   const rpcprog_t program,
 			   const rpcvers_t version,
-			   const unsigned short protocol)
+			   const unsigned short protocol,
+			   struct local_bind_info *local_ip)
 {
 	union nfs_sockaddr address;
 	struct sockaddr *saddr = &address.sa;
@@ -810,7 +813,8 @@ unsigned short nfs_getport(const struct sockaddr *sap,
 
 	memcpy(saddr, sap, (size_t)salen);
 	client = nfs_gp_get_rpcbclient(saddr, salen, protocol,
-						default_rpcb_version, &timeout);
+				       default_rpcb_version, &timeout,
+				       local_ip);
 	if (client != NULL) {
 		port = nfs_gp_getport(client, saddr, program,
 					version, protocol, timeout);
@@ -840,7 +844,8 @@ unsigned short nfs_getport(const struct sockaddr *sap,
  */
 int nfs_getport_ping(struct sockaddr *sap, const socklen_t salen,
 		     const rpcprog_t program, const rpcvers_t version,
-		     const unsigned short protocol)
+		     const unsigned short protocol,
+		     struct local_bind_info *local_ip)
 {
 	struct timeval timeout = { -1, 0 };
 	unsigned short port = 0;
@@ -850,7 +855,8 @@ int nfs_getport_ping(struct sockaddr *sap, const socklen_t salen,
 	nfs_clear_rpc_createerr();
 
 	client = nfs_gp_get_rpcbclient(sap, salen, protocol,
-						default_rpcb_version, &timeout);
+				       default_rpcb_version, &timeout,
+				       local_ip);
 	if (client != NULL) {
 		port = nfs_gp_getport(client, sap, program,
 					version, protocol, timeout);
@@ -868,7 +874,8 @@ int nfs_getport_ping(struct sockaddr *sap, const socklen_t salen,
 		nfs_clear_rpc_createerr();
 
 		client = nfs_get_rpcclient(saddr, salen, protocol,
-						program, version, &timeout);
+					   program, version, &timeout,
+					   local_ip);
 		if (client != NULL) {
 			result = nfs_gp_ping(client, timeout);
 			nfs_gp_map_tcp_errorcodes(protocol);
@@ -909,7 +916,8 @@ int nfs_getport_ping(struct sockaddr *sap, const socklen_t salen,
  */
 unsigned short nfs_getlocalport(const rpcprot_t program,
 				const rpcvers_t version,
-				const unsigned short protocol)
+				const unsigned short protocol,
+				struct local_bind_info *local_ip)
 {
 	union nfs_sockaddr address;
 	struct sockaddr *lb_addr = &address.sa;
@@ -946,7 +954,8 @@ unsigned short nfs_getlocalport(const rpcprot_t program,
 
 		if (nfs_gp_loopback_address(lb_addr, &lb_len)) {
 			port = nfs_getport(lb_addr, lb_len,
-						program, version, protocol);
+					   program, version, protocol,
+					   local_ip);
 		} else
 			rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
 	}
@@ -1009,7 +1018,7 @@ unsigned short nfs_rpcb_getaddr(const struct sockaddr *sap,
 
 	memcpy(saddr, sap, (size_t)salen);
 	client = nfs_gp_get_rpcbclient(saddr, salen, transport,
-							RPCBVERS_4, &tout);
+				       RPCBVERS_4, &tout, NULL);
 	if (client != NULL) {
 		if (nfs_gp_init_rpcb_parms(addr, program, version,
 						protocol, &parms) != 0) {
@@ -1074,7 +1083,8 @@ unsigned long nfs_pmap_getport(const struct sockaddr_in *sin,
 			       const unsigned long program,
 			       const unsigned long version,
 			       const unsigned long protocol,
-			       const struct timeval *timeout)
+			       const struct timeval *timeout,
+			       struct local_bind_info *local_ip)
 {
 	struct sockaddr_in address;
 	struct sockaddr *saddr = (struct sockaddr *)&address;
@@ -1094,7 +1104,8 @@ unsigned long nfs_pmap_getport(const struct sockaddr_in *sin,
 
 	memcpy(saddr, sin, sizeof(address));
 	client = nfs_gp_get_rpcbclient(saddr, (socklen_t)sizeof(*sin),
-					transport, PMAPVERS, &tout);
+				       transport, PMAPVERS, &tout,
+				       local_ip);
 	if (client != NULL) {
 		port = nfs_gp_pmap_getport(client, &parms, tout);
 		CLNT_DESTROY(client);
diff --git a/support/nfs/rpc_socket.c b/support/nfs/rpc_socket.c
index c14efe8..5652f6c 100644
--- a/support/nfs/rpc_socket.c
+++ b/support/nfs/rpc_socket.c
@@ -112,7 +112,8 @@ static CLIENT *nfs_get_localclient(const struct sockaddr *sap,
  * Returns zero on success, or returns -1 on error.  errno is
  * set to reflect the nature of the error.
  */
-static int nfs_bind(const int sock, const sa_family_t family)
+static int nfs_bind(const int sock, const sa_family_t family,
+		    struct local_bind_info *local_ip)
 {
 	struct sockaddr_in sin = {
 		.sin_family		= AF_INET,
@@ -144,7 +145,8 @@ static int nfs_bind(const int sock, const sa_family_t family)
  * Returns zero on success, or returns -1 on error.  errno is
  * set to reflect the nature of the error.
  */
-static int nfs_bindresvport(const int sock, const sa_family_t family)
+static int nfs_bindresvport(const int sock, const sa_family_t family,
+			    struct local_bind_info *local_ip)
 {
 	struct sockaddr_in sin = {
 		.sin_family		= AF_INET,
@@ -174,7 +176,8 @@ static int nfs_bindresvport(const int sock, const sa_family_t family)
  * Returns zero on success, or returns -1 on error.  errno is
  * set to reflect the nature of the error.
  */
-static int nfs_bindresvport(const int sock, const sa_family_t family)
+static int nfs_bindresvport(const int sock, const sa_family_t family,
+			    struct local_bind_info *local_ip)
 {
 	if (family != AF_INET) {
 		errno = EAFNOSUPPORT;
@@ -273,7 +276,8 @@ static CLIENT *nfs_get_udpclient(const struct sockaddr *sap,
 				 const rpcprog_t program,
 				 const rpcvers_t version,
 				 struct timeval *timeout,
-				 const int resvport)
+				 const int resvport,
+				 struct local_bind_info *local_ip)
 {
 	CLIENT *client;
 	int ret, sock;
@@ -301,9 +305,9 @@ static CLIENT *nfs_get_udpclient(const struct sockaddr *sap,
 	}
 
 	if (resvport)
-		ret = nfs_bindresvport(sock, sap->sa_family);
+		ret = nfs_bindresvport(sock, sap->sa_family, local_ip);
 	else
-		ret = nfs_bind(sock, sap->sa_family);
+		ret = nfs_bind(sock, sap->sa_family, local_ip);
 	if (ret < 0) {
 		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
 		rpc_createerr.cf_error.re_errno = errno;
@@ -355,7 +359,8 @@ static CLIENT *nfs_get_tcpclient(const struct sockaddr *sap,
 				 const rpcprog_t program,
 				 const rpcvers_t version,
 				 struct timeval *timeout,
-				 const int resvport)
+				 const int resvport,
+				 struct local_bind_info *local_ip)
 {
 	CLIENT *client;
 	int ret, sock;
@@ -383,9 +388,9 @@ static CLIENT *nfs_get_tcpclient(const struct sockaddr *sap,
 	}
 
 	if (resvport)
-		ret = nfs_bindresvport(sock, sap->sa_family);
+		ret = nfs_bindresvport(sock, sap->sa_family, local_ip);
 	else
-		ret = nfs_bind(sock, sap->sa_family);
+		ret = nfs_bind(sock, sap->sa_family, local_ip);
 	if (ret < 0) {
 		rpc_createerr.cf_stat = RPC_SYSTEMERROR;
 		rpc_createerr.cf_error.re_errno = errno;
@@ -442,7 +447,8 @@ CLIENT *nfs_get_rpcclient(const struct sockaddr *sap,
 			  const unsigned short transport,
 			  const rpcprog_t program,
 			  const rpcvers_t version,
-			  struct timeval *timeout)
+			  struct timeval *timeout,
+			  struct local_bind_info *local_ip)
 {
 	nfs_clear_rpc_createerr();
 
@@ -465,11 +471,11 @@ CLIENT *nfs_get_rpcclient(const struct sockaddr *sap,
 	switch (transport) {
 	case IPPROTO_TCP:
 		return nfs_get_tcpclient(sap, salen, program, version,
-						timeout, 0);
+					 timeout, 0, local_ip);
 	case 0:
 	case IPPROTO_UDP:
 		return nfs_get_udpclient(sap, salen, program, version,
-						timeout, 0);
+					 timeout, 0, local_ip);
 	}
 
 	rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
@@ -499,7 +505,8 @@ CLIENT *nfs_get_priv_rpcclient(const struct sockaddr *sap,
 			       const unsigned short transport,
 			       const rpcprog_t program,
 			       const rpcvers_t version,
-			       struct timeval *timeout)
+			       struct timeval *timeout,
+			       struct local_bind_info *local_ip)
 {
 	nfs_clear_rpc_createerr();
 
@@ -522,11 +529,11 @@ CLIENT *nfs_get_priv_rpcclient(const struct sockaddr *sap,
 	switch (transport) {
 	case IPPROTO_TCP:
 		return nfs_get_tcpclient(sap, salen, program, version,
-						timeout, 1);
+					 timeout, 1, local_ip);
 	case 0:
 	case IPPROTO_UDP:
 		return nfs_get_udpclient(sap, salen, program, version,
-						timeout, 1);
+					 timeout, 1, local_ip);
 	}
 
 	rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
diff --git a/utils/gssd/gssd.h b/utils/gssd/gssd.h
index b1b5793..ccd44a2 100644
--- a/utils/gssd/gssd.h
+++ b/utils/gssd/gssd.h
@@ -34,6 +34,7 @@
 #include <sys/types.h>
 #include <sys/queue.h>
 #include <gssapi/gssapi.h>
+#include "sockaddr.h"
 
 #define MAX_FILE_NAMELEN	32
 #define FD_ALLOC_BLOCK		256
@@ -85,6 +86,7 @@ struct clnt_info {
 	int                     gssd_fd;
 	int                     gssd_poll_index;
 	struct sockaddr_storage addr;
+	struct local_bind_info  local_ip;
 };
 
 TAILQ_HEAD(topdirs_list_head, topdirs_info) topdirs_list;
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 41328c9..e584d20 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -726,7 +726,8 @@ out_err:
 static int
 populate_port(struct sockaddr *sa, const socklen_t salen,
 	      const rpcprog_t program, const rpcvers_t version,
-	      const unsigned short protocol)
+	      const unsigned short protocol,
+	      struct local_bind_info *local_ip)
 {
 	struct sockaddr_in	*s4 = (struct sockaddr_in *) sa;
 #ifdef IPV6_SUPPORTED
@@ -774,7 +775,7 @@ populate_port(struct sockaddr *sa, const socklen_t salen,
 		goto set_port;
 	}
 
-	port = nfs_getport(sa, salen, program, version, protocol);
+	port = nfs_getport(sa, salen, program, version, protocol, local_ip);
 	if (!port) {
 		printerr(0, "ERROR: unable to obtain port for prog %ld "
 			    "vers %ld\n", program, version);
@@ -807,7 +808,8 @@ int create_auth_rpc_client(struct clnt_info *clp,
 			   CLIENT **clnt_return,
 			   AUTH **auth_return,
 			   uid_t uid,
-			   int authtype)
+			   int authtype,
+			   struct local_bind_info *local_ip)
 {
 	CLIENT			*rpc_clnt = NULL;
 	struct rpc_gss_sec	sec;
@@ -899,11 +901,12 @@ int create_auth_rpc_client(struct clnt_info *clp,
 		goto out_fail;
 	}
 
-	if (!populate_port(addr, salen, clp->prog, clp->vers, protocol))
+	if (!populate_port(addr, salen, clp->prog, clp->vers,
+			   protocol, local_ip))
 		goto out_fail;
 
 	rpc_clnt = nfs_get_rpcclient(addr, salen, protocol, clp->prog,
-				     clp->vers, &timeout);
+				     clp->vers, &timeout, local_ip);
 	if (!rpc_clnt) {
 		snprintf(rpc_errmsg, sizeof(rpc_errmsg),
 			 "WARNING: can't create %s rpc_clnt to server %s for "
@@ -955,7 +958,7 @@ int create_auth_rpc_client(struct clnt_info *clp,
  */
 static void
 process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
-		    char *service)
+		    char *service, struct local_bind_info *local_ip)
 {
 	CLIENT			*rpc_clnt = NULL;
 	AUTH			*auth = NULL;
@@ -1011,7 +1014,7 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
 				downcall_err = -EKEYEXPIRED;
 			else if (!err)
 				create_resp = create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
-							     AUTHTYPE_KRB5);
+								     AUTHTYPE_KRB5, local_ip);
 			if (create_resp == 0)
 				break;
 		}
@@ -1038,7 +1041,8 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
 					gssd_setup_krb5_machine_gss_ccache(*ccname);
 					if ((create_auth_rpc_client(clp, &rpc_clnt,
 								    &auth, uid,
-								    AUTHTYPE_KRB5)) == 0) {
+								    AUTHTYPE_KRB5,
+								    local_ip)) == 0) {
 						/* Success! */
 						success++;
 						break;
@@ -1108,7 +1112,8 @@ out_return_error:
  * context on behalf of the kernel
  */
 static void
-process_spkm3_upcall(struct clnt_info *clp, uid_t uid, int fd)
+process_spkm3_upcall(struct clnt_info *clp, uid_t uid, int fd,
+		     struct local_bind_info *local_ip)
 {
 	CLIENT			*rpc_clnt = NULL;
 	AUTH			*auth = NULL;
@@ -1120,7 +1125,7 @@ process_spkm3_upcall(struct clnt_info *clp, uid_t uid, int fd)
 	token.length = 0;
 	token.value = NULL;
 
-	if (create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, AUTHTYPE_SPKM3)) {
+	if (create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, AUTHTYPE_SPKM3, local_ip)) {
 		printerr(0, "WARNING: Failed to create spkm3 context for "
 			    "user with uid %d\n", uid);
 		goto out_return_error;
@@ -1167,7 +1172,7 @@ handle_krb5_upcall(struct clnt_info *clp)
 		return;
 	}
 
-	return process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL);
+	process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL, &clp->local_ip);
 }
 
 void
@@ -1181,7 +1186,7 @@ handle_spkm3_upcall(struct clnt_info *clp)
 		return;
 	}
 
-	return process_spkm3_upcall(clp, uid, clp->spkm3_fd);
+	process_spkm3_upcall(clp, uid, clp->spkm3_fd, &clp->local_ip);
 }
 
 void
@@ -1291,9 +1296,9 @@ handle_gssd_upcall(struct clnt_info *clp)
 	}
 
 	if (strcmp(mech, "krb5") == 0)
-		process_krb5_upcall(clp, uid, clp->gssd_fd, target, service);
+		process_krb5_upcall(clp, uid, clp->gssd_fd, target, service, &clp->local_ip);
 	else if (strcmp(mech, "spkm3") == 0)
-		process_spkm3_upcall(clp, uid, clp->gssd_fd);
+		process_spkm3_upcall(clp, uid, clp->gssd_fd, &clp->local_ip);
 	else
 		printerr(0, "WARNING: handle_gssd_upcall: "
 			    "received unknown gss mech '%s'\n", mech);
diff --git a/utils/mount/network.c b/utils/mount/network.c
index d1f91dc..5ba6967 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -537,7 +537,8 @@ static void nfs_pp_debug2(const char *str)
  */
 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 unsigned int *protos,
+			  struct local_bind_info *local_ip)
 {
 	union nfs_sockaddr address;
 	struct sockaddr *saddr = &address.sa;
@@ -555,14 +556,16 @@ static int nfs_probe_port(const struct sockaddr *sap, const socklen_t salen,
 		if (verbose)
 			printf(_("%s: prog %lu, trying vers=%lu, prot=%u\n"),
 				progname, prog, *p_vers, *p_prot);
-		p_port = nfs_getport(saddr, salen, prog, *p_vers, *p_prot);
+		p_port = nfs_getport(saddr, salen, prog, *p_vers, *p_prot,
+				     local_ip);
 		if (p_port) {
 			if (!port || port == 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,
-							*p_vers, *p_prot, NULL))
+						 *p_vers, *p_prot, NULL,
+						 local_ip))
 					goto out_ok;
 			} else
 				rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
@@ -615,7 +618,8 @@ out_ok:
  * 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 pmap *pmap,
+			     struct local_bind_info *local_ip)
 {
 	if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
 		return 1;
@@ -626,10 +630,12 @@ static int nfs_probe_nfsport(const struct sockaddr *sap, const socklen_t salen,
 		probe_proto = nfs_default_proto();
 
 		return nfs_probe_port(sap, salen, pmap,
-					probe_nfs3_first, probe_proto);
+				      probe_nfs3_first, probe_proto,
+				      local_ip);
 	} else
 		return nfs_probe_port(sap, salen, pmap,
-					probe_nfs2_only, probe_udp_only);
+				      probe_nfs2_only, probe_udp_only,
+				      local_ip);
 }
 
 /*
@@ -646,17 +652,20 @@ static int nfs_probe_nfsport(const struct sockaddr *sap, const socklen_t salen,
  * 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 pmap *pmap,
+			     struct local_bind_info *local_ip)
 {
 	if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
 		return 1;
 
 	if (nfs_mount_data_version >= 4)
 		return nfs_probe_port(sap, salen, pmap,
-					probe_mnt3_first, probe_udp_first);
+				      probe_mnt3_first, probe_udp_first,
+				      local_ip);
 	else
 		return nfs_probe_port(sap, salen, pmap,
-					probe_mnt1_first, probe_udp_only);
+				      probe_mnt1_first, probe_udp_only,
+				      local_ip);
 }
 
 /*
@@ -673,11 +682,12 @@ static int nfs_probe_version_fixed(const struct sockaddr *mnt_saddr,
 			struct pmap *mnt_pmap,
 			const struct sockaddr *nfs_saddr,
 			const socklen_t nfs_salen,
-			struct pmap *nfs_pmap)
+			struct pmap *nfs_pmap,
+			struct local_bind_info *local_ip)
 {
-	if (!nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap))
+	if (!nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap, local_ip))
 		return 0;
-	return nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap);
+	return nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap, local_ip);
 }
 
 /**
@@ -700,7 +710,8 @@ int nfs_probe_bothports(const struct sockaddr *mnt_saddr,
 			struct pmap *mnt_pmap,
 			const struct sockaddr *nfs_saddr,
 			const socklen_t nfs_salen,
-			struct pmap *nfs_pmap)
+			struct pmap *nfs_pmap,
+			struct local_bind_info *local_ip)
 {
 	struct pmap save_nfs, save_mnt;
 	const unsigned long *probe_vers;
@@ -712,7 +723,8 @@ int nfs_probe_bothports(const struct sockaddr *mnt_saddr,
 
 	if (nfs_pmap->pm_vers)
 		return nfs_probe_version_fixed(mnt_saddr, mnt_salen, mnt_pmap,
-					       nfs_saddr, nfs_salen, nfs_pmap);
+					       nfs_saddr, nfs_salen, nfs_pmap,
+					       local_ip);
 
 	memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
 	memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
@@ -721,9 +733,9 @@ int nfs_probe_bothports(const struct sockaddr *mnt_saddr,
 
 	for (; *probe_vers; probe_vers++) {
 		nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
-		if (nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap) != 0) {
+		if (nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap, local_ip) != 0) {
 			mnt_pmap->pm_vers = *probe_vers;
-			if (nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap) != 0)
+			if (nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap, local_ip) != 0)
 				return 1;
 			memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
 		}
@@ -753,7 +765,8 @@ int nfs_probe_bothports(const struct sockaddr *mnt_saddr,
  * 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 probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server,
+		    struct local_bind_info *local_ip)
 {
 	struct sockaddr *mnt_addr = SAFE_SOCKADDR(&mnt_server->saddr);
 	struct sockaddr *nfs_addr = SAFE_SOCKADDR(&nfs_server->saddr);
@@ -761,7 +774,7 @@ int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
 	return nfs_probe_bothports(mnt_addr, sizeof(mnt_server->saddr),
 					&mnt_server->pmap,
 					nfs_addr, sizeof(nfs_server->saddr),
-					&nfs_server->pmap);
+				   &nfs_server->pmap, local_ip);
 }
 
 static int nfs_probe_statd(void)
@@ -773,7 +786,8 @@ static int nfs_probe_statd(void)
 	rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl);
 
 	return nfs_getport_ping(SAFE_SOCKADDR(&addr), sizeof(addr),
-				program, (rpcvers_t)1, IPPROTO_UDP);
+				program, (rpcvers_t)1, IPPROTO_UDP,
+				NULL);
 }
 
 /**
@@ -829,7 +843,8 @@ int start_statd(void)
  * We use a fast timeout since this call is advisory only.
  */
 int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen,
-		      const struct pmap *pmap, const dirpath *argp)
+		      const struct pmap *pmap, const dirpath *argp,
+		      struct local_bind_info *local_ip)
 {
 	union nfs_sockaddr address;
 	struct sockaddr *saddr = &address.sa;
@@ -841,7 +856,7 @@ int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen,
 	enum clnt_stat res = 0;
 
 	memcpy(saddr, sap, salen);
-	if (nfs_probe_mntport(saddr, salen, &mnt_pmap) == 0) {
+	if (nfs_probe_mntport(saddr, salen, &mnt_pmap, local_ip) == 0) {
 		if (verbose)
 			nfs_error(_("%s: Failed to discover mountd port%s"),
 				progname, clnt_spcreateerror(""));
@@ -851,7 +866,7 @@ int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen,
 
 	client = nfs_get_priv_rpcclient(saddr, salen, mnt_pmap.pm_prot,
 					mnt_pmap.pm_prog, mnt_pmap.pm_vers,
-					&timeout);
+					&timeout, local_ip);
 	if (client == NULL) {
 		if (verbose)
 			nfs_error(_("%s: Failed to create RPC client%s"),
@@ -908,7 +923,7 @@ int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
 	enum clnt_stat res = 0;
 	int msock;
 
-	if (!nfs_probe_mntport(sap, salen, pmap))
+	if (!nfs_probe_mntport(sap, salen, pmap, NULL))
 		return 0;
 	clnt = mnt_openclnt(mnt_server, &msock);
 	if (!clnt)
@@ -1659,7 +1674,8 @@ out:
  * parsed successfully; otherwise EX_FAIL.
  */
 int nfs_umount_do_umnt(struct mount_options *options,
-		       char **hostname, char **dirname)
+		       char **hostname, char **dirname,
+		       struct local_bind_info *local_ip)
 {
 	union nfs_sockaddr address;
 	struct sockaddr *sap = &address.sa;
@@ -1686,7 +1702,7 @@ int nfs_umount_do_umnt(struct mount_options *options,
 		/* nfs_lookup reports any errors */
 		return EX_FAIL;
 
-	if (nfs_advise_umount(sap, salen, &mnt_pmap, dirname) == 0)
+	if (nfs_advise_umount(sap, salen, &mnt_pmap, dirname, local_ip) == 0)
 		/* nfs_advise_umount reports any errors */
 		return EX_FAIL;
 
diff --git a/utils/mount/network.h b/utils/mount/network.h
index 81c6f22..a832e76 100644
--- a/utils/mount/network.h
+++ b/utils/mount/network.h
@@ -25,6 +25,7 @@
 #define _NFS_UTILS_MOUNT_NETWORK_H
 
 #include <rpc/pmap_prot.h>
+#include "sockaddr.h"
 
 #define MNT_SENDBUFSIZE (2048U)
 #define MNT_RECVBUFSIZE (1024U)
@@ -39,10 +40,11 @@ typedef struct {
 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 probe_bothports(clnt_addr_t *, clnt_addr_t *, struct local_bind_info *);
 int nfs_probe_bothports(const struct sockaddr *, const socklen_t,
 			struct pmap *, const struct sockaddr *,
-			const socklen_t, struct pmap *);
+			const socklen_t, struct pmap *,
+			struct local_bind_info *);
 int nfs_gethostbyname(const char *, struct sockaddr_in *);
 int nfs_lookup(const char *hostname, const sa_family_t family,
 		struct sockaddr *sap, socklen_t *salen);
@@ -53,7 +55,7 @@ int nfs_callback_address(const struct sockaddr *, const socklen_t,
 		struct sockaddr *, socklen_t *);
 int clnt_ping(struct sockaddr_in *, const unsigned long,
 		const unsigned long, const unsigned int,
-		struct sockaddr_in *);
+	      struct sockaddr_in *);
 
 struct mount_options;
 
@@ -71,11 +73,13 @@ unsigned long nfsvers_to_mnt(const unsigned long);
 
 int nfs_call_umount(clnt_addr_t *, dirpath *);
 int nfs_advise_umount(const struct sockaddr *, const socklen_t,
-		      const struct pmap *, const dirpath *);
+		      const struct pmap *, const dirpath *,
+		      struct local_bind_info *);
 CLIENT *mnt_openclnt(clnt_addr_t *, int *);
 void mnt_closeclnt(CLIENT *, int);
 
 int nfs_umount_do_umnt(struct mount_options *options,
-		       char **hostname, char **dirname);
+		       char **hostname, char **dirname,
+		       struct local_bind_info *local_ip);
 
 #endif	/* _NFS_UTILS_MOUNT_NETWORK_H */
diff --git a/utils/mount/nfsmount.c b/utils/mount/nfsmount.c
index 1298fe4..960cbaa 100644
--- a/utils/mount/nfsmount.c
+++ b/utils/mount/nfsmount.c
@@ -129,7 +129,7 @@ nfs_call_mount(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server,
 	enum clnt_stat stat;
 	int msock;
 
-	if (!probe_bothports(mnt_server, nfs_server))
+	if (!probe_bothports(mnt_server, nfs_server, NULL))
 		goto out_bad;
 
 	clnt = mnt_openclnt(mnt_server, &msock);
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index f1aa503..71417df 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -534,7 +534,7 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options)
 	 * negotiate.  Bail now if we can't contact it.
 	 */
 	if (!nfs_probe_bothports(mnt_saddr, mnt_salen, &mnt_pmap,
-				 nfs_saddr, nfs_salen, &nfs_pmap)) {
+				 nfs_saddr, nfs_salen, &nfs_pmap, NULL)) {
 		errno = ESPIPE;
 		if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED)
 			errno = EOPNOTSUPP;
diff --git a/utils/mount/utils.c b/utils/mount/utils.c
index 298db39..eb50074 100644
--- a/utils/mount/utils.c
+++ b/utils/mount/utils.c
@@ -164,7 +164,7 @@ int nfs_umount23(const char *devname, char *string)
 
 	options = po_split(string);
 	if (options) {
-		result = nfs_umount_do_umnt(options, &hostname, &dirname);
+		result = nfs_umount_do_umnt(options, &hostname, &dirname, NULL);
 		po_destroy(options);
 	} else
 		nfs_error(_("%s: option parsing error"), progname);
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 2/6] nfs-utils:  Add patch to parse srcaddr= option.
  2011-06-10 21:08 [PATCH v3 0/6] nfs-utils: Support binding to source address greearb
  2011-06-10 21:08 ` [PATCH v3 1/6] nfs-utils: Add structure for passing local binding info greearb
@ 2011-06-10 21:08 ` greearb
  2011-06-10 21:08 ` [PATCH v3 3/6] nfs-utils: Implement srcaddr binding in rpc_socket greearb
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: greearb @ 2011-06-10 21:08 UTC (permalink / raw)
  To: linux-nfs; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

This will be used to parse the IP address used for
binding to a particular local IP address.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 5ba6967... 65c2145... M	utils/mount/network.c
:100644 100644 a832e76... 6f66822... M	utils/mount/network.h
 utils/mount/network.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 utils/mount/network.h |    2 ++
 2 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/utils/mount/network.c b/utils/mount/network.c
index 5ba6967..65c2145 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -405,6 +405,51 @@ out:
 }
 
 /*
+ *  node should be an IPv4 or IPv6 address numeric notation.
+ *  The value will be parsed in placed into laddr.
+ */
+void
+parse_local_bind(struct local_bind_info *laddr, const char* node) {
+	/* str is an IP address. */
+	int aiErr;
+	struct addrinfo *aiHead;
+	struct addrinfo hints;
+
+	laddr->is_set = 0;
+
+	memset(&hints, 0, sizeof(hints));
+
+	hints.ai_flags  = AI_NUMERICSERV;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_protocol = IPPROTO_TCP;
+	hints.ai_family = PF_INET;
+
+	aiErr = getaddrinfo(node, NULL, &hints, &aiHead);
+
+	/* If we tried PF_INET and it failed, try IPv6 instead
+	 * to see if it resolves properly.
+	 */
+	if (aiErr != 0) {
+		hints.ai_family = PF_INET6;
+		aiErr = getaddrinfo(node, NULL, &hints, &aiHead);
+	}
+
+	if (aiErr != 0) {
+		nfs_error(_("%s: parse srcaddr failed, "
+			    "node: %s  aiErr: %i %s\n"),
+			  progname, node, aiErr, gai_strerror(aiErr));
+	} else {
+		if (aiHead) {
+			memcpy(&laddr->addr, aiHead->ai_addr,
+			       aiHead->ai_addrlen);
+			laddr->addrlen = aiHead->ai_addrlen;
+			laddr->is_set = true;
+			freeaddrinfo(aiHead);
+		}
+	}
+}
+
+/*
  * Create a socket that is locally bound to a reserved or non-reserved port.
  *
  * The caller should check rpc_createerr to determine the cause of any error.
diff --git a/utils/mount/network.h b/utils/mount/network.h
index a832e76..6f66822 100644
--- a/utils/mount/network.h
+++ b/utils/mount/network.h
@@ -36,6 +36,8 @@ typedef struct {
 	struct pmap pmap;
 } clnt_addr_t;
 
+void parse_local_bind(struct local_bind_info *laddr, const char* str);
+
 /* RPC call timeout values */
 static const struct timeval TIMEOUT = { 20, 0 };
 static const struct timeval RETRY_TIMEOUT = { 3, 0 };
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 3/6] nfs-utils:  Implement srcaddr binding in rpc_socket
  2011-06-10 21:08 [PATCH v3 0/6] nfs-utils: Support binding to source address greearb
  2011-06-10 21:08 ` [PATCH v3 1/6] nfs-utils: Add structure for passing local binding info greearb
  2011-06-10 21:08 ` [PATCH v3 2/6] nfs-utils: Add patch to parse srcaddr= option greearb
@ 2011-06-10 21:08 ` greearb
  2011-06-10 22:06   ` Chuck Lever
  2011-06-10 21:08 ` [PATCH v3 4/6] nfs-utils: Support srcaddr=n option for string mount greearb
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 15+ messages in thread
From: greearb @ 2011-06-10 21:08 UTC (permalink / raw)
  To: linux-nfs; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

This implements the actual binding, if we are passed
a non-null local_ip structure.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 5652f6c... 4bcbdf0... M	support/nfs/rpc_socket.c
 support/nfs/rpc_socket.c |   59 +++++++++++++++++++++++++++++++++++----------
 1 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/support/nfs/rpc_socket.c b/support/nfs/rpc_socket.c
index 5652f6c..4bcbdf0 100644
--- a/support/nfs/rpc_socket.c
+++ b/support/nfs/rpc_socket.c
@@ -115,6 +115,8 @@ static CLIENT *nfs_get_localclient(const struct sockaddr *sap,
 static int nfs_bind(const int sock, const sa_family_t family,
 		    struct local_bind_info *local_ip)
 {
+	struct sockaddr *sa = NULL;
+	socklen_t salen = 0;
 	struct sockaddr_in sin = {
 		.sin_family		= AF_INET,
 		.sin_addr.s_addr	= htonl(INADDR_ANY),
@@ -124,15 +126,26 @@ static int nfs_bind(const int sock, const sa_family_t family,
 		.sin6_addr		= IN6ADDR_ANY_INIT,
 	};
 
-	switch (family) {
-	case AF_INET:
-		return bind(sock, (struct sockaddr *)(char *)&sin,
-					(socklen_t)sizeof(sin));
-	case AF_INET6:
-		return bind(sock, (struct sockaddr *)(char *)&sin6,
-					(socklen_t)sizeof(sin6));
+	if (local_ip && local_ip->is_set) {
+		sa = &local_ip->addr.sa;
+		salen = local_ip->addrlen;
+	} else {
+		switch (family) {
+		case AF_INET:
+			sa = (struct sockaddr *)&sin;
+			salen = sizeof(sin);
+			break;
+		case AF_INET6:
+			sa = (struct sockaddr *)&sin6;
+			salen = sizeof(sin6);
+		default:
+			break;
+		}
 	}
 
+	if (sa)
+		return bind(sock, sa, salen);
+
 	errno = EAFNOSUPPORT;
 	return -1;
 }
@@ -148,6 +161,7 @@ static int nfs_bind(const int sock, const sa_family_t family,
 static int nfs_bindresvport(const int sock, const sa_family_t family,
 			    struct local_bind_info *local_ip)
 {
+	struct sockaddr *sa = NULL;
 	struct sockaddr_in sin = {
 		.sin_family		= AF_INET,
 		.sin_addr.s_addr	= htonl(INADDR_ANY),
@@ -157,13 +171,23 @@ static int nfs_bindresvport(const int sock, const sa_family_t family,
 		.sin6_addr		= IN6ADDR_ANY_INIT,
 	};
 
-	switch (family) {
-	case AF_INET:
-		return bindresvport_sa(sock, (struct sockaddr *)(char *)&sin);
-	case AF_INET6:
-		return bindresvport_sa(sock, (struct sockaddr *)(char *)&sin6);
+	if (local_ip && local_ip->is_set) {
+		sa = &local_ip->addr.sa;
+	} else {
+		switch (family) {
+		case AF_INET:
+			sa = (struct sockaddr *)&sin;
+			break;
+		case AF_INET6:
+			sa = (struct sockaddr *)&sin6;
+		default:
+			break;
+		}
 	}
 
+	if (sa)
+		return bindresvport_sa(sock, sa);
+
 	errno = EAFNOSUPPORT;
 	return -1;
 }
@@ -179,12 +203,21 @@ static int nfs_bindresvport(const int sock, const sa_family_t family,
 static int nfs_bindresvport(const int sock, const sa_family_t family,
 			    struct local_bind_info *local_ip)
 {
+	struct sockaddr_in laddr;
 	if (family != AF_INET) {
 		errno = EAFNOSUPPORT;
 		return -1;
 	}
 
-	return bindresvport(sock, NULL);
+	laddr.sin_family = family;
+	laddr.sin_port = 0;
+	if (local_ip && local_ip->is_set) {
+		struct sockaddr_in *si = &local_ip->addr.s4;
+		laddr.sin_addr.s_addr = si->sin_addr.s_addr;
+	} else {
+		laddr.sin_addr.s_addr = htonl(INADDR_ANY);
+	}
+	return bindresvport(sock, &laddr);
 }
 
 #endif	/* !HAVE_LIBTIRPC */
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 4/6] nfs-utils:  Support srcaddr=n option for string mount.
  2011-06-10 21:08 [PATCH v3 0/6] nfs-utils: Support binding to source address greearb
                   ` (2 preceding siblings ...)
  2011-06-10 21:08 ` [PATCH v3 3/6] nfs-utils: Implement srcaddr binding in rpc_socket greearb
@ 2011-06-10 21:08 ` greearb
  2011-06-10 22:07   ` Chuck Lever
  2011-06-10 21:08 ` [PATCH v3 5/6] nfs-utils: Implement srcaddr=n binding for unmount greearb
  2011-06-10 21:08 ` [PATCH v3 6/6] nfs-utils: Update man page for srcaddr= option greearb
  5 siblings, 1 reply; 15+ messages in thread
From: greearb @ 2011-06-10 21:08 UTC (permalink / raw)
  To: linux-nfs; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

Look for and parse the srcaddr=n argument.  If parsing
succeeds, pass this down the call chain.  This fully
implements binding to a specified source address when
mounting.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 71417df... aba4252... M	utils/mount/stropts.c
 utils/mount/stropts.c |   29 +++++++++++++++++++++++++----
 1 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 71417df..aba4252 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -92,6 +92,7 @@ struct nfsmount_info {
 	int			flags,		/* MS_ flags */
 				fake,		/* actually do the mount? */
 				child;		/* forked bg child? */
+	struct local_bind_info  *local_ip;      /* Local IP binding info */
 };
 
 #ifdef MOUNT_CONFIG
@@ -345,6 +346,7 @@ static int nfs_validate_options(struct nfsmount_info *mi)
 	};
 	sa_family_t family;
 	int error;
+	char *option;
 
 	if (!nfs_parse_devname(mi->spec, &mi->hostname, NULL))
 		return 0;
@@ -371,6 +373,20 @@ static int nfs_validate_options(struct nfsmount_info *mi)
 					mi->address->ai_addrlen, mi->options))
 		return 0;
 
+	option = po_get(mi->options, "srcaddr");
+	if (option) {
+		struct local_bind_info *local_ip;
+		local_ip = malloc(sizeof(*local_ip));
+		memset(local_ip, 0, sizeof(*local_ip));
+		parse_local_bind(local_ip, option);
+
+		if (!local_ip->is_set) {
+			free(local_ip);
+			return 0;
+		}
+		mi->local_ip = local_ip;
+	}
+
 	return 1;
 }
 
@@ -484,7 +500,8 @@ static int nfs_construct_new_options(struct mount_options *options,
  * FALSE is returned if some failure occurred.
  */
 static int
-nfs_rewrite_pmap_mount_options(struct mount_options *options)
+nfs_rewrite_pmap_mount_options(struct mount_options *options,
+			       struct local_bind_info *local_ip)
 {
 	union nfs_sockaddr nfs_address;
 	struct sockaddr *nfs_saddr = &nfs_address.sa;
@@ -534,7 +551,8 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options)
 	 * negotiate.  Bail now if we can't contact it.
 	 */
 	if (!nfs_probe_bothports(mnt_saddr, mnt_salen, &mnt_pmap,
-				 nfs_saddr, nfs_salen, &nfs_pmap, NULL)) {
+				 nfs_saddr, nfs_salen, &nfs_pmap,
+				 local_ip)) {
 		errno = ESPIPE;
 		if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED)
 			errno = EOPNOTSUPP;
@@ -589,7 +607,7 @@ static int nfs_sys_mount(struct nfsmount_info *mi, struct mount_options *opts)
 }
 
 static int nfs_do_mount_v3v2(struct nfsmount_info *mi,
-		struct sockaddr *sap, socklen_t salen)
+			     struct sockaddr *sap, socklen_t salen)
 {
 	struct mount_options *options = po_dup(mi->options);
 	int result = 0;
@@ -631,7 +649,7 @@ static int nfs_do_mount_v3v2(struct nfsmount_info *mi,
 		printf(_("%s: trying text-based options '%s'\n"),
 			progname, *mi->extra_opts);
 
-	if (!nfs_rewrite_pmap_mount_options(options))
+	if (!nfs_rewrite_pmap_mount_options(options, mi->local_ip))
 		goto out_fail;
 
 	result = nfs_sys_mount(mi, options);
@@ -1039,6 +1057,7 @@ int nfsmount_string(const char *spec, const char *node, const char *type,
 		.flags		= flags,
 		.fake		= fake,
 		.child		= child,
+		.local_ip	= NULL,
 	};
 	int retval = EX_FAIL;
 
@@ -1051,5 +1070,7 @@ int nfsmount_string(const char *spec, const char *node, const char *type,
 
 	freeaddrinfo(mi.address);
 	free(mi.hostname);
+	if (mi.local_ip)
+		free(mi.local_ip);
 	return retval;
 }
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 5/6] nfs-utils:  Implement srcaddr=n binding for unmount.
  2011-06-10 21:08 [PATCH v3 0/6] nfs-utils: Support binding to source address greearb
                   ` (3 preceding siblings ...)
  2011-06-10 21:08 ` [PATCH v3 4/6] nfs-utils: Support srcaddr=n option for string mount greearb
@ 2011-06-10 21:08 ` greearb
  2011-06-10 21:08 ` [PATCH v3 6/6] nfs-utils: Update man page for srcaddr= option greearb
  5 siblings, 0 replies; 15+ messages in thread
From: greearb @ 2011-06-10 21:08 UTC (permalink / raw)
  To: linux-nfs; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

This fully implements binding to a local IP address when
attempting to un-mount.

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 8cd2852... ef5ec17... M	utils/mount/nfsumount.c
:100644 100644 eb50074... c3d3467... M	utils/mount/utils.c
:100644 100644 3fcd504... ef71814... M	utils/mount/utils.h
 utils/mount/nfsumount.c |   26 +++++++++++++++++++++++---
 utils/mount/utils.c     |    6 ++++--
 utils/mount/utils.h     |    4 +++-
 3 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c
index 8cd2852..ef5ec17 100644
--- a/utils/mount/nfsumount.c
+++ b/utils/mount/nfsumount.c
@@ -239,6 +239,9 @@ int nfsumount(int argc, char *argv[])
 	int c, ret;
 	char *spec;
 	struct mntentchn *mc;
+	char *opt;
+	struct local_bind_info local_ip;
+	memset(&local_ip, 0, sizeof(local_ip));
 
 	if (argc < 2) {
 		umount_usage();
@@ -314,7 +317,7 @@ int nfsumount(int argc, char *argv[])
 			return EX_USAGE;
 		}
 		if (hasmntopt(&mc->m, "users") == NULL) {
-			char *opt = hasmntopt(&mc->m, "user");
+			opt = hasmntopt(&mc->m, "user");
 			struct passwd *pw;
 			char *comma;
 			size_t len;
@@ -334,6 +337,22 @@ int nfsumount(int argc, char *argv[])
 		}
 	}
 
+	if (mc) {
+		opt = hasmntopt(&mc->m, "srcaddr");
+		if ((opt != NULL) && strlen(opt) > strlen("srcaddr=")) {
+			char *sa = xstrdup(opt + strlen("srcaddr="));
+			unsigned int z;
+			for (z = 0; z < strlen(sa); z++) {
+				if (sa[z] == ',') {
+					sa[z] = 0;
+					break;
+				}
+			}
+			parse_local_bind(&local_ip, sa);
+			free(sa);
+		}
+	}
+
 	ret = EX_SUCCESS;
 	if (mc) {
 		if (!lazy) {
@@ -344,7 +363,8 @@ int nfsumount(int argc, char *argv[])
 				 * we don't want to signal an error, as that
 				 * could cause /sbin/mount to retry!
 				 */
-				nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
+				nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts,
+					     &local_ip);
 				break;
 			case 1:
 				break;
@@ -355,7 +375,7 @@ int nfsumount(int argc, char *argv[])
 		ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir);
 	} else if (*spec != '/') {
 		if (!lazy)
-			ret = nfs_umount23(spec, "tcp,v3");
+			ret = nfs_umount23(spec, "tcp,v3", &local_ip);
 	} else
 		ret = del_mtab(NULL, spec);
 
diff --git a/utils/mount/utils.c b/utils/mount/utils.c
index eb50074..c3d3467 100644
--- a/utils/mount/utils.c
+++ b/utils/mount/utils.c
@@ -153,7 +153,8 @@ int chk_mountpoint(const char *mount_point)
  * pmap tuple.  If the GETPORT call later fails to disambiguate them,
  * then we fail.
  */
-int nfs_umount23(const char *devname, char *string)
+int nfs_umount23(const char *devname, char *string,
+		 struct local_bind_info *local_ip)
 {
 	char *hostname = NULL, *dirname = NULL;
 	struct mount_options *options;
@@ -164,7 +165,8 @@ int nfs_umount23(const char *devname, char *string)
 
 	options = po_split(string);
 	if (options) {
-		result = nfs_umount_do_umnt(options, &hostname, &dirname, NULL);
+		result = nfs_umount_do_umnt(options, &hostname, &dirname,
+					    local_ip);
 		po_destroy(options);
 	} else
 		nfs_error(_("%s: option parsing error"), progname);
diff --git a/utils/mount/utils.h b/utils/mount/utils.h
index 3fcd504..ef71814 100644
--- a/utils/mount/utils.h
+++ b/utils/mount/utils.h
@@ -31,6 +31,8 @@ void mount_usage(void);
 void umount_usage(void);
 int chk_mountpoint(const char *mount_point);
 
-int nfs_umount23(const char *devname, char *string);
+struct local_bind_info;
+int nfs_umount23(const char *devname, char *string,
+		 struct local_bind_info *local_ip);
 
 #endif	/* !_NFS_UTILS_MOUNT_UTILS_H */
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v3 6/6] nfs-utils:  Update man page for srcaddr= option.
  2011-06-10 21:08 [PATCH v3 0/6] nfs-utils: Support binding to source address greearb
                   ` (4 preceding siblings ...)
  2011-06-10 21:08 ` [PATCH v3 5/6] nfs-utils: Implement srcaddr=n binding for unmount greearb
@ 2011-06-10 21:08 ` greearb
  5 siblings, 0 replies; 15+ messages in thread
From: greearb @ 2011-06-10 21:08 UTC (permalink / raw)
  To: linux-nfs; +Cc: Ben Greear

From: Ben Greear <greearb@candelatech.com>

Signed-off-by: Ben Greear <greearb@candelatech.com>
---
:100644 100644 be91a25... 622d7cb... M	utils/mount/nfs.man
 utils/mount/nfs.man |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man
index be91a25..622d7cb 100644
--- a/utils/mount/nfs.man
+++ b/utils/mount/nfs.man
@@ -463,6 +463,13 @@ by other clients, but can impact application and server performance.
 .IP
 The DATA AND METADATA COHERENCE section contains a
 detailed discussion of these trade-offs.
+.TP 1.5i
+.BI srcaddr= n
+Specifies a single IPv4 or IPv6 address
+to which the NFS client will bind its sockets.
+This can help force NFS to use a particular IP
+address on a multi-homed machine.  This option is not required
+in most cases.
 .SS "Options for NFS versions 2 and 3 only"
 Use these options, along with the options in the above subsection,
 for NFS versions 2 and 3 only.
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 3/6] nfs-utils:  Implement srcaddr binding in rpc_socket
  2011-06-10 21:08 ` [PATCH v3 3/6] nfs-utils: Implement srcaddr binding in rpc_socket greearb
@ 2011-06-10 22:06   ` Chuck Lever
  2011-06-10 22:19     ` Ben Greear
  0 siblings, 1 reply; 15+ messages in thread
From: Chuck Lever @ 2011-06-10 22:06 UTC (permalink / raw)
  To: greearb; +Cc: linux-nfs


On Jun 10, 2011, at 5:08 PM, greearb@candelatech.com wrote:

> From: Ben Greear <greearb@candelatech.com>
> 
> This implements the actual binding, if we are passed
> a non-null local_ip structure.

Why not _always_ pass a valid local_ip structure, and simply set .addr to an appropriate ANYADDR by default?  Then .is_set wouldn't be necessary, would it?  It would also simplify the logic in nfs_validate_options().

> 
> Signed-off-by: Ben Greear <greearb@candelatech.com>
> ---
> :100644 100644 5652f6c... 4bcbdf0... M	support/nfs/rpc_socket.c
> support/nfs/rpc_socket.c |   59 +++++++++++++++++++++++++++++++++++----------
> 1 files changed, 46 insertions(+), 13 deletions(-)
> 
> diff --git a/support/nfs/rpc_socket.c b/support/nfs/rpc_socket.c
> index 5652f6c..4bcbdf0 100644
> --- a/support/nfs/rpc_socket.c
> +++ b/support/nfs/rpc_socket.c
> @@ -115,6 +115,8 @@ static CLIENT *nfs_get_localclient(const struct sockaddr *sap,
> static int nfs_bind(const int sock, const sa_family_t family,
> 		    struct local_bind_info *local_ip)
> {
> +	struct sockaddr *sa = NULL;
> +	socklen_t salen = 0;
> 	struct sockaddr_in sin = {
> 		.sin_family		= AF_INET,
> 		.sin_addr.s_addr	= htonl(INADDR_ANY),
> @@ -124,15 +126,26 @@ static int nfs_bind(const int sock, const sa_family_t family,
> 		.sin6_addr		= IN6ADDR_ANY_INIT,
> 	};
> 
> -	switch (family) {
> -	case AF_INET:
> -		return bind(sock, (struct sockaddr *)(char *)&sin,
> -					(socklen_t)sizeof(sin));
> -	case AF_INET6:
> -		return bind(sock, (struct sockaddr *)(char *)&sin6,
> -					(socklen_t)sizeof(sin6));
> +	if (local_ip && local_ip->is_set) {
> +		sa = &local_ip->addr.sa;
> +		salen = local_ip->addrlen;
> +	} else {
> +		switch (family) {
> +		case AF_INET:
> +			sa = (struct sockaddr *)&sin;
> +			salen = sizeof(sin);
> +			break;
> +		case AF_INET6:
> +			sa = (struct sockaddr *)&sin6;
> +			salen = sizeof(sin6);
> +		default:
> +			break;
> +		}
> 	}
> 
> +	if (sa)
> +		return bind(sock, sa, salen);
> +
> 	errno = EAFNOSUPPORT;
> 	return -1;
> }
> @@ -148,6 +161,7 @@ static int nfs_bind(const int sock, const sa_family_t family,
> static int nfs_bindresvport(const int sock, const sa_family_t family,
> 			    struct local_bind_info *local_ip)
> {
> +	struct sockaddr *sa = NULL;
> 	struct sockaddr_in sin = {
> 		.sin_family		= AF_INET,
> 		.sin_addr.s_addr	= htonl(INADDR_ANY),
> @@ -157,13 +171,23 @@ static int nfs_bindresvport(const int sock, const sa_family_t family,
> 		.sin6_addr		= IN6ADDR_ANY_INIT,
> 	};
> 
> -	switch (family) {
> -	case AF_INET:
> -		return bindresvport_sa(sock, (struct sockaddr *)(char *)&sin);
> -	case AF_INET6:
> -		return bindresvport_sa(sock, (struct sockaddr *)(char *)&sin6);
> +	if (local_ip && local_ip->is_set) {
> +		sa = &local_ip->addr.sa;
> +	} else {
> +		switch (family) {
> +		case AF_INET:
> +			sa = (struct sockaddr *)&sin;
> +			break;
> +		case AF_INET6:
> +			sa = (struct sockaddr *)&sin6;
> +		default:
> +			break;
> +		}
> 	}
> 
> +	if (sa)
> +		return bindresvport_sa(sock, sa);
> +
> 	errno = EAFNOSUPPORT;
> 	return -1;
> }
> @@ -179,12 +203,21 @@ static int nfs_bindresvport(const int sock, const sa_family_t family,
> static int nfs_bindresvport(const int sock, const sa_family_t family,
> 			    struct local_bind_info *local_ip)
> {
> +	struct sockaddr_in laddr;
> 	if (family != AF_INET) {
> 		errno = EAFNOSUPPORT;
> 		return -1;
> 	}
> 
> -	return bindresvport(sock, NULL);
> +	laddr.sin_family = family;
> +	laddr.sin_port = 0;
> +	if (local_ip && local_ip->is_set) {
> +		struct sockaddr_in *si = &local_ip->addr.s4;
> +		laddr.sin_addr.s_addr = si->sin_addr.s_addr;
> +	} else {
> +		laddr.sin_addr.s_addr = htonl(INADDR_ANY);
> +	}
> +	return bindresvport(sock, &laddr);
> }
> 
> #endif	/* !HAVE_LIBTIRPC */
> -- 
> 1.7.3.4
> 
> --
> 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

-- 
Chuck Lever
chuck[dot]lever[at]oracle[dot]com





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 4/6] nfs-utils:  Support srcaddr=n option for string mount.
  2011-06-10 21:08 ` [PATCH v3 4/6] nfs-utils: Support srcaddr=n option for string mount greearb
@ 2011-06-10 22:07   ` Chuck Lever
  2011-06-10 22:30     ` Ben Greear
  2011-06-13 20:37     ` Steve Dickson
  0 siblings, 2 replies; 15+ messages in thread
From: Chuck Lever @ 2011-06-10 22:07 UTC (permalink / raw)
  To: greearb; +Cc: linux-nfs


On Jun 10, 2011, at 5:08 PM, greearb@candelatech.com wrote:

> From: Ben Greear <greearb@candelatech.com>
> 
> Look for and parse the srcaddr=n argument.  If parsing
> succeeds, pass this down the call chain.  This fully
> implements binding to a specified source address when
> mounting.
> 
> Signed-off-by: Ben Greear <greearb@candelatech.com>
> ---
> :100644 100644 71417df... aba4252... M	utils/mount/stropts.c
> utils/mount/stropts.c |   29 +++++++++++++++++++++++++----
> 1 files changed, 25 insertions(+), 4 deletions(-)
> 
> diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
> index 71417df..aba4252 100644
> --- a/utils/mount/stropts.c
> +++ b/utils/mount/stropts.c
> @@ -92,6 +92,7 @@ struct nfsmount_info {
> 	int			flags,		/* MS_ flags */
> 				fake,		/* actually do the mount? */
> 				child;		/* forked bg child? */
> +	struct local_bind_info  *local_ip;      /* Local IP binding info */
> };
> 
> #ifdef MOUNT_CONFIG
> @@ -345,6 +346,7 @@ static int nfs_validate_options(struct nfsmount_info *mi)
> 	};
> 	sa_family_t family;
> 	int error;
> +	char *option;
> 
> 	if (!nfs_parse_devname(mi->spec, &mi->hostname, NULL))
> 		return 0;
> @@ -371,6 +373,20 @@ static int nfs_validate_options(struct nfsmount_info *mi)
> 					mi->address->ai_addrlen, mi->options))
> 		return 0;
> 
> +	option = po_get(mi->options, "srcaddr");
> +	if (option) {
> +		struct local_bind_info *local_ip;
> +		local_ip = malloc(sizeof(*local_ip));
> +		memset(local_ip, 0, sizeof(*local_ip));
> +		parse_local_bind(local_ip, option);

Nit: Steve may not agree with this, possibly, but it is better IMO if we name new functions like parse_local_bind() with an nfs_ prefix so that, when debugging, we can immediately tell in a backtrace what functions are in mount.nfs and which are in a system library.

> +
> +		if (!local_ip->is_set) {
> +			free(local_ip);
> +			return 0;
> +		}
> +		mi->local_ip = local_ip;
> +	}

I'm wondering what kind of sanity checking is done on the srcaddr value.

1.  Do we verify that srcaddr == clientaddr?

2.  Do we verify that srcaddr.sa_family == addr.sa_family ?

> +
> 	return 1;
> }
> 
> @@ -484,7 +500,8 @@ static int nfs_construct_new_options(struct mount_options *options,
>  * FALSE is returned if some failure occurred.
>  */
> static int
> -nfs_rewrite_pmap_mount_options(struct mount_options *options)
> +nfs_rewrite_pmap_mount_options(struct mount_options *options,
> +			       struct local_bind_info *local_ip)
> {
> 	union nfs_sockaddr nfs_address;
> 	struct sockaddr *nfs_saddr = &nfs_address.sa;
> @@ -534,7 +551,8 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options)
> 	 * negotiate.  Bail now if we can't contact it.
> 	 */
> 	if (!nfs_probe_bothports(mnt_saddr, mnt_salen, &mnt_pmap,
> -				 nfs_saddr, nfs_salen, &nfs_pmap, NULL)) {
> +				 nfs_saddr, nfs_salen, &nfs_pmap,
> +				 local_ip)) {
> 		errno = ESPIPE;
> 		if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED)
> 			errno = EOPNOTSUPP;
> @@ -589,7 +607,7 @@ static int nfs_sys_mount(struct nfsmount_info *mi, struct mount_options *opts)
> }
> 
> static int nfs_do_mount_v3v2(struct nfsmount_info *mi,
> -		struct sockaddr *sap, socklen_t salen)
> +			     struct sockaddr *sap, socklen_t salen)
> {
> 	struct mount_options *options = po_dup(mi->options);
> 	int result = 0;
> @@ -631,7 +649,7 @@ static int nfs_do_mount_v3v2(struct nfsmount_info *mi,
> 		printf(_("%s: trying text-based options '%s'\n"),
> 			progname, *mi->extra_opts);
> 
> -	if (!nfs_rewrite_pmap_mount_options(options))
> +	if (!nfs_rewrite_pmap_mount_options(options, mi->local_ip))
> 		goto out_fail;
> 
> 	result = nfs_sys_mount(mi, options);
> @@ -1039,6 +1057,7 @@ int nfsmount_string(const char *spec, const char *node, const char *type,
> 		.flags		= flags,
> 		.fake		= fake,
> 		.child		= child,
> +		.local_ip	= NULL,
> 	};
> 	int retval = EX_FAIL;
> 
> @@ -1051,5 +1070,7 @@ int nfsmount_string(const char *spec, const char *node, const char *type,
> 
> 	freeaddrinfo(mi.address);
> 	free(mi.hostname);
> +	if (mi.local_ip)
> +		free(mi.local_ip);

Nit: free(3) works when passed NULL, you don't need the extra "if (mi.local_ip)" in front of it.

> 	return retval;
> }
> -- 
> 1.7.3.4
> 
> --
> 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

-- 
Chuck Lever
chuck[dot]lever[at]oracle[dot]com





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 3/6] nfs-utils:  Implement srcaddr binding in rpc_socket
  2011-06-10 22:06   ` Chuck Lever
@ 2011-06-10 22:19     ` Ben Greear
  2011-06-10 22:37       ` Chuck Lever
  0 siblings, 1 reply; 15+ messages in thread
From: Ben Greear @ 2011-06-10 22:19 UTC (permalink / raw)
  To: Chuck Lever; +Cc: linux-nfs

On 06/10/2011 03:06 PM, Chuck Lever wrote:
>
> On Jun 10, 2011, at 5:08 PM, greearb@candelatech.com wrote:
>
>> From: Ben Greear<greearb@candelatech.com>
>>
>> This implements the actual binding, if we are passed
>> a non-null local_ip structure.
>
> Why not _always_ pass a valid local_ip structure, and simply set .addr to an appropriate ANYADDR by default?  Then .is_set wouldn't be necessary, would it?  It would also simplify the logic in nfs_validate_options().

I like it as is because almost none of the new code is actually
used unless users pass in the srcaddr= option.  So, if I *did*
introduce any bugs, hopefully they would be limited to users
of the new option, and not a real regression.

Maybe after the srcaddr= code is used a bit I could go back and
do that cleanup.

But, I don't feel strongly about it, so if you think it's
worth the bother, I'll try changing the code as you suggest.

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 4/6] nfs-utils:  Support srcaddr=n option for string mount.
  2011-06-10 22:07   ` Chuck Lever
@ 2011-06-10 22:30     ` Ben Greear
  2011-06-10 22:35       ` Chuck Lever
  2011-06-13 20:37     ` Steve Dickson
  1 sibling, 1 reply; 15+ messages in thread
From: Ben Greear @ 2011-06-10 22:30 UTC (permalink / raw)
  To: Chuck Lever; +Cc: linux-nfs

On 06/10/2011 03:07 PM, Chuck Lever wrote:
>
> On Jun 10, 2011, at 5:08 PM, greearb@candelatech.com wrote:
>
>> From: Ben Greear<greearb@candelatech.com>
>>
>> Look for and parse the srcaddr=n argument.  If parsing
>> succeeds, pass this down the call chain.  This fully
>> implements binding to a specified source address when
>> mounting.

>> +		if (!local_ip->is_set) {
>> +			free(local_ip);
>> +			return 0;
>> +		}
>> +		mi->local_ip = local_ip;
>> +	}
>
> I'm wondering what kind of sanity checking is done on the srcaddr value.
>
> 1.  Do we verify that srcaddr == clientaddr?

No, and I'm not sure we should.  If they are specifying
both srcaddr and clientaddr, they are already in the rarely-used-options
category, so maybe they know what they are doing.

And, if it clientaddr is automatically figured out by
the kernel, then I think it must necessarily always be
srcaddr.

Makes me wonder though..could you do some sort of lame security
violation by making clientaddr some third-party IP?

>
> 2.  Do we verify that srcaddr.sa_family == addr.sa_family ?

Not directly, but it will blow up in the bind() call if you
try it:

strace -f mount -t nfs [2002::100:157]:/rpool/ben /mnt/lf/znfs36-sol-1 -o srcaddr=192.168.100.117,vers=3
...
[pid  1488] munmap(0x7f0cd7b20000, 4096) = 0
[pid  1488] socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP) = 3
[pid  1488] bind(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.100.117")}, 16) = -1 EINVAL (Invalid argument)

[root@ice-si-dmz fileio]# mount -t nfs [2002::100:157]:/rpool/ben /mnt/lf/znfs36-sol-1 -o srcaddr=192.168.100.117,vers=3
mount.nfs: an incorrect mount option was specified

That sufficient you think?

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 4/6] nfs-utils:  Support srcaddr=n option for string mount.
  2011-06-10 22:30     ` Ben Greear
@ 2011-06-10 22:35       ` Chuck Lever
  0 siblings, 0 replies; 15+ messages in thread
From: Chuck Lever @ 2011-06-10 22:35 UTC (permalink / raw)
  To: Ben Greear; +Cc: linux-nfs


On Jun 10, 2011, at 6:30 PM, Ben Greear wrote:

> On 06/10/2011 03:07 PM, Chuck Lever wrote:
>> 
>> On Jun 10, 2011, at 5:08 PM, greearb@candelatech.com wrote:
>> 
>>> From: Ben Greear<greearb@candelatech.com>
>>> 
>>> Look for and parse the srcaddr=n argument.  If parsing
>>> succeeds, pass this down the call chain.  This fully
>>> implements binding to a specified source address when
>>> mounting.
> 
>>> +		if (!local_ip->is_set) {
>>> +			free(local_ip);
>>> +			return 0;
>>> +		}
>>> +		mi->local_ip = local_ip;
>>> +	}
>> 
>> I'm wondering what kind of sanity checking is done on the srcaddr value.
>> 
>> 1.  Do we verify that srcaddr == clientaddr?
> 
> No, and I'm not sure we should.  If they are specifying
> both srcaddr and clientaddr, they are already in the rarely-used-options
> category, so maybe they know what they are doing.
> 
> And, if it clientaddr is automatically figured out by
> the kernel, then I think it must necessarily always be
> srcaddr.

Today the kernel doesn't automatically figure out a value for clientaddr=, that value is provided by the mount.nfs command.  I guess no harm is done if they are different, but you probably want to remove any comments or other documentation that suggests that is bad.  Maybe you've already done that.

> Makes me wonder though..could you do some sort of lame security
> violation by making clientaddr some third-party IP?
> 
>> 
>> 2.  Do we verify that srcaddr.sa_family == addr.sa_family ?
> 
> Not directly, but it will blow up in the bind() call if you
> try it:
> 
> strace -f mount -t nfs [2002::100:157]:/rpool/ben /mnt/lf/znfs36-sol-1 -o srcaddr=192.168.100.117,vers=3
> ...
> [pid  1488] munmap(0x7f0cd7b20000, 4096) = 0
> [pid  1488] socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP) = 3
> [pid  1488] bind(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("192.168.100.117")}, 16) = -1 EINVAL (Invalid argument)
> 
> [root@ice-si-dmz fileio]# mount -t nfs [2002::100:157]:/rpool/ben /mnt/lf/znfs36-sol-1 -o srcaddr=192.168.100.117,vers=3
> mount.nfs: an incorrect mount option was specified
> 
> That sufficient you think?

I think it would be more helpful to admins if mount.nfs were more explicit about the problem.

-- 
Chuck Lever
chuck[dot]lever[at]oracle[dot]com





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 3/6] nfs-utils:  Implement srcaddr binding in rpc_socket
  2011-06-10 22:19     ` Ben Greear
@ 2011-06-10 22:37       ` Chuck Lever
  2011-06-10 22:50         ` Ben Greear
  0 siblings, 1 reply; 15+ messages in thread
From: Chuck Lever @ 2011-06-10 22:37 UTC (permalink / raw)
  To: Ben Greear; +Cc: linux-nfs


On Jun 10, 2011, at 6:19 PM, Ben Greear wrote:

> On 06/10/2011 03:06 PM, Chuck Lever wrote:
>> 
>> On Jun 10, 2011, at 5:08 PM, greearb@candelatech.com wrote:
>> 
>>> From: Ben Greear<greearb@candelatech.com>
>>> 
>>> This implements the actual binding, if we are passed
>>> a non-null local_ip structure.
>> 
>> Why not _always_ pass a valid local_ip structure, and simply set .addr to an appropriate ANYADDR by default?  Then .is_set wouldn't be necessary, would it?  It would also simplify the logic in nfs_validate_options().
> 
> I like it as is because almost none of the new code is actually
> used unless users pass in the srcaddr= option.  So, if I *did*
> introduce any bugs, hopefully they would be limited to users
> of the new option, and not a real regression.

It should be pretty obvious if something here breaks.

> Maybe after the srcaddr= code is used a bit I could go back and
> do that cleanup.
> 
> But, I don't feel strongly about it, so if you think it's
> worth the bother, I'll try changing the code as you suggest.

In the long-term, if my suggestion works out, this code would be simpler, and to me that's better than the risk of a little short-term instability.

-- 
Chuck Lever
chuck[dot]lever[at]oracle[dot]com





^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 3/6] nfs-utils:  Implement srcaddr binding in rpc_socket
  2011-06-10 22:37       ` Chuck Lever
@ 2011-06-10 22:50         ` Ben Greear
  0 siblings, 0 replies; 15+ messages in thread
From: Ben Greear @ 2011-06-10 22:50 UTC (permalink / raw)
  To: Chuck Lever; +Cc: linux-nfs

On 06/10/2011 03:37 PM, Chuck Lever wrote:
>
> On Jun 10, 2011, at 6:19 PM, Ben Greear wrote:
>
>> On 06/10/2011 03:06 PM, Chuck Lever wrote:
>>>
>>> On Jun 10, 2011, at 5:08 PM, greearb@candelatech.com wrote:
>>>
>>>> From: Ben Greear<greearb@candelatech.com>
>>>>
>>>> This implements the actual binding, if we are passed
>>>> a non-null local_ip structure.
>>>
>>> Why not _always_ pass a valid local_ip structure, and simply set .addr to an appropriate ANYADDR by default?  Then .is_set wouldn't be necessary, would it?  It would also simplify the logic in nfs_validate_options().
>>
>> I like it as is because almost none of the new code is actually
>> used unless users pass in the srcaddr= option.  So, if I *did*
>> introduce any bugs, hopefully they would be limited to users
>> of the new option, and not a real regression.
>
> It should be pretty obvious if something here breaks.
>
>> Maybe after the srcaddr= code is used a bit I could go back and
>> do that cleanup.
>>
>> But, I don't feel strongly about it, so if you think it's
>> worth the bother, I'll try changing the code as you suggest.
>
> In the long-term, if my suggestion works out, this code would be simpler, and to me that's better than the risk of a little short-term instability.

Do you mean always make sure it is not NULL as well?

That would complicate code everywhere I currently pass NULL in for local_ip
(like in methods that don't care about binding, non stropts logic, etc).
I think that would cause more harm than good.

I could add return value to the parse method instead of relying on
is_set (and just pass in NULL instead of &local_ip if we didn't have the srcaddr=
option) if you think that is cleaner, but I don't think it will simplify things very
much...

Thanks,
Ben


-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v3 4/6] nfs-utils:  Support srcaddr=n option for string mount.
  2011-06-10 22:07   ` Chuck Lever
  2011-06-10 22:30     ` Ben Greear
@ 2011-06-13 20:37     ` Steve Dickson
  1 sibling, 0 replies; 15+ messages in thread
From: Steve Dickson @ 2011-06-13 20:37 UTC (permalink / raw)
  To: Chuck Lever; +Cc: greearb, linux-nfs



On 06/10/2011 06:07 PM, Chuck Lever wrote:
> 
> On Jun 10, 2011, at 5:08 PM, greearb@candelatech.com wrote:
> 
>> From: Ben Greear <greearb@candelatech.com>
>>
>> Look for and parse the srcaddr=n argument.  If parsing
>> succeeds, pass this down the call chain.  This fully
>> implements binding to a specified source address when
>> mounting.
>>
>> Signed-off-by: Ben Greear <greearb@candelatech.com>
>> ---
>> :100644 100644 71417df... aba4252... M	utils/mount/stropts.c
>> utils/mount/stropts.c |   29 +++++++++++++++++++++++++----
>> 1 files changed, 25 insertions(+), 4 deletions(-)
>>
>> diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
>> index 71417df..aba4252 100644
>> --- a/utils/mount/stropts.c
>> +++ b/utils/mount/stropts.c
>> @@ -92,6 +92,7 @@ struct nfsmount_info {
>> 	int			flags,		/* MS_ flags */
>> 				fake,		/* actually do the mount? */
>> 				child;		/* forked bg child? */
>> +	struct local_bind_info  *local_ip;      /* Local IP binding info */
>> };
>>
>> #ifdef MOUNT_CONFIG
>> @@ -345,6 +346,7 @@ static int nfs_validate_options(struct nfsmount_info *mi)
>> 	};
>> 	sa_family_t family;
>> 	int error;
>> +	char *option;
>>
>> 	if (!nfs_parse_devname(mi->spec, &mi->hostname, NULL))
>> 		return 0;
>> @@ -371,6 +373,20 @@ static int nfs_validate_options(struct nfsmount_info *mi)
>> 					mi->address->ai_addrlen, mi->options))
>> 		return 0;
>>
>> +	option = po_get(mi->options, "srcaddr");
>> +	if (option) {
>> +		struct local_bind_info *local_ip;
>> +		local_ip = malloc(sizeof(*local_ip));
>> +		memset(local_ip, 0, sizeof(*local_ip));
>> +		parse_local_bind(local_ip, option);
> 
> Nit: Steve may not agree with this, possibly, but it is better IMO if we name new functions like parse_local_bind() with an nfs_ prefix so that, when debugging, we can immediately tell in a backtrace what functions are in mount.nfs and which are in a system library.
I do agree... We might as well stay with the naming convention
that already been established... 

steved.
 
> 
>> +
>> +		if (!local_ip->is_set) {
>> +			free(local_ip);
>> +			return 0;
>> +		}
>> +		mi->local_ip = local_ip;
>> +	}
> 
> I'm wondering what kind of sanity checking is done on the srcaddr value.
> 
> 1.  Do we verify that srcaddr == clientaddr?
> 
> 2.  Do we verify that srcaddr.sa_family == addr.sa_family ?
> 
>> +
>> 	return 1;
>> }
>>
>> @@ -484,7 +500,8 @@ static int nfs_construct_new_options(struct mount_options *options,
>>  * FALSE is returned if some failure occurred.
>>  */
>> static int
>> -nfs_rewrite_pmap_mount_options(struct mount_options *options)
>> +nfs_rewrite_pmap_mount_options(struct mount_options *options,
>> +			       struct local_bind_info *local_ip)
>> {
>> 	union nfs_sockaddr nfs_address;
>> 	struct sockaddr *nfs_saddr = &nfs_address.sa;
>> @@ -534,7 +551,8 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options)
>> 	 * negotiate.  Bail now if we can't contact it.
>> 	 */
>> 	if (!nfs_probe_bothports(mnt_saddr, mnt_salen, &mnt_pmap,
>> -				 nfs_saddr, nfs_salen, &nfs_pmap, NULL)) {
>> +				 nfs_saddr, nfs_salen, &nfs_pmap,
>> +				 local_ip)) {
>> 		errno = ESPIPE;
>> 		if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED)
>> 			errno = EOPNOTSUPP;
>> @@ -589,7 +607,7 @@ static int nfs_sys_mount(struct nfsmount_info *mi, struct mount_options *opts)
>> }
>>
>> static int nfs_do_mount_v3v2(struct nfsmount_info *mi,
>> -		struct sockaddr *sap, socklen_t salen)
>> +			     struct sockaddr *sap, socklen_t salen)
>> {
>> 	struct mount_options *options = po_dup(mi->options);
>> 	int result = 0;
>> @@ -631,7 +649,7 @@ static int nfs_do_mount_v3v2(struct nfsmount_info *mi,
>> 		printf(_("%s: trying text-based options '%s'\n"),
>> 			progname, *mi->extra_opts);
>>
>> -	if (!nfs_rewrite_pmap_mount_options(options))
>> +	if (!nfs_rewrite_pmap_mount_options(options, mi->local_ip))
>> 		goto out_fail;
>>
>> 	result = nfs_sys_mount(mi, options);
>> @@ -1039,6 +1057,7 @@ int nfsmount_string(const char *spec, const char *node, const char *type,
>> 		.flags		= flags,
>> 		.fake		= fake,
>> 		.child		= child,
>> +		.local_ip	= NULL,
>> 	};
>> 	int retval = EX_FAIL;
>>
>> @@ -1051,5 +1070,7 @@ int nfsmount_string(const char *spec, const char *node, const char *type,
>>
>> 	freeaddrinfo(mi.address);
>> 	free(mi.hostname);
>> +	if (mi.local_ip)
>> +		free(mi.local_ip);
> 
> Nit: free(3) works when passed NULL, you don't need the extra "if (mi.local_ip)" in front of it.
> 
>> 	return retval;
>> }
>> -- 
>> 1.7.3.4
>>
>> --
>> 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
> 

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2011-06-13 20:37 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-10 21:08 [PATCH v3 0/6] nfs-utils: Support binding to source address greearb
2011-06-10 21:08 ` [PATCH v3 1/6] nfs-utils: Add structure for passing local binding info greearb
2011-06-10 21:08 ` [PATCH v3 2/6] nfs-utils: Add patch to parse srcaddr= option greearb
2011-06-10 21:08 ` [PATCH v3 3/6] nfs-utils: Implement srcaddr binding in rpc_socket greearb
2011-06-10 22:06   ` Chuck Lever
2011-06-10 22:19     ` Ben Greear
2011-06-10 22:37       ` Chuck Lever
2011-06-10 22:50         ` Ben Greear
2011-06-10 21:08 ` [PATCH v3 4/6] nfs-utils: Support srcaddr=n option for string mount greearb
2011-06-10 22:07   ` Chuck Lever
2011-06-10 22:30     ` Ben Greear
2011-06-10 22:35       ` Chuck Lever
2011-06-13 20:37     ` Steve Dickson
2011-06-10 21:08 ` [PATCH v3 5/6] nfs-utils: Implement srcaddr=n binding for unmount greearb
2011-06-10 21:08 ` [PATCH v3 6/6] nfs-utils: Update man page for srcaddr= option greearb

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.