SUNRPC: Ensure IPV6_V6ONLY is set on the socket before binding to a port

Also ensure that we use the protocol family instead of the address
family when calling sock_create_kern().

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index ac6cd652..9d50423 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1110,7 +1110,6 @@
 	struct svc_sock	*svsk;
 	struct sock	*inet;
 	int		pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
-	int		val;
 
 	dprintk("svc: svc_setup_socket %p\n", sock);
 	if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) {
@@ -1143,16 +1142,6 @@
 	else
 		svc_tcp_init(svsk, serv);
 
-	/*
-	 * If this is a PF_INET6 listener, we want to avoid
-	 * getting requests from IPv4 remotes.  Those should
-	 * be shunted to a PF_INET listener via rpcbind.
-	 */
-	val = 1;
-	if (inet->sk_family == PF_INET6)
-		kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY,
-					(char *)&val, sizeof(val));
-
 	dprintk("svc: svc_setup_socket created %p (inet %p)\n",
 				svsk, svsk->sk_sk);
 
@@ -1220,6 +1209,8 @@
 	struct sockaddr_storage addr;
 	struct sockaddr *newsin = (struct sockaddr *)&addr;
 	int		newlen;
+	int		family;
+	int		val;
 	RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
 
 	dprintk("svc: svc_create_socket(%s, %d, %s)\n",
@@ -1231,14 +1222,35 @@
 				"sockets supported\n");
 		return ERR_PTR(-EINVAL);
 	}
-	type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
 
-	error = sock_create_kern(sin->sa_family, type, protocol, &sock);
+	type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
+	switch (sin->sa_family) {
+	case AF_INET6:
+		family = PF_INET6;
+		break;
+	case AF_INET:
+		family = PF_INET;
+		break;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	error = sock_create_kern(family, type, protocol, &sock);
 	if (error < 0)
 		return ERR_PTR(error);
 
 	svc_reclassify_socket(sock);
 
+	/*
+	 * If this is an PF_INET6 listener, we want to avoid
+	 * getting requests from IPv4 remotes.  Those should
+	 * be shunted to a PF_INET listener via rpcbind.
+	 */
+	val = 1;
+	if (family == PF_INET6)
+		kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY,
+					(char *)&val, sizeof(val));
+
 	if (type == SOCK_STREAM)
 		sock->sk->sk_reuse = 1;		/* allow address reuse */
 	error = kernel_bind(sock, sin, len);