From: Ben Greear <greearb@candelatech.com>
To: Chuck Lever <chuck.lever@oracle.com>
Cc: linux-nfs@vger.kernel.org, Patrick McHardy <kaber@trash.net>
Subject: Re: PATCH: Support binding to a local IPv4 address when mounting a server.
Date: Fri, 20 Feb 2009 23:43:07 -0800 [thread overview]
Message-ID: <499FB08B.1070200@candelatech.com> (raw)
In-Reply-To: <65D69956-DB67-43A7-9101-9AFB7EC55A9F@oracle.com>
[-- Attachment #1: Type: text/plain, Size: 578 bytes --]
I re-worked the kernel nfs local-address-binding logic against
2.6.29-rc5. In quick testing,
this works with IPv4 and NFSv3 at least. I changed the attribute to be
called 'bindaddr'
as previously suggested.
I didn't actually make any further changes to the mount.nfs tool and it
took the bindaddr=a.b.c.d
just fine, so maybe there are no changes at all needed in user-space.
Comments & suggestions welcome.
Thanks,
Ben
Signed-Off-By: Ben Greear<greearb@candelatech.com>
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
[-- Attachment #2: nfs_bind.patch --]
[-- Type: text/x-patch, Size: 10272 bytes --]
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 3e634f2..1c7011e 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -213,7 +213,7 @@ static int nfs_callback_authenticate(struct svc_rqst *rqstp)
int ret = SVC_OK;
/* Don't talk to strangers */
- clp = nfs_find_client(svc_addr(rqstp), 4);
+ clp = nfs_find_client(svc_daddr(rqstp), svc_addr(rqstp), 4);
if (clp == NULL)
return SVC_DROP;
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index bb25d21..94fd8b4 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -39,6 +39,7 @@ struct cb_compound_hdr_res {
struct cb_getattrargs {
struct sockaddr *addr;
+ struct sockaddr *bindaddr;
struct nfs_fh fh;
uint32_t bitmap[2];
};
@@ -54,6 +55,7 @@ struct cb_getattrres {
struct cb_recallargs {
struct sockaddr *addr;
+ struct sockaddr *bindaddr;
struct nfs_fh fh;
nfs4_stateid stateid;
uint32_t truncate;
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index f7e83e2..cd75849 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -25,7 +25,7 @@ __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *
res->bitmap[0] = res->bitmap[1] = 0;
res->status = htonl(NFS4ERR_BADHANDLE);
- clp = nfs_find_client(args->addr, 4);
+ clp = nfs_find_client(args->bindaddr, args->addr, 4);
if (clp == NULL)
goto out;
@@ -68,7 +68,7 @@ __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy)
__be32 res;
res = htonl(NFS4ERR_BADHANDLE);
- clp = nfs_find_client(args->addr, 4);
+ clp = nfs_find_client(args->bindaddr, args->addr, 4);
if (clp == NULL)
goto out;
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index dd0ef34..a342e8e 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -177,6 +177,7 @@ static __be32 decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr
if (unlikely(status != 0))
goto out;
args->addr = svc_addr(rqstp);
+ args->bindaddr = svc_daddr(rqstp);
status = decode_bitmap(xdr, args->bitmap);
out:
dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
@@ -189,6 +190,7 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr,
__be32 status;
args->addr = svc_addr(rqstp);
+ args->bindaddr = svc_daddr(rqstp);
status = decode_stateid(xdr, &args->stateid);
if (unlikely(status != 0))
goto out;
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 9b728f3..6cd8bd5 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -98,6 +98,7 @@ struct rpc_program nfsacl_program = {
struct nfs_client_initdata {
const char *hostname;
const struct sockaddr *addr;
+ const struct sockaddr *bindaddr;
size_t addrlen;
const struct nfs_rpc_ops *rpc_ops;
int proto;
@@ -130,7 +131,8 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
memcpy(&clp->cl_addr, cl_init->addr, cl_init->addrlen);
clp->cl_addrlen = cl_init->addrlen;
-
+ memcpy(&clp->bindaddr, cl_init->bindaddr, cl_init->addrlen);
+
if (cl_init->hostname) {
clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL);
if (!clp->cl_hostname)
@@ -276,7 +278,8 @@ static int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
* Find a client by IP address and protocol version
* - returns NULL if no such client
*/
-struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
+struct nfs_client *nfs_find_client(const struct sockaddr *bindaddr,
+ const struct sockaddr *addr, u32 nfsversion)
{
struct nfs_client *clp;
@@ -293,6 +296,8 @@ struct nfs_client *nfs_find_client(const struct sockaddr *addr, u32 nfsversion)
continue;
/* Match only the IP address, not the port number */
+ if (!nfs_sockaddr_match_ipaddr(bindaddr, (const struct sockaddr*)(&clp->bindaddr)))
+ continue;
if (!nfs_sockaddr_match_ipaddr(addr, clap))
continue;
@@ -357,6 +362,11 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
if (clp->cl_proto != data->proto)
continue;
+ /* Check to make sure local-IP bindings match, but just the IP-addr. */
+ if (!nfs_sockaddr_match_ipaddr((const struct sockaddr*)(&clp->bindaddr),
+ data->bindaddr))
+ continue;
+
/* Match the full socket address */
if (memcmp(&clp->cl_addr, data->addr, sizeof(clp->cl_addr)) != 0)
continue;
@@ -493,6 +503,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
struct rpc_clnt *clnt = NULL;
struct rpc_create_args args = {
.protocol = clp->cl_proto,
+ .saddress = (struct sockaddr *)&clp->bindaddr,
.address = (struct sockaddr *)&clp->cl_addr,
.addrsize = clp->cl_addrlen,
.timeout = timeparms,
@@ -670,6 +681,7 @@ static int nfs_init_server(struct nfs_server *server,
.hostname = data->nfs_server.hostname,
.addr = (const struct sockaddr *)&data->nfs_server.address,
.addrlen = data->nfs_server.addrlen,
+ .bindaddr = (const struct sockaddr *)&data->bindaddr.address,
.rpc_ops = &nfs_v2_clientops,
.proto = data->nfs_server.protocol,
};
@@ -1035,6 +1047,7 @@ static int nfs4_set_client(struct nfs_server *server,
const struct sockaddr *addr,
const size_t addrlen,
const char *ip_addr,
+ const struct sockaddr* bindaddr,
rpc_authflavor_t authflavour,
int proto, const struct rpc_timeout *timeparms)
{
@@ -1042,6 +1055,7 @@ static int nfs4_set_client(struct nfs_server *server,
.hostname = hostname,
.addr = addr,
.addrlen = addrlen,
+ .bindaddr = bindaddr,
.rpc_ops = &nfs_v4_clientops,
.proto = proto,
};
@@ -1096,6 +1110,7 @@ static int nfs4_init_server(struct nfs_server *server,
(const struct sockaddr *)&data->nfs_server.address,
data->nfs_server.addrlen,
data->client_address,
+ (const struct sockaddr *)&data->bindaddr.address,
data->auth_flavors[0],
data->nfs_server.protocol,
&timeparms);
@@ -1214,6 +1229,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
data->addr,
data->addrlen,
parent_client->cl_ipaddr,
+ (const struct sockaddr *)(&parent_client->bindaddr),
data->authflavor,
parent_server->client->cl_xprt->prot,
parent_server->client->cl_timeout);
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 340ede8..330d10f 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -41,6 +41,12 @@ struct nfs_parsed_mount_data {
unsigned int auth_flavor_len;
rpc_authflavor_t auth_flavors[1];
char *client_address;
+
+ struct {
+ struct sockaddr_storage address;
+ size_t addrlen;
+ char *hostname;
+ } bindaddr;
struct {
struct sockaddr_storage address;
@@ -66,6 +72,7 @@ struct nfs_parsed_mount_data {
/* mount_clnt.c */
struct nfs_mount_request {
struct sockaddr *sap;
+ struct sockaddr *bindaddr;
size_t salen;
char *hostname;
char *dirpath;
@@ -81,7 +88,8 @@ extern int nfs_mount(struct nfs_mount_request *info);
extern struct rpc_program nfs_program;
extern void nfs_put_client(struct nfs_client *);
-extern struct nfs_client *nfs_find_client(const struct sockaddr *, u32);
+extern struct nfs_client *nfs_find_client(const struct sockaddr *,
+ const struct sockaddr *, u32);
extern struct nfs_client *nfs_find_client_next(struct nfs_client *);
extern struct nfs_server *nfs_create_server(
const struct nfs_parsed_mount_data *,
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index ca905a5..89acb0c 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -44,6 +44,7 @@ int nfs_mount(struct nfs_mount_request *info)
};
struct rpc_create_args args = {
.protocol = info->protocol,
+ .saddress = info->bindaddr,
.address = info->sap,
.addrsize = info->salen,
.servername = info->hostname,
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index d6686f4..90f29bd 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -91,7 +91,7 @@ enum {
/* Mount options that take string arguments */
Opt_sec, Opt_proto, Opt_mountproto, Opt_mounthost,
- Opt_addr, Opt_mountaddr, Opt_clientaddr,
+ Opt_addr, Opt_mountaddr, Opt_clientaddr, Opt_bindaddr,
Opt_lookupcache,
/* Special mount options */
@@ -155,6 +155,7 @@ static const match_table_t nfs_mount_option_tokens = {
{ Opt_mountproto, "mountproto=%s" },
{ Opt_addr, "addr=%s" },
{ Opt_clientaddr, "clientaddr=%s" },
+ { Opt_bindaddr, "bindaddr=%s" },
{ Opt_mounthost, "mounthost=%s" },
{ Opt_mountaddr, "mountaddr=%s" },
@@ -563,6 +564,15 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
if (clp->rpc_ops->version == 4)
seq_printf(m, ",clientaddr=%s", clp->cl_ipaddr);
#endif
+
+ if (clp->bindaddr.ss_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(&clp->bindaddr);
+ seq_printf(m, ",bindaddr=%pI6", &sin6->sin6_addr);
+ }
+ else {
+ struct sockaddr_in *sin = (struct sockaddr_in *)(&clp->bindaddr);
+ seq_printf(m, ",bindaddr=%pI4", &sin->sin_addr.s_addr);
+ }
}
/*
@@ -1251,6 +1261,16 @@ static int nfs_parse_mount_options(char *raw,
kfree(mnt->client_address);
mnt->client_address = string;
break;
+ case Opt_bindaddr:
+ string = match_strdup(args);
+ if (string == NULL)
+ goto out_nomem;
+ nfs_parse_ip_address(string, strlen(string),
+ (struct sockaddr *)&mnt->bindaddr.address,
+ &mnt->bindaddr.addrlen);
+ kfree(mnt->bindaddr.hostname);
+ mnt->bindaddr.hostname = string;
+ break;
case Opt_mounthost:
string = match_strdup(args);
if (string == NULL)
@@ -1340,6 +1360,8 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
struct nfs_mount_request request = {
.sap = (struct sockaddr *)
&args->mount_server.address,
+ .bindaddr = (struct sockaddr *)&args->bindaddr.address,
+ .salen = args->mount_server.addrlen,
.dirpath = args->nfs_server.export_path,
.protocol = args->mount_server.protocol,
.fh = root_fh,
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 9bb81ae..ebe612f 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -64,6 +64,9 @@ struct nfs_client {
char cl_ipaddr[48];
unsigned char cl_id_uniquifier;
#endif
+
+ /* If we should bind to a local IP, it should be specified below. */
+ struct sockaddr_storage bindaddr;
};
/*
next prev parent reply other threads:[~2009-02-21 7:43 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-22 1:01 PATCH: Support binding to a local IPv4 address when mounting a server Ben Greear
2009-01-22 2:38 ` Chuck Lever
2009-01-22 5:35 ` Ben Greear
2009-01-22 17:06 ` Chuck Lever
2009-01-22 17:31 ` Ben Greear
2009-01-23 17:18 ` Chuck Lever
2009-01-23 17:39 ` Ben Greear
2009-02-21 7:43 ` Ben Greear [this message]
2009-02-21 17:16 ` Trond Myklebust
2009-02-21 22:09 ` Chuck Lever
2009-02-22 5:52 ` Ben Greear
2009-02-22 19:09 ` Trond Myklebust
[not found] ` <1235329791.7331.75.camel-rJ7iovZKK19ZJLDQqaL3InhyD016LWXt@public.gmane.org>
2009-02-22 20:29 ` Chuck Lever
2009-02-22 22:01 ` Trond Myklebust
2009-02-22 23:17 ` Ben Greear
2009-02-22 23:41 ` Trond Myklebust
[not found] ` <1235346094.7331.111.camel-rJ7iovZKK19ZJLDQqaL3InhyD016LWXt@public.gmane.org>
2009-02-22 23:45 ` Ben Greear
2009-02-22 6:24 ` Ben Greear
2009-02-22 20:01 ` Chuck Lever
2009-02-22 7:05 ` Ben Greear
-- strict thread matches above, loose matches on Subject: below --
2009-02-21 18:18 Ben Greear
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=499FB08B.1070200@candelatech.com \
--to=greearb@candelatech.com \
--cc=chuck.lever@oracle.com \
--cc=kaber@trash.net \
--cc=linux-nfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.