aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sctp/socket.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 536298c2eda2..523e73ee354a 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5638,6 +5638,36 @@ void sctp_wait_for_close(struct sock *sk, long timeout)
5638 finish_wait(sk->sk_sleep, &wait); 5638 finish_wait(sk->sk_sleep, &wait);
5639} 5639}
5640 5640
5641static void sctp_sock_rfree_frag(struct sk_buff *skb)
5642{
5643 struct sk_buff *frag;
5644
5645 if (!skb->data_len)
5646 goto done;
5647
5648 /* Don't forget the fragments. */
5649 for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next)
5650 sctp_sock_rfree_frag(frag);
5651
5652done:
5653 sctp_sock_rfree(skb);
5654}
5655
5656static void sctp_skb_set_owner_r_frag(struct sk_buff *skb, struct sock *sk)
5657{
5658 struct sk_buff *frag;
5659
5660 if (!skb->data_len)
5661 goto done;
5662
5663 /* Don't forget the fragments. */
5664 for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next)
5665 sctp_skb_set_owner_r_frag(frag, sk);
5666
5667done:
5668 sctp_skb_set_owner_r(skb, sk);
5669}
5670
5641/* Populate the fields of the newsk from the oldsk and migrate the assoc 5671/* Populate the fields of the newsk from the oldsk and migrate the assoc
5642 * and its messages to the newsk. 5672 * and its messages to the newsk.
5643 */ 5673 */
@@ -5692,10 +5722,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
5692 sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) { 5722 sctp_skb_for_each(skb, &oldsk->sk_receive_queue, tmp) {
5693 event = sctp_skb2event(skb); 5723 event = sctp_skb2event(skb);
5694 if (event->asoc == assoc) { 5724 if (event->asoc == assoc) {
5695 sctp_sock_rfree(skb); 5725 sctp_sock_rfree_frag(skb);
5696 __skb_unlink(skb, &oldsk->sk_receive_queue); 5726 __skb_unlink(skb, &oldsk->sk_receive_queue);
5697 __skb_queue_tail(&newsk->sk_receive_queue, skb); 5727 __skb_queue_tail(&newsk->sk_receive_queue, skb);
5698 sctp_skb_set_owner_r(skb, newsk); 5728 sctp_skb_set_owner_r_frag(skb, newsk);
5699 } 5729 }
5700 } 5730 }
5701 5731
@@ -5723,10 +5753,10 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
5723 sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) { 5753 sctp_skb_for_each(skb, &oldsp->pd_lobby, tmp) {
5724 event = sctp_skb2event(skb); 5754 event = sctp_skb2event(skb);
5725 if (event->asoc == assoc) { 5755 if (event->asoc == assoc) {
5726 sctp_sock_rfree(skb); 5756 sctp_sock_rfree_frag(skb);
5727 __skb_unlink(skb, &oldsp->pd_lobby); 5757 __skb_unlink(skb, &oldsp->pd_lobby);
5728 __skb_queue_tail(queue, skb); 5758 __skb_queue_tail(queue, skb);
5729 sctp_skb_set_owner_r(skb, newsk); 5759 sctp_skb_set_owner_r_frag(skb, newsk);
5730 } 5760 }
5731 } 5761 }
5732 5762
@@ -5738,6 +5768,16 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
5738 5768
5739 } 5769 }
5740 5770
5771 sctp_skb_for_each(skb, &assoc->ulpq.reasm, tmp) {
5772 sctp_sock_rfree_frag(skb);
5773 sctp_skb_set_owner_r_frag(skb, newsk);
5774 }
5775
5776 sctp_skb_for_each(skb, &assoc->ulpq.lobby, tmp) {
5777 sctp_sock_rfree_frag(skb);
5778 sctp_skb_set_owner_r_frag(skb, newsk);
5779 }
5780
5741 /* Set the type of socket to indicate that it is peeled off from the 5781 /* Set the type of socket to indicate that it is peeled off from the
5742 * original UDP-style socket or created with the accept() call on a 5782 * original UDP-style socket or created with the accept() call on a
5743 * TCP-style socket.. 5783 * TCP-style socket..