* [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
* 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 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 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
* [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
* 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 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 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
* [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
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 a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).