diff options
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r-- | net/sunrpc/svcsock.c | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 5763e6460fea..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))) { |
@@ -1122,7 +1121,7 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
1122 | 1121 | ||
1123 | /* Register socket with portmapper */ | 1122 | /* Register socket with portmapper */ |
1124 | if (*errp >= 0 && pmap_register) | 1123 | if (*errp >= 0 && pmap_register) |
1125 | *errp = svc_register(serv, inet->sk_protocol, | 1124 | *errp = svc_register(serv, inet->sk_family, inet->sk_protocol, |
1126 | ntohs(inet_sk(inet)->sport)); | 1125 | ntohs(inet_sk(inet)->sport)); |
1127 | 1126 | ||
1128 | if (*errp < 0) { | 1127 | if (*errp < 0) { |
@@ -1143,18 +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 | * We start one listener per sv_serv. We want AF_INET | ||
1148 | * requests to be automatically shunted to our AF_INET6 | ||
1149 | * listener using a mapped IPv4 address. Make sure | ||
1150 | * no-one starts an equivalent IPv4 listener, which | ||
1151 | * would steal our incoming connections. | ||
1152 | */ | ||
1153 | val = 0; | ||
1154 | if (serv->sv_family == AF_INET6) | ||
1155 | kernel_setsockopt(sock, SOL_IPV6, IPV6_V6ONLY, | ||
1156 | (char *)&val, sizeof(val)); | ||
1157 | |||
1158 | dprintk("svc: svc_setup_socket created %p (inet %p)\n", | 1145 | dprintk("svc: svc_setup_socket created %p (inet %p)\n", |
1159 | svsk, svsk->sk_sk); | 1146 | svsk, svsk->sk_sk); |
1160 | 1147 | ||
@@ -1222,6 +1209,8 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, | |||
1222 | struct sockaddr_storage addr; | 1209 | struct sockaddr_storage addr; |
1223 | struct sockaddr *newsin = (struct sockaddr *)&addr; | 1210 | struct sockaddr *newsin = (struct sockaddr *)&addr; |
1224 | int newlen; | 1211 | int newlen; |
1212 | int family; | ||
1213 | int val; | ||
1225 | RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); | 1214 | RPC_IFDEBUG(char buf[RPC_MAX_ADDRBUFLEN]); |
1226 | 1215 | ||
1227 | dprintk("svc: svc_create_socket(%s, %d, %s)\n", | 1216 | dprintk("svc: svc_create_socket(%s, %d, %s)\n", |
@@ -1233,14 +1222,35 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, | |||
1233 | "sockets supported\n"); | 1222 | "sockets supported\n"); |
1234 | return ERR_PTR(-EINVAL); | 1223 | return ERR_PTR(-EINVAL); |
1235 | } | 1224 | } |
1225 | |||
1236 | 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 | } | ||
1237 | 1237 | ||
1238 | error = sock_create_kern(sin->sa_family, type, protocol, &sock); | 1238 | error = sock_create_kern(family, type, protocol, &sock); |
1239 | if (error < 0) | 1239 | if (error < 0) |
1240 | return ERR_PTR(error); | 1240 | return ERR_PTR(error); |
1241 | 1241 | ||
1242 | svc_reclassify_socket(sock); | 1242 | svc_reclassify_socket(sock); |
1243 | 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 | |||
1244 | if (type == SOCK_STREAM) | 1254 | if (type == SOCK_STREAM) |
1245 | sock->sk->sk_reuse = 1; /* allow address reuse */ | 1255 | sock->sk->sk_reuse = 1; /* allow address reuse */ |
1246 | error = kernel_bind(sock, sin, len); | 1256 | error = kernel_bind(sock, sin, len); |