The branch main has been updated by tuexen:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=105b68b42dd11bce5c554b1ef0ddf73aa069d7da

commit 105b68b42dd11bce5c554b1ef0ddf73aa069d7da
Author:     Michael Tuexen <[email protected]>
AuthorDate: 2021-07-09 21:17:35 +0000
Commit:     Michael Tuexen <[email protected]>
CommitDate: 2021-07-09 21:19:25 +0000

    sctp: Fix errno in case of association setup failures
    
    Do not report always ETIMEDOUT, but only when appropriate. In
    other cases report ECONNABORTED.
    
    MFC after:      3 days
---
 sys/netinet/sctp_asconf.c    |  2 +-
 sys/netinet/sctp_constants.h |  1 +
 sys/netinet/sctp_indata.c    | 34 ++++++++++++++---------------
 sys/netinet/sctp_input.c     |  8 +++----
 sys/netinet/sctp_output.c    | 10 ++++-----
 sys/netinet/sctp_pcb.c       |  4 ++--
 sys/netinet/sctp_timer.c     |  4 ++--
 sys/netinet/sctp_usrreq.c    |  4 ++--
 sys/netinet/sctputil.c       | 52 ++++++++++++++++++++++++++++----------------
 sys/netinet/sctputil.h       |  4 ++--
 sys/netinet6/sctp6_usrreq.c  |  2 +-
 11 files changed, 70 insertions(+), 55 deletions(-)

diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c
index c06ddf7b1f2e..0915e187ee40 100644
--- a/sys/netinet/sctp_asconf.c
+++ b/sys/netinet/sctp_asconf.c
@@ -1704,7 +1704,7 @@ sctp_handle_asconf_ack(struct mbuf *m, int offset,
                SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected 
next serial number! Aborting asoc!\n");
                SCTP_SNPRINTF(msg, sizeof(msg), "Never sent serial number 
%8.8x", serial_num);
                op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, 
msg);
-               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, false, 
SCTP_SO_NOT_LOCKED);
                *abort_no_unlock = 1;
                return;
        }
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 197b93791944..1ff3f3918ef6 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -716,6 +716,7 @@ __FBSDID("$FreeBSD$");
 #define SCTP_NOTIFY_NO_PEER_AUTH                25
 #define SCTP_NOTIFY_SENDER_DRY                  26
 #define SCTP_NOTIFY_REMOTE_ERROR                27
+#define SCTP_NOTIFY_ASSOC_TIMEDOUT              28
 
 /* This is the value for messages that are NOT completely
  * copied down where we will start to split the message.
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 6997a0099c88..fb1327a94475 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -444,7 +444,7 @@ sctp_abort_in_reasm(struct sctp_tcb *stcb,
        chk->data = NULL;
        sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
        stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + SCTP_LOC_1;
-       sctp_abort_an_association(stcb->sctp_ep, stcb, oper, 
SCTP_SO_NOT_LOCKED);
+       sctp_abort_an_association(stcb->sctp_ep, stcb, oper, false, 
SCTP_SO_NOT_LOCKED);
        *abort_flag = 1;
 }
 
@@ -533,7 +533,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb,
                }
                op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, 
msg);
                stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + 
SCTP_LOC_2;
-               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, false, 
SCTP_SO_NOT_LOCKED);
                *abort_flag = 1;
                return;
        }
@@ -623,7 +623,7 @@ sctp_queue_data_to_stream(struct sctp_tcb *stcb,
                        sctp_clean_up_control(stcb, control);
                        op_err = 
sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
                        stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA 
+ SCTP_LOC_3;
-                       sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+                       sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
false, SCTP_SO_NOT_LOCKED);
                        *abort_flag = 1;
                }
        }
@@ -1745,7 +1745,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct 
sctp_association *asoc,
                 */
                op_err = sctp_generate_no_user_data_cause(tsn);
                stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + 
SCTP_LOC_16;
-               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, false, 
SCTP_SO_NOT_LOCKED);
                *abort_flag = 1;
                return (0);
        }
@@ -1811,7 +1811,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct 
sctp_association *asoc,
                 * receiver. Send peer an ABORT!
                 */
                op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
