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>
This commit is contained in:
@@ -1110,7 +1110,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
|
|||||||
struct svc_sock *svsk;
|
struct svc_sock *svsk;
|
||||||
struct sock *inet;
|
struct sock *inet;
|
||||||
int pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
|
int pmap_register = !(flags & SVC_SOCK_ANONYMOUS);
|
||||||
int val;
|
|
||||||
|
|
||||||
dprintk("svc: svc_setup_socket %p\n", sock);
|
dprintk("svc: svc_setup_socket %p\n", sock);
|
||||||
if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) {
|
if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) {
|
||||||
@@ -1143,16 +1142,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
|
|||||||
else
|
else
|
||||||
svc_tcp_init(svsk, serv);
|
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",
|
dprintk("svc: svc_setup_socket created %p (inet %p)\n",
|
||||||
svsk, svsk->sk_sk);
|
svsk, svsk->sk_sk);
|
||||||
|
|
||||||
@@ -1220,6 +1209,8 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
|
|||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
struct sockaddr *newsin = (struct sockaddr *)&addr;
|
struct sockaddr *newsin = (struct sockaddr *)&addr;
|
||||||
int newlen;
|
int newlen;
|
||||||
|
int family;
|
||||||
|
int val;
|
||||||
RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
|
RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]);
|
||||||
|
|
||||||
dprintk("svc: svc_create_socket(%s, %d, %s)\n",
|
dprintk("svc: svc_create_socket(%s, %d, %s)\n",
|
||||||
@@ -1231,14 +1222,35 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
|
|||||||
"sockets supported\n");
|
"sockets supported\n");
|
||||||
return ERR_PTR(-EINVAL);
|
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)
|
if (error < 0)
|
||||||
return ERR_PTR(error);
|
return ERR_PTR(error);
|
||||||
|
|
||||||
svc_reclassify_socket(sock);
|
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)
|
if (type == SOCK_STREAM)
|
||||||
sock->sk->sk_reuse = 1; /* allow address reuse */
|
sock->sk->sk_reuse = 1; /* allow address reuse */
|
||||||
error = kernel_bind(sock, sin, len);
|
error = kernel_bind(sock, sin, len);
|
||||||
|
Reference in New Issue
Block a user