aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/rpcb_clnt.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2007-08-06 11:57:18 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-10-09 17:16:02 -0400
commitd5b6443014940eb83788161c69b17cb7a1ffaaed (patch)
tree36ff07511b2c5548bb1e76298aa6050b7515ccee /net/sunrpc/rpcb_clnt.c
parent4b6473fba4e832ee1d15737bc38779501c349a61 (diff)
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 <chuck.lever@oracle.com> Cc: Aurelien Charbon <aurelien.charbon@ext.bull.net> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/rpcb_clnt.c')
-rw-r--r--net/sunrpc/rpcb_clnt.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index a9d2cdc8e32c..7db75e177e67 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -16,6 +16,8 @@
16 16
17#include <linux/types.h> 17#include <linux/types.h>
18#include <linux/socket.h> 18#include <linux/socket.h>
19#include <linux/in.h>
20#include <linux/in6.h>
19#include <linux/kernel.h> 21#include <linux/kernel.h>
20#include <linux/errno.h> 22#include <linux/errno.h>
21 23
@@ -137,10 +139,13 @@ struct rpcbind_args {
137static struct rpc_procinfo rpcb_procedures2[]; 139static struct rpc_procinfo rpcb_procedures2[];
138static struct rpc_procinfo rpcb_procedures3[]; 140static struct rpc_procinfo rpcb_procedures3[];
139 141
140static struct rpcb_info { 142struct rpcb_info {
141 int rpc_vers; 143 int rpc_vers;
142 struct rpc_procinfo * rpc_proc; 144 struct rpc_procinfo * rpc_proc;
143} rpcb_next_version[]; 145};
146
147static struct rpcb_info rpcb_next_version[];
148static struct rpcb_info rpcb_next_version6[];
144 149
145static void rpcb_getport_prepare(struct rpc_task *task, void *calldata) 150static void rpcb_getport_prepare(struct rpc_task *task, void *calldata)
146{ 151{
@@ -190,7 +195,17 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
190 RPC_CLNT_CREATE_INTR), 195 RPC_CLNT_CREATE_INTR),
191 }; 196 };
192 197
193 ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT); 198 switch (srvaddr->sa_family) {
199 case AF_INET:
200 ((struct sockaddr_in *)srvaddr)->sin_port = htons(RPCBIND_PORT);
201 break;
202 case AF_INET6:
203 ((struct sockaddr_in6 *)srvaddr)->sin6_port = htons(RPCBIND_PORT);
204 break;
205 default:
206 return NULL;
207 }
208
194 if (!privileged) 209 if (!privileged)
195 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; 210 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
196 return rpc_create(&args); 211 return rpc_create(&args);
@@ -316,6 +331,7 @@ void rpcb_getport_async(struct rpc_task *task)
316 struct rpc_task *child; 331 struct rpc_task *child;
317 struct sockaddr addr; 332 struct sockaddr addr;
318 int status; 333 int status;
334 struct rpcb_info *info;
319 335
320 dprintk("RPC: %5u %s(%s, %u, %u, %d)\n", 336 dprintk("RPC: %5u %s(%s, %u, %u, %d)\n",
321 task->tk_pid, __FUNCTION__, 337 task->tk_pid, __FUNCTION__,
@@ -343,14 +359,30 @@ void rpcb_getport_async(struct rpc_task *task)
343 goto bailout_nofree; 359 goto bailout_nofree;
344 } 360 }
345 361
346 if (rpcb_next_version[xprt->bind_index].rpc_proc == NULL) { 362 rpc_peeraddr(clnt, (void *)&addr, sizeof(addr));
363
364 /* Don't ever use rpcbind v2 for AF_INET6 requests */
365 switch (addr.sa_family) {
366 case AF_INET:
367 info = rpcb_next_version;
368 break;
369 case AF_INET6:
370 info = rpcb_next_version6;
371 break;
372 default:
373 status = -EAFNOSUPPORT;
374 dprintk("RPC: %5u %s: bad address family\n",
375 task->tk_pid, __FUNCTION__);
376 goto bailout_nofree;
377 }
378 if (info[xprt->bind_index].rpc_proc == NULL) {
347 xprt->bind_index = 0; 379 xprt->bind_index = 0;
348 status = -EACCES; /* tell caller to try again later */ 380 status = -EACCES; /* tell caller to try again later */
349 dprintk("RPC: %5u %s: no more getport versions available\n", 381 dprintk("RPC: %5u %s: no more getport versions available\n",
350 task->tk_pid, __FUNCTION__); 382 task->tk_pid, __FUNCTION__);
351 goto bailout_nofree; 383 goto bailout_nofree;
352 } 384 }
353 bind_version = rpcb_next_version[xprt->bind_index].rpc_vers; 385 bind_version = info[xprt->bind_index].rpc_vers;
354 386
355 dprintk("RPC: %5u %s: trying rpcbind version %u\n", 387 dprintk("RPC: %5u %s: trying rpcbind version %u\n",
356 task->tk_pid, __FUNCTION__, bind_version); 388 task->tk_pid, __FUNCTION__, bind_version);
@@ -373,7 +405,6 @@ void rpcb_getport_async(struct rpc_task *task)
373 sizeof(map->r_addr)); 405 sizeof(map->r_addr));
374 map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */ 406 map->r_owner = RPCB_OWNER_STRING; /* ignored for GETADDR */
375 407
376 rpc_peeraddr(clnt, (void *)&addr, sizeof(addr));
377 rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0); 408 rpcb_clnt = rpcb_create(clnt->cl_server, &addr, xprt->prot, bind_version, 0);
378 if (IS_ERR(rpcb_clnt)) { 409 if (IS_ERR(rpcb_clnt)) {
379 status = PTR_ERR(rpcb_clnt); 410 status = PTR_ERR(rpcb_clnt);
@@ -594,6 +625,14 @@ static struct rpcb_info rpcb_next_version[] = {
594 { 0, NULL }, 625 { 0, NULL },
595}; 626};
596 627
628static struct rpcb_info rpcb_next_version6[] = {
629#ifdef CONFIG_SUNRPC_BIND34
630 { 4, &rpcb_procedures4[RPCBPROC_GETVERSADDR] },
631 { 3, &rpcb_procedures3[RPCBPROC_GETADDR] },
632#endif
633 { 0, NULL },
634};
635
597static struct rpc_version rpcb_version2 = { 636static struct rpc_version rpcb_version2 = {
598 .number = 2, 637 .number = 2,
599 .nrprocs = RPCB_HIGHPROC_2, 638 .nrprocs = RPCB_HIGHPROC_2,