-               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, false, 
SCTP_SO_NOT_LOCKED);
                *abort_flag = 1;
                return (0);
        }
@@ -1882,7 +1882,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct 
sctp_association *asoc,
                err_out:
                                op_err = 
sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
                                stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_17;
-                               sctp_abort_an_association(stcb->sctp_ep, stcb, 
op_err, SCTP_SO_NOT_LOCKED);
+                               sctp_abort_an_association(stcb->sctp_ep, stcb, 
op_err, false, SCTP_SO_NOT_LOCKED);
                                *abort_flag = 1;
                                return (0);
                        }
@@ -2017,7 +2017,7 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct 
sctp_association *asoc,
                }
                op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, 
msg);
                stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + 
SCTP_LOC_18;
-               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, false, 
SCTP_SO_NOT_LOCKED);
                *abort_flag = 1;
                return (0);
        }
@@ -2736,7 +2736,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int 
*offset, int length,
                        SCTP_SNPRINTF(msg, sizeof(msg), "%s", "DATA chunk 
received when I-DATA was negotiated");
                        op_err = 
sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
                        stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA 
+ SCTP_LOC_21;
-                       sctp_abort_an_association(inp, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+                       sctp_abort_an_association(inp, stcb, op_err, false, 
SCTP_SO_NOT_LOCKED);
                        return (2);
                }
                if ((asoc->idata_supported == 0) &&
@@ -2747,7 +2747,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int 
*offset, int length,
                        SCTP_SNPRINTF(msg, sizeof(msg), "%s", "I-DATA chunk 
received when DATA was negotiated");
                        op_err = 
sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
                        stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA 
+ SCTP_LOC_22;
-                       sctp_abort_an_association(inp, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+                       sctp_abort_an_association(inp, stcb, op_err, false, 
SCTP_SO_NOT_LOCKED);
                        return (2);
                }
                if ((ch->chunk_type == SCTP_DATA) ||
@@ -2772,7 +2772,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int 
*offset, int length,
                                    chk_length);
                                op_err = 
sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
                                stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_23;
-                               sctp_abort_an_association(inp, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+                               sctp_abort_an_association(inp, stcb, op_err, 
false, SCTP_SO_NOT_LOCKED);
                                return (2);
                        }
 #ifdef SCTP_AUDITING_ENABLED
@@ -2841,7 +2841,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int 
*offset, int length,
                                        SCTP_SNPRINTF(msg, sizeof(msg), "DATA 
chunk followed by chunk of type %2.2x",
                                            ch->chunk_type);
                                        op_err = 
sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
-                                       sctp_abort_an_association(inp, stcb, 
op_err, SCTP_SO_NOT_LOCKED);
+                                       sctp_abort_an_association(inp, stcb, 
op_err, false, SCTP_SO_NOT_LOCKED);
                                        return (2);
                                }
                        default:
@@ -2860,7 +2860,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int 
*offset, int length,
                                        SCTP_SNPRINTF(msg, sizeof(msg), "Chunk 
of length %u", chk_length);
                                        op_err = 
sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
                                        stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_INDATA + SCTP_LOC_24;
-                                       sctp_abort_an_association(inp, stcb, 
op_err, SCTP_SO_NOT_LOCKED);
+                                       sctp_abort_an_association(inp, stcb, 
op_err, false, SCTP_SO_NOT_LOCKED);
                                        return (2);
                                }
                                if (ch->chunk_type & 0x40) {
@@ -4003,7 +4003,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t 
cumack,
                    cumack, send_s);
                op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, 
msg);
                stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + 
SCTP_LOC_25;
-               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, false, 
SCTP_SO_NOT_LOCKED);
                return;
        }
        asoc->this_sack_highest_gap = cumack;
@@ -4308,7 +4308,7 @@ again:
                        /* XXX */
                        op_err = 
sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
                        stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA 
+ SCTP_LOC_28;
-                       sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+                       sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
false, SCTP_SO_NOT_LOCKED);
                        return;
                }
                if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) &&
