aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/socket.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/socket.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/socket.c')
-rw-r--r--net/sctp/socket.c55
1 files changed, 48 insertions, 7 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index ff0a8f88de04..dea864f5de54 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3939,7 +3939,6 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
3939{ 3939{
3940 struct sock *sk = asoc->base.sk; 3940 struct sock *sk = asoc->base.sk;
3941 struct socket *sock; 3941 struct socket *sock;
3942 struct inet_sock *inetsk;
3943 struct sctp_af *af; 3942 struct sctp_af *af;
3944 int err = 0; 3943 int err = 0;
3945 3944
@@ -3954,18 +3953,18 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc,
3954 if (err < 0) 3953 if (err < 0)
3955 return err; 3954 return err;
3956 3955
3957 /* Populate the fields of the newsk from the oldsk and migrate the 3956 sctp_copy_sock(sock->sk, sk, asoc);
3958 * asoc to the newsk.
3959 */
3960 sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
3961 3957
3962 /* Make peeled-off sockets more like 1-1 accepted sockets. 3958 /* Make peeled-off sockets more like 1-1 accepted sockets.
3963 * Set the daddr and initialize id to something more random 3959 * Set the daddr and initialize id to something more random
3964 */ 3960 */
3965 af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family); 3961 af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family);
3966 af->to_sk_daddr(&asoc->peer.primary_addr, sk); 3962 af->to_sk_daddr(&asoc->peer.primary_addr, sk);
3967 inetsk = inet_sk(sock->sk); 3963
3968 inetsk->id = asoc->next_tsn ^ jiffies; 3964 /* Populate the fields of the newsk from the oldsk and migrate the
3965 * asoc to the newsk.
3966 */
3967 sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH);
3969 3968
3970 *sockp = sock; 3969 *sockp = sock;
3971 3970
@@ -6700,6 +6699,48 @@ done:
6700 sctp_skb_set_owner_r(skb, sk); 6699 sctp_skb_set_owner_r(skb, sk);
6701} 6700}
6702 6701
6702void sctp_copy_sock(struct sock *newsk, struct sock *sk,
6703 struct sctp_association *asoc)
6704{
6705 struct inet_sock *inet = inet_sk(sk);
6706 struct inet_sock *newinet = inet_sk(newsk);
6707
6708 newsk->sk_type = sk->sk_type;
6709 newsk->sk_bound_dev_if = sk->sk_bound_dev_if;
6710 newsk->sk_flags = sk->sk_flags;
6711 newsk->sk_no_check = sk->sk_no_check;
6712 newsk->sk_reuse = sk->sk_reuse;
6713
6714 newsk->sk_shutdown = sk->sk_shutdown;
6715 newsk->sk_destruct = inet_sock_destruct;
6716 newsk->sk_family = sk->sk_family;
6717 newsk->sk_protocol = IPPROTO_SCTP;
6718 newsk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
6719 newsk->sk_sndbuf = sk->sk_sndbuf;
6720 newsk->sk_rcvbuf = sk->sk_rcvbuf;
6721 newsk->sk_lingertime = sk->sk_lingertime;
6722 newsk->sk_rcvtimeo = sk->sk_rcvtimeo;
6723 newsk->sk_sndtimeo = sk->sk_sndtimeo;
6724
6725 newinet = inet_sk(newsk);
6726
6727 /* Initialize sk's sport, dport, rcv_saddr and daddr for
6728 * getsockname() and getpeername()
6729 */
6730 newinet->sport = inet->sport;
6731 newinet->saddr = inet->saddr;
6732 newinet->rcv_saddr = inet->rcv_saddr;
6733 newinet->dport = htons(asoc->peer.port);
6734 newinet->pmtudisc = inet->pmtudisc;
6735 newinet->id = asoc->next_tsn ^ jiffies;
6736
6737 newinet->uc_ttl = inet->uc_ttl;
6738 newinet->mc_loop = 1;
6739 newinet->mc_ttl = 1;
6740 newinet->mc_index = 0;
6741 newinet->mc_list = NULL;
6742}
6743
6703/* Populate the fields of the newsk from the oldsk and migrate the assoc 6744/* Populate the fields of the newsk from the oldsk and migrate the assoc
6704 * and its messages to the newsk. 6745 * and its messages to the newsk.
6705 */ 6746 */