aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/sctputil.c
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@FreeBSD.org>2021-07-09 21:17:35 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2021-07-09 21:19:25 +0000
commit105b68b42dd11bce5c554b1ef0ddf73aa069d7da (patch)
treeb5abcb3da01486d91cfdd5bd2ab4ab8cd9c84816 /sys/netinet/sctputil.c
parent82626fef6253a9172163df137097f54e93e3c209 (diff)
Diffstat (limited to 'sys/netinet/sctputil.c')
-rw-r--r--sys/netinet/sctputil.c52
1 files changed, 33 insertions, 19 deletions
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