@@ -4524,7 +4524,7 @@ hopeless_peer:
                    cum_ack, send_s);
                op_err = sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, 
msg);
                stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA + 
SCTP_LOC_29;
-               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, false, 
SCTP_SO_NOT_LOCKED);
                return;
        }
        /**********************/
@@ -4985,7 +4985,7 @@ hopeless_peer:
                        /* XXX */
                        op_err = 
sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
                        stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA 
+ SCTP_LOC_35;
-                       sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+                       sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
false, SCTP_SO_NOT_LOCKED);
                        return;
                }
                if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) &&
@@ -5533,7 +5533,7 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
                            new_cum_tsn, asoc->highest_tsn_inside_map);
                        op_err = 
sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
                        stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_INDATA 
+ SCTP_LOC_37;
-                       sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+                       sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
false, SCTP_SO_NOT_LOCKED);
                        return;
                }
                SCTP_STAT_INCR(sctps_fwdtsn_map_over);
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 6a0b5d41052a..ed15b81ba3e5 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -414,7 +414,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int 
offset,
            &nat_friendly, &cookie_found);
        if (abort_flag) {
                /* Send an abort and notify peer */
-               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, false, 
SCTP_SO_NOT_LOCKED);
                *abort_no_unlock = 1;
                return (-1);
        }
@@ -785,7 +785,7 @@ sctp_handle_abort(struct sctp_abort_chunk *abort,
        sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL,
            SCTP_FROM_SCTP_INPUT + SCTP_LOC_7);
        /* notify user of the abort and clean up... */
-       sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED);
+       sctp_abort_notification(stcb, true, false, error, abort, 
SCTP_SO_NOT_LOCKED);
        /* free the tcb */
        SCTP_STAT_INCR_COUNTER32(sctps_aborted);
        if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
