aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.c
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2008-07-19 02:05:40 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-19 02:05:40 -0400
commit7dab83de50c7b2b7ceac695a0b56fa6c0f95b0bc (patch)
tree979c6905f2ef643acccfea9ab9ed926e764e72c8 /net/sctp/socket.c
parent6d0ccbac688207ca0616ab5094932af4db4747b3 (diff)
sctp: Support ipv6only AF_INET6 sockets.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r--net/sctp/socket.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 6aba01b0ce4e..a0e879bb202d 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -308,9 +308,16 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
308 if (len < sizeof (struct sockaddr)) 308 if (len < sizeof (struct sockaddr))
309 return NULL; 309 return NULL;
310 310
311 /* Does this PF support this AF? */ 311 /* V4 mapped address are really of AF_INET family */
312 if (!opt->pf->af_supported(addr->sa.sa_family, opt)) 312 if (addr->sa.sa_family == AF_INET6 &&
313 return NULL; 313 ipv6_addr_v4mapped(&addr->v6.sin6_addr)) {
314 if (!opt->pf->af_supported(AF_INET, opt))
315 return NULL;
316 } else {
317 /* Does this PF support this AF? */
318 if (!opt->pf->af_supported(addr->sa.sa_family, opt))
319 return NULL;
320 }
314 321
315 /* If we get this far, af is valid. */ 322 /* If we get this far, af is valid. */
316 af = sctp_get_af_specific(addr->sa.sa_family); 323 af = sctp_get_af_specific(addr->sa.sa_family);
@@ -4395,6 +4402,11 @@ static int sctp_getsockopt_local_addrs_num_old(struct sock *sk, int len,
4395 (AF_INET6 == addr->a.sa.sa_family)) 4402 (AF_INET6 == addr->a.sa.sa_family))
4396 continue; 4403 continue;
4397 4404
4405 if ((PF_INET6 == sk->sk_family) &&
4406 inet_v6_ipv6only(sk) &&
4407 (AF_INET == addr->a.sa.sa_family))
4408 continue;
4409
4398 cnt++; 4410 cnt++;
4399 } 4411 }
4400 rcu_read_unlock(); 4412 rcu_read_unlock();
@@ -4435,6 +4447,10 @@ static int sctp_copy_laddrs_old(struct sock *sk, __u16 port,
4435 if ((PF_INET == sk->sk_family) && 4447 if ((PF_INET == sk->sk_family) &&
4436 (AF_INET6 == addr->a.sa.sa_family)) 4448 (AF_INET6 == addr->a.sa.sa_family))
4437 continue; 4449 continue;
4450 if ((PF_INET6 == sk->sk_family) &&
4451 inet_v6_ipv6only(sk) &&
4452 (AF_INET == addr->a.sa.sa_family))
4453 continue;
4438 memcpy(&temp, &addr->a, sizeof(temp)); 4454 memcpy(&temp, &addr->a, sizeof(temp));
4439 if (!temp.v4.sin_port) 4455 if (!temp.v4.sin_port)
4440 temp.v4.sin_port = htons(port); 4456 temp.v4.sin_port = htons(port);
@@ -4470,6 +4486,10 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
4470 if ((PF_INET == sk->sk_family) && 4486 if ((PF_INET == sk->sk_family) &&
4471 (AF_INET6 == addr->a.sa.sa_family)) 4487 (AF_INET6 == addr->a.sa.sa_family))
4472 continue; 4488 continue;
4489 if ((PF_INET6 == sk->sk_family) &&
4490 inet_v6_ipv6only(sk) &&
4491 (AF_INET == addr->a.sa.sa_family))
4492 continue;
4473 memcpy(&temp, &addr->a, sizeof(temp)); 4493 memcpy(&temp, &addr->a, sizeof(temp));
4474 if (!temp.v4.sin_port) 4494 if (!temp.v4.sin_port)
4475 temp.v4.sin_port = htons(port); 4495 temp.v4.sin_port = htons(port);
@@ -5568,8 +5588,8 @@ pp_found:
5568 sk2->sk_state != SCTP_SS_LISTENING) 5588 sk2->sk_state != SCTP_SS_LISTENING)
5569 continue; 5589 continue;
5570 5590
5571 if (sctp_bind_addr_match(&ep2->base.bind_addr, addr, 5591 if (sctp_bind_addr_conflict(&ep2->base.bind_addr, addr,
5572 sctp_sk(sk))) { 5592 sctp_sk(sk2), sctp_sk(sk))) {
5573 ret = (long)sk2; 5593 ret = (long)sk2;
5574 goto fail_unlock; 5594 goto fail_unlock;
5575 } 5595 }