aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@FreeBSD.org>2023-08-25 15:31:19 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2024-01-11 12:50:49 +0000
commit122e6541316a09ba32f89ab7e42571d83fd2e174 (patch)
treee1251e32898f1e278045eb7fa423c87efdb756c6
parent6ebc414625386c9c90f115e1f132af22dc881b43 (diff)
downloadsrc-122e6541316a09ba32f89ab7e42571d83fd2e174.tar.gz
src-122e6541316a09ba32f89ab7e42571d83fd2e174.zip
sctp: cleanup
In particular, don't use a socket level flag, use the inp level one. After adding appropriate locking, this will close a race condition. (cherry picked from commit e40d16ad6ee952f315356ef091fa282f28fac0d5)
-rw-r--r--sys/netinet/sctputil.c60
1 files changed, 27 insertions, 33 deletions
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 380aee5f671d..3769faeb1842 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -4052,14 +4052,14 @@ void
sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
uint32_t error, void *data, int so_locked)
{
- if ((stcb == NULL) ||
- (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
- (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
- (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
- /* If the socket is gone we are out of here */
- return;
- }
- if (stcb->sctp_socket->so_rcv.sb_state & SBS_CANTRCVMORE) {
+ struct sctp_inpcb *inp;
+ struct sctp_nets *net;
+
+ KASSERT(stcb != NULL, ("stcb == NULL"));
+ SCTP_TCB_LOCK_ASSERT(stcb);
+
+ inp = stcb->sctp_ep;
+ if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
return;
}
if ((SCTP_GET_STATE(stcb) == SCTP_STATE_COOKIE_WAIT) ||
@@ -4071,6 +4071,12 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
return;
}
}
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ)) {
+ return;
+ }
+
switch (notification) {
case SCTP_NOTIFY_ASSOC_UP:
if (stcb->asoc.assoc_up_sent == 0) {
@@ -4089,32 +4095,20 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, false, false, so_locked);
break;
case SCTP_NOTIFY_INTERFACE_DOWN:
- {
- struct sctp_nets *net;
-
- net = (struct sctp_nets *)data;
- sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE,
- (struct sockaddr *)&net->ro._l_addr, error, so_locked);
- break;
- }
+ net = (struct sctp_nets *)data;
+ sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE,
+ &net->ro._l_addr.sa, error, so_locked);
+ break;
case SCTP_NOTIFY_INTERFACE_UP:
- {
- struct sctp_nets *net;
-
- net = (struct sctp_nets *)data;
- sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE,
- (struct sockaddr *)&net->ro._l_addr, error, so_locked);
- break;
- }
+ net = (struct sctp_nets *)data;
+ sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE,
+ &net->ro._l_addr.sa, error, so_locked);
+ break;
case SCTP_NOTIFY_INTERFACE_CONFIRMED:
- {
- struct sctp_nets *net;
-
- net = (struct sctp_nets *)data;
- sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED,
- (struct sockaddr *)&net->ro._l_addr, error, so_locked);
- break;
- }
+ net = (struct sctp_nets *)data;
+ sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED,
+ &net->ro._l_addr.sa, error, so_locked);
+ break;
case SCTP_NOTIFY_SPECIAL_SP_FAIL:
sctp_notify_send_failed2(stcb, error,
(struct sctp_stream_queue_pending *)data, so_locked);
@@ -4225,7 +4219,7 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
SCTPDBG(SCTP_DEBUG_UTIL1, "%s: unknown notification %xh (%u)\n",
__func__, notification, notification);
break;
- } /* end switch */
+ }
}
void