.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* SCTP kernel implementation |
---|
2 | 3 | * (C) Copyright IBM Corp. 2001, 2004 |
---|
3 | 4 | * Copyright (c) 1999-2000 Cisco, Inc. |
---|
.. | .. |
---|
7 | 8 | * Copyright (c) 2001 La Monte H.P. Yarroll |
---|
8 | 9 | * |
---|
9 | 10 | * This abstraction carries sctp events to the ULP (sockets). |
---|
10 | | - * |
---|
11 | | - * This SCTP implementation is free software; |
---|
12 | | - * you can redistribute it and/or modify it under the terms of |
---|
13 | | - * the GNU General Public License as published by |
---|
14 | | - * the Free Software Foundation; either version 2, or (at your option) |
---|
15 | | - * any later version. |
---|
16 | | - * |
---|
17 | | - * This SCTP implementation is distributed in the hope that it |
---|
18 | | - * will be useful, but WITHOUT ANY WARRANTY; without even the implied |
---|
19 | | - * ************************ |
---|
20 | | - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
---|
21 | | - * See the GNU General Public License for more details. |
---|
22 | | - * |
---|
23 | | - * You should have received a copy of the GNU General Public License |
---|
24 | | - * along with GNU CC; see the file COPYING. If not, see |
---|
25 | | - * <http://www.gnu.org/licenses/>. |
---|
26 | 11 | * |
---|
27 | 12 | * Please send any bug reports or fixes you make to the |
---|
28 | 13 | * email address(es): |
---|
.. | .. |
---|
116 | 101 | event = sctp_ulpq_reasm(ulpq, event); |
---|
117 | 102 | |
---|
118 | 103 | /* Do ordering if needed. */ |
---|
119 | | - if ((event) && (event->msg_flags & MSG_EOR)) { |
---|
| 104 | + if (event) { |
---|
120 | 105 | /* Create a temporary list to collect chunks on. */ |
---|
121 | 106 | skb_queue_head_init(&temp); |
---|
122 | 107 | __skb_queue_tail(&temp, sctp_event2skb(event)); |
---|
123 | 108 | |
---|
124 | | - event = sctp_ulpq_order(ulpq, event); |
---|
| 109 | + if (event->msg_flags & MSG_EOR) |
---|
| 110 | + event = sctp_ulpq_order(ulpq, event); |
---|
125 | 111 | } |
---|
126 | 112 | |
---|
127 | 113 | /* Send event to the ULP. 'event' is the sctp_ulpevent for |
---|
.. | .. |
---|
129 | 115 | */ |
---|
130 | 116 | if (event) { |
---|
131 | 117 | event_eor = (event->msg_flags & MSG_EOR) ? 1 : 0; |
---|
132 | | - sctp_ulpq_tail_event(ulpq, event); |
---|
| 118 | + sctp_ulpq_tail_event(ulpq, &temp); |
---|
133 | 119 | } |
---|
134 | 120 | |
---|
135 | 121 | return event_eor; |
---|
.. | .. |
---|
193 | 179 | return sctp_clear_pd(ulpq->asoc->base.sk, ulpq->asoc); |
---|
194 | 180 | } |
---|
195 | 181 | |
---|
196 | | -/* If the SKB of 'event' is on a list, it is the first such member |
---|
197 | | - * of that list. |
---|
198 | | - */ |
---|
199 | | -int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) |
---|
| 182 | +int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sk_buff_head *skb_list) |
---|
200 | 183 | { |
---|
201 | 184 | struct sock *sk = ulpq->asoc->base.sk; |
---|
202 | 185 | struct sctp_sock *sp = sctp_sk(sk); |
---|
203 | | - struct sk_buff_head *queue, *skb_list; |
---|
204 | | - struct sk_buff *skb = sctp_event2skb(event); |
---|
| 186 | + struct sctp_ulpevent *event; |
---|
| 187 | + struct sk_buff_head *queue; |
---|
| 188 | + struct sk_buff *skb; |
---|
205 | 189 | int clear_pd = 0; |
---|
206 | 190 | |
---|
207 | | - skb_list = (struct sk_buff_head *) skb->prev; |
---|
| 191 | + skb = __skb_peek(skb_list); |
---|
| 192 | + event = sctp_skb2event(skb); |
---|
208 | 193 | |
---|
209 | 194 | /* If the socket is just going to throw this away, do not |
---|
210 | 195 | * even try to deliver it. |
---|
.. | .. |
---|
219 | 204 | sk_incoming_cpu_update(sk); |
---|
220 | 205 | } |
---|
221 | 206 | /* Check if the user wishes to receive this event. */ |
---|
222 | | - if (!sctp_ulpevent_is_enabled(event, &sp->subscribe)) |
---|
| 207 | + if (!sctp_ulpevent_is_enabled(event, ulpq->asoc->subscribe)) |
---|
223 | 208 | goto out_free; |
---|
224 | 209 | |
---|
225 | 210 | /* If we are in partial delivery mode, post to the lobby until |
---|
.. | .. |
---|
257 | 242 | } |
---|
258 | 243 | } |
---|
259 | 244 | |
---|
260 | | - /* If we are harvesting multiple skbs they will be |
---|
261 | | - * collected on a list. |
---|
262 | | - */ |
---|
263 | | - if (skb_list) |
---|
264 | | - skb_queue_splice_tail_init(skb_list, queue); |
---|
265 | | - else |
---|
266 | | - __skb_queue_tail(queue, skb); |
---|
| 245 | + skb_queue_splice_tail_init(skb_list, queue); |
---|
267 | 246 | |
---|
268 | 247 | /* Did we just complete partial delivery and need to get |
---|
269 | 248 | * rolling again? Move pending data to the receive |
---|
.. | .. |
---|
459 | 438 | * element in the queue, then count it towards |
---|
460 | 439 | * possible PD. |
---|
461 | 440 | */ |
---|
462 | | - if (pos == ulpq->reasm.next) { |
---|
| 441 | + if (skb_queue_is_first(&ulpq->reasm, pos)) { |
---|
463 | 442 | pd_first = pos; |
---|
464 | 443 | pd_last = pos; |
---|
465 | 444 | pd_len = pos->len; |
---|
.. | .. |
---|
507 | 486 | cevent = sctp_skb2event(pd_first); |
---|
508 | 487 | pd_point = sctp_sk(asoc->base.sk)->pd_point; |
---|
509 | 488 | if (pd_point && pd_point <= pd_len) { |
---|
510 | | - retval = sctp_make_reassembled_event(sock_net(asoc->base.sk), |
---|
| 489 | + retval = sctp_make_reassembled_event(asoc->base.net, |
---|
511 | 490 | &ulpq->reasm, |
---|
512 | | - pd_first, |
---|
513 | | - pd_last); |
---|
| 491 | + pd_first, pd_last); |
---|
514 | 492 | if (retval) |
---|
515 | 493 | sctp_ulpq_set_pd(ulpq); |
---|
516 | 494 | } |
---|
.. | .. |
---|
518 | 496 | done: |
---|
519 | 497 | return retval; |
---|
520 | 498 | found: |
---|
521 | | - retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), |
---|
| 499 | + retval = sctp_make_reassembled_event(ulpq->asoc->base.net, |
---|
522 | 500 | &ulpq->reasm, first_frag, pos); |
---|
523 | 501 | if (retval) |
---|
524 | 502 | retval->msg_flags |= MSG_EOR; |
---|
.. | .. |
---|
584 | 562 | * further. |
---|
585 | 563 | */ |
---|
586 | 564 | done: |
---|
587 | | - retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), |
---|
588 | | - &ulpq->reasm, first_frag, last_frag); |
---|
| 565 | + retval = sctp_make_reassembled_event(ulpq->asoc->base.net, &ulpq->reasm, |
---|
| 566 | + first_frag, last_frag); |
---|
589 | 567 | if (retval && is_last) |
---|
590 | 568 | retval->msg_flags |= MSG_EOR; |
---|
591 | 569 | |
---|
.. | .. |
---|
685 | 663 | * further. |
---|
686 | 664 | */ |
---|
687 | 665 | done: |
---|
688 | | - retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), |
---|
689 | | - &ulpq->reasm, first_frag, last_frag); |
---|
| 666 | + retval = sctp_make_reassembled_event(ulpq->asoc->base.net, &ulpq->reasm, |
---|
| 667 | + first_frag, last_frag); |
---|
690 | 668 | return retval; |
---|
691 | 669 | } |
---|
692 | 670 | |
---|
.. | .. |
---|
738 | 716 | static void sctp_ulpq_reasm_drain(struct sctp_ulpq *ulpq) |
---|
739 | 717 | { |
---|
740 | 718 | struct sctp_ulpevent *event = NULL; |
---|
741 | | - struct sk_buff_head temp; |
---|
742 | 719 | |
---|
743 | 720 | if (skb_queue_empty(&ulpq->reasm)) |
---|
744 | 721 | return; |
---|
745 | 722 | |
---|
746 | 723 | while ((event = sctp_ulpq_retrieve_reassembled(ulpq)) != NULL) { |
---|
747 | | - /* Do ordering if needed. */ |
---|
748 | | - if ((event) && (event->msg_flags & MSG_EOR)) { |
---|
749 | | - skb_queue_head_init(&temp); |
---|
750 | | - __skb_queue_tail(&temp, sctp_event2skb(event)); |
---|
| 724 | + struct sk_buff_head temp; |
---|
751 | 725 | |
---|
| 726 | + skb_queue_head_init(&temp); |
---|
| 727 | + __skb_queue_tail(&temp, sctp_event2skb(event)); |
---|
| 728 | + |
---|
| 729 | + /* Do ordering if needed. */ |
---|
| 730 | + if (event->msg_flags & MSG_EOR) |
---|
752 | 731 | event = sctp_ulpq_order(ulpq, event); |
---|
753 | | - } |
---|
754 | 732 | |
---|
755 | 733 | /* Send event to the ULP. 'event' is the |
---|
756 | 734 | * sctp_ulpevent for very first SKB on the temp' list. |
---|
757 | 735 | */ |
---|
758 | 736 | if (event) |
---|
759 | | - sctp_ulpq_tail_event(ulpq, event); |
---|
| 737 | + sctp_ulpq_tail_event(ulpq, &temp); |
---|
760 | 738 | } |
---|
761 | 739 | } |
---|
762 | 740 | |
---|
763 | 741 | |
---|
764 | 742 | /* Helper function to gather skbs that have possibly become |
---|
765 | | - * ordered by an an incoming chunk. |
---|
| 743 | + * ordered by an incoming chunk. |
---|
766 | 744 | */ |
---|
767 | 745 | static void sctp_ulpq_retrieve_ordered(struct sctp_ulpq *ulpq, |
---|
768 | 746 | struct sctp_ulpevent *event) |
---|
.. | .. |
---|
956 | 934 | if (event) { |
---|
957 | 935 | /* see if we have more ordered that we can deliver */ |
---|
958 | 936 | sctp_ulpq_retrieve_ordered(ulpq, event); |
---|
959 | | - sctp_ulpq_tail_event(ulpq, event); |
---|
| 937 | + sctp_ulpq_tail_event(ulpq, &temp); |
---|
960 | 938 | } |
---|
961 | 939 | } |
---|
962 | 940 | |
---|
.. | .. |
---|
1082 | 1060 | event = sctp_ulpq_retrieve_first(ulpq); |
---|
1083 | 1061 | /* Send event to the ULP. */ |
---|
1084 | 1062 | if (event) { |
---|
1085 | | - sctp_ulpq_tail_event(ulpq, event); |
---|
| 1063 | + struct sk_buff_head temp; |
---|
| 1064 | + |
---|
| 1065 | + skb_queue_head_init(&temp); |
---|
| 1066 | + __skb_queue_tail(&temp, sctp_event2skb(event)); |
---|
| 1067 | + sctp_ulpq_tail_event(ulpq, &temp); |
---|
1086 | 1068 | sctp_ulpq_set_pd(ulpq); |
---|
1087 | 1069 | return; |
---|
1088 | 1070 | } |
---|
.. | .. |
---|
1106 | 1088 | freed += sctp_ulpq_renege_frags(ulpq, needed - freed); |
---|
1107 | 1089 | } |
---|
1108 | 1090 | /* If able to free enough room, accept this chunk. */ |
---|
1109 | | - if (freed >= needed) { |
---|
| 1091 | + if (sk_rmem_schedule(asoc->base.sk, chunk->skb, needed) && |
---|
| 1092 | + freed >= needed) { |
---|
1110 | 1093 | int retval = sctp_ulpq_tail_data(ulpq, chunk, gfp); |
---|
1111 | 1094 | /* |
---|
1112 | 1095 | * Enter partial delivery if chunk has not been |
---|
.. | .. |
---|
1129 | 1112 | void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, gfp_t gfp) |
---|
1130 | 1113 | { |
---|
1131 | 1114 | struct sctp_ulpevent *ev = NULL; |
---|
1132 | | - struct sock *sk; |
---|
1133 | 1115 | struct sctp_sock *sp; |
---|
| 1116 | + struct sock *sk; |
---|
1134 | 1117 | |
---|
1135 | 1118 | if (!ulpq->pd_mode) |
---|
1136 | 1119 | return; |
---|
1137 | 1120 | |
---|
1138 | 1121 | sk = ulpq->asoc->base.sk; |
---|
1139 | 1122 | sp = sctp_sk(sk); |
---|
1140 | | - if (sctp_ulpevent_type_enabled(SCTP_PARTIAL_DELIVERY_EVENT, |
---|
1141 | | - &sctp_sk(sk)->subscribe)) |
---|
| 1123 | + if (sctp_ulpevent_type_enabled(ulpq->asoc->subscribe, |
---|
| 1124 | + SCTP_PARTIAL_DELIVERY_EVENT)) |
---|
1142 | 1125 | ev = sctp_ulpevent_make_pdapi(ulpq->asoc, |
---|
1143 | 1126 | SCTP_PARTIAL_DELIVERY_ABORTED, |
---|
1144 | 1127 | 0, 0, 0, gfp); |
---|