@@ -1140,7 +1140,7 @@ sctp_handle_error(struct sctp_chunkhdr *ch,
                                asoc->stale_cookie_count++;
                                if (asoc->stale_cookie_count >
                                    asoc->max_init_times) {
-                                       sctp_abort_notification(stcb, 0, 0, 
NULL, SCTP_SO_NOT_LOCKED);
+                                       sctp_abort_notification(stcb, false, 
true, 0, NULL, SCTP_SO_NOT_LOCKED);
                                        /* now free the asoc */
                                        (void)sctp_free_assoc(stcb->sctp_ep, 
stcb, SCTP_NORMAL_PROC,
                                            SCTP_FROM_SCTP_INPUT + SCTP_LOC_12);
@@ -5106,7 +5106,7 @@ process_control_chunks:
                                        SCTP_SNPRINTF(msg, sizeof(msg), "%s", 
"I-FORWARD-TSN chunk received when FORWARD-TSN was negotiated");
                                }
                                op_err = 
sctp_generate_cause(SCTP_CAUSE_PROTOCOL_VIOLATION, msg);
-                               sctp_abort_an_association(inp, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+                               sctp_abort_an_association(inp, stcb, op_err, 
false, SCTP_SO_NOT_LOCKED);
                                *offset = length;
                                return (NULL);
                        }
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index c69db88f7d7d..e34534e80fa3 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -6631,7 +6631,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct 
sctp_tcb *stcb, void *ptr,
                 * us.
                 */
                atomic_add_int(&stcb->asoc.refcnt, 1);
-               sctp_abort_an_association(inp, stcb, m, SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(inp, stcb, m, false, 
SCTP_SO_NOT_LOCKED);
                /*
                 * sctp_abort_an_association calls sctp_free_asoc() free
                 * association will NOT free it since we incremented the
@@ -6715,7 +6715,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct 
sctp_tcb *stcb, void *ptr,
                                                    msg);
                                                
atomic_add_int(&stcb->asoc.refcnt, 1);
                                                
sctp_abort_an_association(stcb->sctp_ep, stcb,
-                                                   op_err, SCTP_SO_NOT_LOCKED);
+                                                   op_err, false, 
SCTP_SO_NOT_LOCKED);
                                                
atomic_add_int(&stcb->asoc.refcnt, -1);
                                                goto no_chunk_output;
                                        }
@@ -9555,7 +9555,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
                            msg);
                        atomic_add_int(&stcb->asoc.refcnt, 1);
                        sctp_abort_an_association(stcb->sctp_ep, stcb, op_err,
-                           so_locked);
+                           false, so_locked);
                        SCTP_TCB_LOCK(stcb);
                        atomic_subtract_int(&stcb->asoc.refcnt, 1);
                        return (SCTP_RETRAN_EXIT);
@@ -12967,7 +12967,7 @@ sctp_lower_sosend(struct socket *so,
                free_cnt_applied = 0;
                /* release this lock, otherwise we hang on ourselves */
                NET_EPOCH_ENTER(et);
-               sctp_abort_an_association(stcb->sctp_ep, stcb, mm, 
SCTP_SO_LOCKED);
+               sctp_abort_an_association(stcb->sctp_ep, stcb, mm, false, 
SCTP_SO_LOCKED);
                NET_EPOCH_EXIT(et);
                /* now relock the stcb so everything is sane */
                hold_tcblock = 0;
@@ -13544,7 +13544,7 @@ dataless_eof:
                                            msg);
                                        NET_EPOCH_ENTER(et);
                                        
sctp_abort_an_association(stcb->sctp_ep, stcb,
-                                           op_err, SCTP_SO_LOCKED);
+                                           op_err, false, SCTP_SO_LOCKED);
                                        NET_EPOCH_EXIT(et);
                                        /*
                                         * now relock the stcb so everything
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index ce4850469144..bdc575de615f 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -6198,7 +6198,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, 
struct mbuf *m,
                                                        op_err = 
sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
                                                            msg);
                                                        
sctp_abort_an_association(stcb_tmp->sctp_ep,
-                                                           stcb_tmp, op_err,
+                                                           stcb_tmp, op_err, 
false,
                                                            SCTP_SO_NOT_LOCKED);
                                                        goto add_it_now;
                                                }
@@ -6298,7 +6298,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, 
struct mbuf *m,
                                                        op_err = 
sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
                                                            msg);
                                                        
sctp_abort_an_association(stcb_tmp->sctp_ep,
-                                                           stcb_tmp, op_err,
+                                                           stcb_tmp, op_err, 
false,
                                                            SCTP_SO_NOT_LOCKED);
                                                        goto add_it_now6;
                                                }
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index 582abd8e8854..2d3836829e89 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -157,7 +157,7 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct 
sctp_tcb *stcb,
                op_err = 
sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
                    "Association error counter exceeded");
                inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_2;
-               sctp_abort_an_association(inp, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(inp, stcb, op_err, true, 
SCTP_SO_NOT_LOCKED);
                return (1);
        }
        return (0);
@@ -1071,7 +1071,7 @@ sctp_cookie_timer(struct sctp_inpcb *inp,
                        op_err = 
sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
                            "Cookie timer expired, but no cookie");
                        inp->last_abort_code = SCTP_FROM_SCTP_TIMER + 
SCTP_LOC_3;
-                       sctp_abort_an_association(inp, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+                       sctp_abort_an_association(inp, stcb, op_err, false, 
SCTP_SO_NOT_LOCKED);
                } else {
 #ifdef INVARIANTS
                        panic("Cookie timer expires in wrong state?");
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 6308cabf5d63..822a8ffb534f 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -189,7 +189,7 @@ sctp_notify(struct sctp_inpcb *inp,
        } else if ((icmp_code == ICMP_UNREACH_PROTOCOL) ||
            (icmp_code == ICMP_UNREACH_PORT)) {
                /* Treat it like an ABORT. */
-               sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
+               sctp_abort_notification(stcb, true, false, 0, NULL, 
SCTP_SO_NOT_LOCKED);
                (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
                    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
                /* no need to unlock here, since the TCB is gone */
@@ -960,7 +960,7 @@ sctp_shutdown(struct socket *so)
                                stcb->sctp_ep->last_abort_code = 
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
                                SCTP_INP_RUNLOCK(inp);
                                sctp_abort_an_association(stcb->sctp_ep, stcb,
-                                   op_err, SCTP_SO_LOCKED);
+                                   op_err, false, SCTP_SO_LOCKED);
                                NET_EPOCH_EXIT(et);
                                return (0);
                        }
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 21e49bdfcb23..ad4409f666df 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1998,7 +1998,7 @@ sctp_timeout_handler(void *t)
                SCTP_STAT_INCR(sctps_timoshutdownguard);
                op_err = 
sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
                    "Shutdown guard timer expired");
-               sctp_abort_an_association(inp, stcb, op_err, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_an_association(inp, stcb, op_err, true, 
SCTP_SO_NOT_LOCKED);
                /* no need to unlock on tcb its gone */
                goto out_decr;
        case SCTP_TIMER_TYPE_AUTOCLOSE:
@@ -3154,7 +3154,8 @@ sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf 
*last_mbuf)
 
 static void
 sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
-    uint16_t error, struct sctp_abort_chunk *abort, uint8_t from_peer, int 
so_locked)
+    uint16_t error, struct sctp_abort_chunk *abort,
+    bool from_peer, bool timedout, int so_locked)
 {
        struct mbuf *m_notify;
        struct sctp_assoc_change *sac;
@@ -3163,8 +3164,10 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb 
*stcb,
        uint16_t abort_len;
        unsigned int i;
 
-       KASSERT((abort == NULL) || (from_peer != 0),
+       KASSERT(abort == NULL || from_peer,
            ("sctp_notify_assoc_change: ABORT chunk provided for local 
termination"));
+       KASSERT(!from_peer || !timedout,
+           ("sctp_notify_assoc_change: timeouts can only be local"));
        if (stcb == NULL) {
                return;
        }
@@ -3272,8 +3275,7 @@ set_error:
                                stcb->sctp_socket->so_error = ECONNRESET;
                        }
                } else {
-                       if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
-                           (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) 
{
+                       if (timedout) {
                                SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, 
SCTP_FROM_SCTPUTIL, ETIMEDOUT);
                                stcb->sctp_socket->so_error = ETIMEDOUT;
                        } else {
@@ -4085,7 +4087,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb 
*stcb,
        switch (notification) {
        case SCTP_NOTIFY_ASSOC_UP:
                if (stcb->asoc.assoc_up_sent == 0) {
-                       sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, 
NULL, 0, so_locked);
+                       sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, 
NULL, false, false, so_locked);
                        stcb->asoc.assoc_up_sent = 1;
                }
                if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent 
== 0)) {
@@ -4097,7 +4099,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb 
*stcb,
                }
                break;
        case SCTP_NOTIFY_ASSOC_DOWN:
-               sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, 
0, so_locked);
+               sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, 
false, false, so_locked);
                break;
        case SCTP_NOTIFY_INTERFACE_DOWN:
                {
@@ -4150,21 +4152,29 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb 
*stcb,
        case SCTP_NOTIFY_ASSOC_LOC_ABORTED:
                if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
                    (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
-                       sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, 
error, data, 0, so_locked);
+                       sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, 
error, data, false, false, so_locked);
                } else {
-                       sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, 
data, 0, so_locked);
+                       sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, 
data, false, false, so_locked);
                }
                break;
        case SCTP_NOTIFY_ASSOC_REM_ABORTED:
                if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
                    (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
-                       sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, 
error, data, 1, so_locked);
+                       sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, 
error, data, true, false, so_locked);
                } else {
-                       sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, 
data, 1, so_locked);
+                       sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, 
data, true, false, so_locked);
+               }
+               break;
+       case SCTP_NOTIFY_ASSOC_TIMEDOUT:
+               if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
+                   (SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_ECHOED)) {
+                       sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, 
error, data, false, true, so_locked);
+               } else {
+                       sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, 
data, false, true, so_locked);
                }
                break;
        case SCTP_NOTIFY_ASSOC_RESTART:
-               sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, 
so_locked);
+               sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 
false, false, so_locked);
                if (stcb->asoc.auth_supported == 0) {
                        sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
                            NULL, so_locked);
@@ -4337,8 +4347,9 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t 
error, int so_locked)
 }
 
 void
-sctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t 
error,
-    struct sctp_abort_chunk *abort, int so_locked)
+sctp_abort_notification(struct sctp_tcb *stcb, bool from_peer, bool timeout,
+    uint16_t error, struct sctp_abort_chunk *abort,
+    int so_locked)
 {
        if (stcb == NULL) {
                return;
@@ -4361,7 +4372,11 @@ sctp_abort_notification(struct sctp_tcb *stcb, uint8_t 
from_peer, uint16_t error
        if (from_peer) {
                sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, 
abort, so_locked);
        } else {
-               sctp_ulp_notify(SCTP_NOTIFY_ASSOC_LOC_ABORTED, stcb, error, 
abort, so_locked);
+               if (timeout) {
+                       sctp_ulp_notify(SCTP_NOTIFY_ASSOC_TIMEDOUT, stcb, 
error, abort, so_locked);
+               } else {
+                       sctp_ulp_notify(SCTP_NOTIFY_ASSOC_LOC_ABORTED, stcb, 
error, abort, so_locked);
+               }
        }
 }
 
@@ -4395,7 +4410,7 @@ sctp_abort_association(struct sctp_inpcb *inp, struct 
sctp_tcb *stcb,
            vrf_id, port);
        if (stcb != NULL) {
                /* We have a TCB to abort, send notification too */
-               sctp_abort_notification(stcb, 0, cause_code, NULL, 
SCTP_SO_NOT_LOCKED);
+               sctp_abort_notification(stcb, false, false, cause_code, NULL, 
SCTP_SO_NOT_LOCKED);
                /* Ok, now lets free it */
                SCTP_STAT_INCR_COUNTER32(sctps_aborted);
                if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
@@ -4471,8 +4486,7 @@ none_in:
 
 void
 sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
-    struct mbuf *op_err,
-    int so_locked)
+    struct mbuf *op_err, bool timedout, int so_locked)
 {
        struct sctp_gen_error_cause *cause;
        uint16_t cause_code;
@@ -4503,7 +4517,7 @@ sctp_abort_an_association(struct sctp_inpcb *inp, struct 
sctp_tcb *stcb,
        }
        /* notify the ulp */
        if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
-               sctp_abort_notification(stcb, 0, cause_code, NULL, so_locked);
+               sctp_abort_notification(stcb, false, timedout, cause_code, 
NULL, so_locked);
        }
        /* now free the asoc */
 #ifdef SCTP_ASOCLOG_OF_TSNS
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index c81633223224..3319eb4f455b 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -167,7 +167,7 @@ void sctp_report_all_outbound(struct sctp_tcb *, uint16_t, 
int);
 int sctp_expand_mapping_array(struct sctp_association *, uint32_t);
 
 void
-sctp_abort_notification(struct sctp_tcb *, uint8_t, uint16_t,
+sctp_abort_notification(struct sctp_tcb *, bool, bool, uint16_t,
     struct sctp_abort_chunk *, int);
 
 /* We abort responding to an IP packet for some reason */
@@ -181,7 +181,7 @@ sctp_abort_association(struct sctp_inpcb *, struct sctp_tcb 
*, struct mbuf *,
 /* We choose to abort via user input */
 void
 sctp_abort_an_association(struct sctp_inpcb *, struct sctp_tcb *,
-    struct mbuf *, int);
+    struct mbuf *, bool, int);
 
 void
 sctp_handle_ootb(struct mbuf *, int, int,
diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c
index 09371ce249db..6f5d639e6367 100644
--- a/sys/netinet6/sctp6_usrreq.c
+++ b/sys/netinet6/sctp6_usrreq.c
@@ -200,7 +200,7 @@ sctp6_notify(struct sctp_inpcb *inp,
        case ICMP6_PARAM_PROB:
                /* Treat it like an ABORT. */
                if (icmp6_code == ICMP6_PARAMPROB_NEXTHEADER) {
-                       sctp_abort_notification(stcb, 1, 0, NULL, 
SCTP_SO_NOT_LOCKED);
+                       sctp_abort_notification(stcb, true, false, 0, NULL, 
SCTP_SO_NOT_LOCKED);
                        (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
                            SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
                } else {
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to