summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2007-08-06 11:57:33 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-10-09 17:16:10 -0400
commit90058d37c30ffce0e033ea3dcc6a539111483a58 (patch)
treebaed7764ac3c00bc27244aa58bb1465c6dd87989
parent7dc753f0391ad94868609376f37be4833671b57d (diff)
SUNRPC: create an IPv6-savvy mechanism for binding to a reserved port
Clone xs_bindresvport into two functions, one that can handle IPv4 addresses, and one that can handle IPv6 addresses. 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>
-rw-r--r--net/sunrpc/xprtsock.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index cd7c18b2452..8295ae28391 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1261,6 +1261,39 @@ static int xs_bind4(struct sock_xprt *transport, struct socket *sock)
return err;
}
+static int xs_bind6(struct sock_xprt *transport, struct socket *sock)
+{
+ struct sockaddr_in6 myaddr = {
+ .sin6_family = AF_INET6,
+ };
+ struct sockaddr_in6 *sa;
+ int err;
+ unsigned short port = transport->port;
+
+ if (!transport->xprt.resvport)
+ port = 0;
+ sa = (struct sockaddr_in6 *)&transport->addr;
+ myaddr.sin6_addr = sa->sin6_addr;
+ do {
+ myaddr.sin6_port = htons(port);
+ err = kernel_bind(sock, (struct sockaddr *) &myaddr,
+ sizeof(myaddr));
+ if (!transport->xprt.resvport)
+ break;
+ if (err == 0) {
+ transport->port = port;
+ break;
+ }
+ if (port <= xprt_min_resvport)
+ port = xprt_max_resvport;
+ else
+ port--;
+ } while (err == -EADDRINUSE && port != transport->port);
+ dprintk("RPC: xs_bind6 "NIP6_FMT":%u: %s (%d)\n",
+ NIP6(myaddr.sin6_addr), port, err ? "failed" : "ok", err);
+ return err;
+}
+
#ifdef CONFIG_DEBUG_LOCK_ALLOC
static struct lock_class_key xs_key[2];
static struct lock_class_key xs_slock_key[2];