aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/ipv6.c
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2009-02-13 03:33:44 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-16 03:03:11 -0500
commit914e1c8b6980c516667375d3e55f0b6e674c8c58 (patch)
treed61194143a112ace85f6e6dfc22bc01d7173f62e /net/sctp/ipv6.c
parentfaee47cdbfe8d74a1573c2f81ea6dbb08d735be6 (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.c33
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)
627static struct sock *sctp_v6_create_accept_sk(struct sock *sk, 627static 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)) {