Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=d5b6443014940eb83788161c69b17cb7a1ffaaed
Commit:     d5b6443014940eb83788161c69b17cb7a1ffaaed
Parent:     4b6473fba4e832ee1d15737bc38779501c349a61
Author:     Chuck Lever <[EMAIL PROTECTED]>
AuthorDate: Mon Aug 6 11:57:18 2007 -0400
Committer:  Trond Myklebust <[EMAIL PROTECTED]>
CommitDate: Tue Oct 9 17:16:02 2007 -0400

    SUNRPC: add support for IPv6 to the kernel's rpcbind client
    
    Prepare for adding IPv6 support to the RPC client by adding IPv6
    capabilities to rpcbind.  Note that this is support on the query side
    only; registering IPv6 addresses with the local portmapper will come
    later.
    
    Note we have to take care not to fall back to using version 2 of the
    rpcbind protocol if we're dealing with IPv6 address.  Version 2 doesn't
    support IPv6 at all.
    
    Signed-off-by: Chuck Lever <[EMAIL PROTECTED]>
    Cc: Aurelien Charbon <[EMAIL PROTECTED]>
    Signed-off-by: Trond Myklebust <[EMAIL PROTECTED]>
---
 net/sunrpc/rpcb_clnt.c |   51 ++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index a9d2cdc..7db75e1 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -16,6 +16,8 @@
 
 #include <linux/types.h>
 #include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/in6.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 
@@ -137,10 +139,13 @@ struct rpcbind_args {
 static struct rpc_procinfo rpcb_procedures2[];
 static struct rpc_procinfo rpcb_procedures3[];
 
-static struct rpcb_info {
+struct rpcb_info {
        int                     rpc_vers;
        struct rpc_procinfo *   rpc_proc;
-} rpcb_next_version[];
+};
+
+static struct rpcb_info rpcb_next_version[];
+static struct rpcb_info rpcb_next_version6[];
 
 static void rpcb_getport_prepare(struct rpc_task *task, void *calldata)
 {
@@ -190,7 +195,17 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct 
sockaddr *srvaddr,
                                   RPC_CLNT_CREATE_INTR),
        };
 
-       ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
+       switch (srvaddr->sa_family) {
+       case AF_INET:
+               ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
+               break;
+       case AF_INET6:
+               ((struct sockaddr_in6 *)srvaddr)->sin6_port = 
htons(RPCBIND_PORT);
+               break;
+       default:
+               return NULL;
+       }
+
        if (!privileged)
                args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
        return rpc_create(&args);
@@ -316,6 +331,7 @@ void rpcb_getport_async(struct rpc_task *task)
        struct rpc_task *child;
        struct sockaddr addr;
        int status;
+       struct rpcb_info *info;
 
        dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
                task->tk_pid, __FUNCTION__,
@@ -343,14 +359,30 @@ void rpcb_getport_async(struct rpc_task *task)
                goto bailout_nofree;
        }
 
-       if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) {
+       rpc_peeraddr(clnt, (void *)&addr, sizeof(addr));
+
+       /* Don't ever use rpcbind v2 for AF_INET6 requests */
+       switch (addr.sa_family) {
+       case AF_INET:
+               info = rpcb_next_version;
+               break;
+       case AF_INET6:
+               info = rpcb_next_version6;
+               break;
+       default:
+               status = -EAFNOSUPPORT;
+               dprintk("RPC: %5u %s: bad address family\n",
+                               task->tk_pid, __FUNCTION__);
+               goto bailout_nofree;
+       }
+       if (info[xprt->bind_index].rpc_proc == NULL) {
                xprt->bind_index = 0;
                status = -EACCES;       /* tell caller to try again later */
                dprintk("RPC: %5u %s: no more getport versions available\n",
                        task->tk_pid, __FUNCTION__);
                goto bailout_nofree;
        }
-       bind_version = rpcb_next_version[xprt->bind_index].rpc_vers;
+       bind_version = info[xprt->bind_index].rpc_vers;
 
        dprintk("RPC: %5u %s: trying rpcbind version %u\n",
                task->tk_pid, __FUNCTION__, bind_version);
@@ -373,7 +405,6 @@ void rpcb_getport_async(struct rpc_task *task)
                        sizeof(map->r_addr));
        map->r_owner = RPCB_OWNER_STRING;       /* ignored for GETADDR */
 
-       rpc_peeraddr(clnt, (void *)&addr, sizeof(addr));
        rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, 
bind_version, 0);
        if (IS_ERR(rpcb_clnt)) {
                status = PTR_ERR(rpcb_clnt);
@@ -594,6 +625,14 @@ static struct rpcb_info rpcb_next_version[] = {
        { 0, NULL },
 };
 
+static struct rpcb_info rpcb_next_version6[] = {
+#ifdef CONFIG_SUNRPC_BIND34
+       { 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] },
+       { 3, &rpcb_procedures3[RPCBPROC_GETADDR] },
+#endif
+       { 0, NULL },
+};
+
 static struct rpc_version rpcb_version2 = {
        .number         = 2,
        .nrprocs        = RPCB_HIGHPROC_2,
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to