diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2009-02-13 03:33:44 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-16 03:03:11 -0500 |
commit | 914e1c8b6980c516667375d3e55f0b6e674c8c58 (patch) | |
tree | d61194143a112ace85f6e6dfc22bc01d7173f62e /net/sctp/ipv6.c | |
parent | faee47cdbfe8d74a1573c2f81ea6dbb08d735be6 (diff) |
sctp: Inherit all socket options from parent correctly.
During peeloff/accept() sctp needs to save the parent socket state
into the new socket so that any options set on the parent are
inherited by the child socket. This was found when the
parent/listener socket issues SO_BINDTODEVICE, but the
data was misrouted after a route cache flush.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/ipv6.c')
-rw-r--r-- | net/sctp/ipv6.c | 33 |
1 files changed, 1 insertions, 32 deletions
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 786227566696..a63de3f7f185 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -627,9 +627,7 @@ static sctp_scope_t sctp_v6_scope(union sctp_addr *addr) | |||
627 | static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | 627 | static struct sock *sctp_v6_create_accept_sk(struct sock *sk, |
628 | struct sctp_association *asoc) | 628 | struct sctp_association *asoc) |
629 | { | 629 | { |
630 | struct inet_sock *inet = inet_sk(sk); | ||
631 | struct sock *newsk; | 630 | struct sock *newsk; |
632 | struct inet_sock *newinet; | ||
633 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); | 631 | struct ipv6_pinfo *newnp, *np = inet6_sk(sk); |
634 | struct sctp6_sock *newsctp6sk; | 632 | struct sctp6_sock *newsctp6sk; |
635 | 633 | ||
@@ -639,17 +637,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | |||
639 | 637 | ||
640 | sock_init_data(NULL, newsk); | 638 | sock_init_data(NULL, newsk); |
641 | 639 | ||
642 | newsk->sk_type = SOCK_STREAM; | 640 | sctp_copy_sock(newsk, sk, asoc); |
643 | |||
644 | newsk->sk_prot = sk->sk_prot; | ||
645 | newsk->sk_no_check = sk->sk_no_check; | ||
646 | newsk->sk_reuse = sk->sk_reuse; | ||
647 | |||
648 | newsk->sk_destruct = inet_sock_destruct; | ||
649 | newsk->sk_family = PF_INET6; | ||
650 | newsk->sk_protocol = IPPROTO_SCTP; | ||
651 | newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; | ||
652 | newsk->sk_shutdown = sk->sk_shutdown; | ||
653 | sock_reset_flag(sk, SOCK_ZAPPED); | 641 | sock_reset_flag(sk, SOCK_ZAPPED); |
654 | 642 | ||
655 | newsctp6sk = (struct sctp6_sock *)newsk; | 643 | newsctp6sk = (struct sctp6_sock *)newsk; |
@@ -657,7 +645,6 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | |||
657 | 645 | ||
658 | sctp_sk(newsk)->v4mapped = sctp_sk(sk)->v4mapped; | 646 | sctp_sk(newsk)->v4mapped = sctp_sk(sk)->v4mapped; |
659 | 647 | ||
660 | newinet = inet_sk(newsk); | ||
661 | newnp = inet6_sk(newsk); | 648 | newnp = inet6_sk(newsk); |
662 | 649 | ||
663 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); | 650 | memcpy(newnp, np, sizeof(struct ipv6_pinfo)); |
@@ -665,26 +652,8 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk, | |||
665 | /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname() | 652 | /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname() |
666 | * and getpeername(). | 653 | * and getpeername(). |
667 | */ | 654 | */ |
668 | newinet->sport = inet->sport; | ||
669 | newnp->saddr = np->saddr; | ||
670 | newnp->rcv_saddr = np->rcv_saddr; | ||
671 | newinet->dport = htons(asoc->peer.port); | ||
672 | sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk); | 655 | sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk); |
673 | 656 | ||
674 | /* Init the ipv4 part of the socket since we can have sockets | ||
675 | * using v6 API for ipv4. | ||
676 | */ | ||
677 | newinet->uc_ttl = -1; | ||
678 | newinet->mc_loop = 1; | ||
679 | newinet->mc_ttl = 1; | ||
680 | newinet->mc_index = 0; | ||
681 | newinet->mc_list = NULL; | ||
682 | |||
683 | if (ipv4_config.no_pmtu_disc) | ||
684 | newinet->pmtudisc = IP_PMTUDISC_DONT; | ||
685 | else | ||
686 | newinet->pmtudisc = IP_PMTUDISC_WANT; | ||
687 | |||
688 | sk_refcnt_debug_inc(newsk); | 657 | sk_refcnt_debug_inc(newsk); |
689 | 658 | ||
690 | if (newsk->sk_prot->init(newsk)) { | 659 | if (newsk->sk_prot->init(newsk)) { |