.. | .. |
---|
| 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 Cisco, Inc. |
---|
.. | .. |
---|
8 | 9 | * These functions work with the state functions in sctp_sm_statefuns.c |
---|
9 | 10 | * to implement that state operations. These functions implement the |
---|
10 | 11 | * steps which require modifying existing data structures. |
---|
11 | | - * |
---|
12 | | - * This SCTP implementation is free software; |
---|
13 | | - * you can redistribute it and/or modify it under the terms of |
---|
14 | | - * the GNU General Public License as published by |
---|
15 | | - * the Free Software Foundation; either version 2, or (at your option) |
---|
16 | | - * any later version. |
---|
17 | | - * |
---|
18 | | - * This SCTP implementation is distributed in the hope that it |
---|
19 | | - * will be useful, but WITHOUT ANY WARRANTY; without even the implied |
---|
20 | | - * ************************ |
---|
21 | | - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
---|
22 | | - * See the GNU General Public License for more details. |
---|
23 | | - * |
---|
24 | | - * You should have received a copy of the GNU General Public License |
---|
25 | | - * along with GNU CC; see the file COPYING. If not, see |
---|
26 | | - * <http://www.gnu.org/licenses/>. |
---|
27 | 12 | * |
---|
28 | 13 | * Please send any bug reports or fixes you make to the |
---|
29 | 14 | * email address(es): |
---|
.. | .. |
---|
52 | 37 | #include <net/sctp/sm.h> |
---|
53 | 38 | #include <net/sctp/stream_sched.h> |
---|
54 | 39 | |
---|
55 | | -static int sctp_cmd_interpreter(enum sctp_event event_type, |
---|
| 40 | +static int sctp_cmd_interpreter(enum sctp_event_type event_type, |
---|
56 | 41 | union sctp_subtype subtype, |
---|
57 | 42 | enum sctp_state state, |
---|
58 | 43 | struct sctp_endpoint *ep, |
---|
.. | .. |
---|
61 | 46 | enum sctp_disposition status, |
---|
62 | 47 | struct sctp_cmd_seq *commands, |
---|
63 | 48 | gfp_t gfp); |
---|
64 | | -static int sctp_side_effects(enum sctp_event event_type, |
---|
| 49 | +static int sctp_side_effects(enum sctp_event_type event_type, |
---|
65 | 50 | union sctp_subtype subtype, |
---|
66 | 51 | enum sctp_state state, |
---|
67 | 52 | struct sctp_endpoint *ep, |
---|
.. | .. |
---|
473 | 458 | goto out_unlock; |
---|
474 | 459 | } |
---|
475 | 460 | |
---|
| 461 | + /* This happens when the response arrives after the timer is triggered. */ |
---|
| 462 | + if (!asoc->strreset_chunk) |
---|
| 463 | + goto out_unlock; |
---|
| 464 | + |
---|
476 | 465 | error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT, |
---|
477 | 466 | SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_RECONF), |
---|
478 | 467 | asoc->state, asoc->ep, asoc, |
---|
.. | .. |
---|
531 | 520 | struct sctp_transport *transport, |
---|
532 | 521 | int is_hb) |
---|
533 | 522 | { |
---|
534 | | - struct net *net = sock_net(asoc->base.sk); |
---|
535 | | - |
---|
536 | 523 | /* The check for association's overall error counter exceeding the |
---|
537 | 524 | * threshold is done in the state function. |
---|
538 | 525 | */ |
---|
.. | .. |
---|
559 | 546 | * is SCTP_ACTIVE, then mark this transport as Partially Failed, |
---|
560 | 547 | * see SCTP Quick Failover Draft, section 5.1 |
---|
561 | 548 | */ |
---|
562 | | - if (net->sctp.pf_enable && |
---|
563 | | - (transport->state == SCTP_ACTIVE) && |
---|
564 | | - (transport->error_count < transport->pathmaxrxt) && |
---|
565 | | - (transport->error_count > transport->pf_retrans)) { |
---|
| 549 | + if (asoc->base.net->sctp.pf_enable && |
---|
| 550 | + transport->state == SCTP_ACTIVE && |
---|
| 551 | + transport->error_count < transport->pathmaxrxt && |
---|
| 552 | + transport->error_count > transport->pf_retrans) { |
---|
566 | 553 | |
---|
567 | 554 | sctp_assoc_control_transport(asoc, transport, |
---|
568 | 555 | SCTP_TRANSPORT_PF, |
---|
.. | .. |
---|
581 | 568 | SCTP_TRANSPORT_DOWN, |
---|
582 | 569 | SCTP_FAILED_THRESHOLD); |
---|
583 | 570 | } |
---|
| 571 | + |
---|
| 572 | + if (transport->error_count > transport->ps_retrans && |
---|
| 573 | + asoc->peer.primary_path == transport && |
---|
| 574 | + asoc->peer.active_path != transport) |
---|
| 575 | + sctp_assoc_set_primary(asoc, asoc->peer.active_path); |
---|
584 | 576 | |
---|
585 | 577 | /* E2) For the destination address for which the timer |
---|
586 | 578 | * expires, set RTO <- RTO * 2 ("back off the timer"). The |
---|
.. | .. |
---|
623 | 615 | /* Worker routine to handle SCTP_CMD_ASSOC_FAILED. */ |
---|
624 | 616 | static void sctp_cmd_assoc_failed(struct sctp_cmd_seq *commands, |
---|
625 | 617 | struct sctp_association *asoc, |
---|
626 | | - enum sctp_event event_type, |
---|
| 618 | + enum sctp_event_type event_type, |
---|
627 | 619 | union sctp_subtype subtype, |
---|
628 | 620 | struct sctp_chunk *chunk, |
---|
629 | 621 | unsigned int error) |
---|
.. | .. |
---|
808 | 800 | int err = 0; |
---|
809 | 801 | |
---|
810 | 802 | if (sctp_outq_sack(&asoc->outqueue, chunk)) { |
---|
811 | | - struct net *net = sock_net(asoc->base.sk); |
---|
812 | | - |
---|
813 | 803 | /* There are no more TSNs awaiting SACK. */ |
---|
814 | | - err = sctp_do_sm(net, SCTP_EVENT_T_OTHER, |
---|
| 804 | + err = sctp_do_sm(asoc->base.net, SCTP_EVENT_T_OTHER, |
---|
815 | 805 | SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN), |
---|
816 | 806 | asoc->state, asoc->ep, asoc, NULL, |
---|
817 | 807 | GFP_ATOMIC); |
---|
.. | .. |
---|
844 | 834 | struct sctp_association *asoc, |
---|
845 | 835 | struct sctp_association *new) |
---|
846 | 836 | { |
---|
847 | | - struct net *net = sock_net(asoc->base.sk); |
---|
| 837 | + struct net *net = asoc->base.net; |
---|
848 | 838 | struct sctp_chunk *abort; |
---|
849 | 839 | |
---|
850 | 840 | if (!sctp_assoc_update(asoc, new)) |
---|
.. | .. |
---|
1141 | 1131 | * If you want to understand all of lksctp, this is a |
---|
1142 | 1132 | * good place to start. |
---|
1143 | 1133 | */ |
---|
1144 | | -int sctp_do_sm(struct net *net, enum sctp_event event_type, |
---|
| 1134 | +int sctp_do_sm(struct net *net, enum sctp_event_type event_type, |
---|
1145 | 1135 | union sctp_subtype subtype, enum sctp_state state, |
---|
1146 | 1136 | struct sctp_endpoint *ep, struct sctp_association *asoc, |
---|
1147 | 1137 | void *event_arg, gfp_t gfp) |
---|
.. | .. |
---|
1178 | 1168 | /***************************************************************** |
---|
1179 | 1169 | * This the master state function side effect processing function. |
---|
1180 | 1170 | *****************************************************************/ |
---|
1181 | | -static int sctp_side_effects(enum sctp_event event_type, |
---|
| 1171 | +static int sctp_side_effects(enum sctp_event_type event_type, |
---|
1182 | 1172 | union sctp_subtype subtype, |
---|
1183 | 1173 | enum sctp_state state, |
---|
1184 | 1174 | struct sctp_endpoint *ep, |
---|
.. | .. |
---|
1251 | 1241 | default: |
---|
1252 | 1242 | pr_err("impossible disposition %d in state %d, event_type %d, event_id %d\n", |
---|
1253 | 1243 | status, state, event_type, subtype.chunk); |
---|
1254 | | - BUG(); |
---|
| 1244 | + error = status; |
---|
| 1245 | + if (error >= 0) |
---|
| 1246 | + error = -EINVAL; |
---|
| 1247 | + WARN_ON_ONCE(1); |
---|
1255 | 1248 | break; |
---|
1256 | 1249 | } |
---|
1257 | 1250 | |
---|
.. | .. |
---|
1264 | 1257 | ********************************************************************/ |
---|
1265 | 1258 | |
---|
1266 | 1259 | /* This is the side-effect interpreter. */ |
---|
1267 | | -static int sctp_cmd_interpreter(enum sctp_event event_type, |
---|
| 1260 | +static int sctp_cmd_interpreter(enum sctp_event_type event_type, |
---|
1268 | 1261 | union sctp_subtype subtype, |
---|
1269 | 1262 | enum sctp_state state, |
---|
1270 | 1263 | struct sctp_endpoint *ep, |
---|
.. | .. |
---|
1530 | 1523 | |
---|
1531 | 1524 | if (timer_pending(timer)) |
---|
1532 | 1525 | break; |
---|
1533 | | - /* fall through */ |
---|
| 1526 | + fallthrough; |
---|
1534 | 1527 | |
---|
1535 | 1528 | case SCTP_CMD_TIMER_START: |
---|
1536 | 1529 | timer = &asoc->timers[cmd->obj.to]; |
---|