diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-03-30 18:59:17 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-04-01 13:24:29 -0400 |
commit | c69da774b28e01e062e0a3aba7509f2dcfd2a11a (patch) | |
tree | e406bb8055548fcfcd3796881c263fe44dc69443 | |
parent | ad5b365c1266b0c9e8e254a3c1cc4ef66bf33cba (diff) |
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>
-rw-r--r-- | net/sunrpc/svcsock.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index ac6cd65220c7..9d504234af4a 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -1110,7 +1110,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1110 | struct svc_sock *svsk; | 1110 | struct svc_sock *svsk; |
1111 | struct sock *inet; | 1111 | struct sock *inet; |
1112 | int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); | 1112 | int pmap_register = !(flags & SVC_SOCK_ANONYMOUS); |
1113 | int val; | ||
1114 | 1113 | ||
1115 | dprintk("svc: svc_setup_socket %p\n", sock); | 1114 | dprintk("svc: svc_setup_socket %p\n", sock); |
1116 | if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) { | 1115 | if (!(svsk = kzalloc(sizeof(*svsk), GFP_KERNEL))) { |
@@ -1143,16 +1142,6 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1143 | else | 1142 | else |
1144 | svc_tcp_init(svsk, serv); | 1143 | svc_tcp_init(svsk, serv); |
1145 | 1144 | ||
1146 | /* | ||
1147 | * If this is a PF_INET6 listener, we want to avoid | ||
1148 | * getting requests from IPv4 remotes. Those should | ||
1149 | * be shunted to a PF_INET listener via rpcbind. | ||
1150 | */ | ||
1151 | val = 1; | ||
1152 | if (inet->sk_family == PF_INET6) | ||
1153 | kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, | ||
1154 | (char *)&val, sizeof(val)); | ||
1155 | |||
1156 | dprintk("svc: svc_setup_socket created %p (inet %p)\n", | 1145 | dprintk("svc: svc_setup_socket created %p (inet %p)\n", |
1157 | svsk, svsk->sk_sk); | 1146 | svsk, svsk->sk_sk); |
1158 | 1147 | ||
@@ -1220,6 +1209,8 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, | |||
1220 | struct sockaddr_storage addr; | 1209 | struct sockaddr_storage addr; |
1221 | struct sockaddr *newsin = (struct sockaddr *)&addr; | 1210 | struct sockaddr *newsin = (struct sockaddr *)&addr; |
1222 | int newlen; | 1211 | int newlen; |
1212 | int family; | ||
1213 | int val; | ||
1223 | RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); | 1214 | RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); |
1224 | 1215 | ||
1225 | dprintk("svc: svc_create_socket(%s, %d, %s)\n", | 1216 | dprintk("svc: svc_create_socket(%s, %d, %s)\n", |
@@ -1231,14 +1222,35 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, | |||
1231 | "sockets supported\n"); | 1222 | "sockets supported\n"); |
1232 | return ERR_PTR(-EINVAL); | 1223 | return ERR_PTR(-EINVAL); |
1233 | } | 1224 | } |
1225 | |||
1234 | type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM; | 1226 | type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM; |
1227 | switch (sin->sa_family) { | ||
1228 | case AF_INET6: | ||
1229 | family = PF_INET6; | ||
1230 | break; | ||
1231 | case AF_INET: | ||
1232 | family = PF_INET; | ||
1233 | break; | ||
1234 | default: | ||
1235 | return ERR_PTR(-EINVAL); | ||
1236 | } | ||
1235 | 1237 | ||
1236 | error = sock_create_kern(sin->sa_family, type, protocol, &sock); | 1238 | error = sock_create_kern(family, type, protocol, &sock); |
1237 | if (error < 0) | 1239 | if (error < 0) |
1238 | return ERR_PTR(error); | 1240 | return ERR_PTR(error); |
1239 | 1241 | ||
1240 | svc_reclassify_socket(sock); | 1242 | svc_reclassify_socket(sock); |
1241 | 1243 | ||
1244 | /* | ||
1245 | * If this is an PF_INET6 listener, we want to avoid | ||
1246 | * getting requests from IPv4 remotes. Those should | ||
1247 | * be shunted to a PF_INET listener via rpcbind. | ||
1248 | */ | ||
1249 | val = 1; | ||
1250 | if (family == PF_INET6) | ||
1251 | kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, | ||
1252 | (char *)&val, sizeof(val)); | ||
1253 | |||
1242 | if (type == SOCK_STREAM) | 1254 | if (type == SOCK_STREAM) |
1243 | sock->sk->sk_reuse = 1; /* allow address reuse */ | 1255 | sock->sk->sk_reuse = 1; /* allow address reuse */ |
1244 | error = kernel_bind(sock, sin, len); | 1256 | error = kernel_bind(sock, sin, len); |