From 76c5508f62f6cc12d4255b0b78da44d452cccfdb Mon Sep 17 00:00:00 2001 From: Jonathan Lennox Date: Fri, 19 Apr 2024 23:39:53 -0400 Subject: [PATCH 1/2] Centralize socket upcall methods into utility functions. --- usrsctplib/netinet/sctp_input.c | 43 +--------- usrsctplib/netinet/sctp_usrreq.c | 17 +--- usrsctplib/netinet/sctputil.c | 126 ++++++++++++++++++----------- usrsctplib/netinet/sctputil.h | 8 ++ usrsctplib/netinet6/sctp6_usrreq.c | 17 +--- 5 files changed, 91 insertions(+), 120 deletions(-) diff --git a/usrsctplib/netinet/sctp_input.c b/usrsctplib/netinet/sctp_input.c index 3b134c498..8d004115e 100755 --- a/usrsctplib/netinet/sctp_input.c +++ b/usrsctplib/netinet/sctp_input.c @@ -5931,20 +5931,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } } #if defined(__Userspace__) - if ((stcb != NULL) && - ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (stcb->sctp_socket != NULL)) { - ACCEPT_LOCK(); - if (stcb->sctp_socket->so_head != NULL) { - upcall_socket = stcb->sctp_socket->so_head; - } else { - upcall_socket = stcb->sctp_socket; - } - SOCK_LOCK(upcall_socket); - soref(upcall_socket); - SOCK_UNLOCK(upcall_socket); - ACCEPT_UNLOCK(); - } + upcall_socket = sctp_get_upcall_socket_or_accept_head(stcb); #endif if (IS_SCTP_CONTROL(ch)) { /* process the control portion of the SCTP packet */ @@ -6036,19 +6023,8 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt goto out; } #if defined(__Userspace__) - if ((upcall_socket == NULL) && - ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (stcb->sctp_socket != NULL)) { - ACCEPT_LOCK(); - if (stcb->sctp_socket->so_head != NULL) { - upcall_socket = stcb->sctp_socket->so_head; - } else { - upcall_socket = stcb->sctp_socket; - } - SOCK_LOCK(upcall_socket); - soref(upcall_socket); - SOCK_UNLOCK(upcall_socket); - ACCEPT_UNLOCK(); + if (upcall_socket != NULL) { + upcall_socket = sctp_get_upcall_socket_or_accept_head(stcb); } #endif @@ -6191,18 +6167,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt SCTP_TCB_UNLOCK(stcb); } #if defined(__Userspace__) - if (upcall_socket != NULL) { - if (upcall_socket->so_upcall != NULL) { - if (soreadable(upcall_socket) || - sowriteable(upcall_socket) || - upcall_socket->so_error) { - (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT); - } - } - ACCEPT_LOCK(); - SOCK_LOCK(upcall_socket); - sorele(upcall_socket); - } + sctp_do_upcall_socket_if_readable_writeable_or_error(upcall_socket); #endif if (inp_decr != NULL) { /* reduce ref-count */ diff --git a/usrsctplib/netinet/sctp_usrreq.c b/usrsctplib/netinet/sctp_usrreq.c index df4424e2f..9b1eb0f30 100755 --- a/usrsctplib/netinet/sctp_usrreq.c +++ b/usrsctplib/netinet/sctp_usrreq.c @@ -554,22 +554,7 @@ sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip) inner_ip->ip_len, (uint32_t)ntohs(icmp->icmp_nextmtu)); #if defined(__Userspace__) - if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (stcb->sctp_socket != NULL)) { - struct socket *upcall_socket; - - upcall_socket = stcb->sctp_socket; - SOCK_LOCK(upcall_socket); - soref(upcall_socket); - SOCK_UNLOCK(upcall_socket); - if ((upcall_socket->so_upcall != NULL) && - (upcall_socket->so_error != 0)) { - (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT); - } - ACCEPT_LOCK(); - SOCK_LOCK(upcall_socket); - sorele(upcall_socket); - } + stcp_upcall_socket_if_error(stcb); #endif } else { if ((stcb == NULL) && (inp != NULL)) { diff --git a/usrsctplib/netinet/sctputil.c b/usrsctplib/netinet/sctputil.c index 1abfea3f2..6c5de480a 100755 --- a/usrsctplib/netinet/sctputil.c +++ b/usrsctplib/netinet/sctputil.c @@ -1881,14 +1881,7 @@ sctp_timeout_handler(void *t) SCTP_OS_TIMER_DEACTIVATE(&tmr->timer); #if defined(__Userspace__) - if ((stcb != NULL) && - ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (stcb->sctp_socket != NULL)) { - upcall_socket = stcb->sctp_socket; - SOCK_LOCK(upcall_socket); - soref(upcall_socket); - SOCK_UNLOCK(upcall_socket); - } + upcall_socket = sctp_get_upcall_socket(stcb); #endif /* call the handler for the appropriate timer type */ switch (type) { @@ -2206,15 +2199,7 @@ sctp_timeout_handler(void *t) out_decr: #if defined(__Userspace__) - if (upcall_socket != NULL) { - if ((upcall_socket->so_upcall != NULL) && - (upcall_socket->so_error != 0)) { - (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT); - } - ACCEPT_LOCK(); - SOCK_LOCK(upcall_socket); - sorele(upcall_socket); - } + sctp_do_upcall_socket_if_error(upcall_socket); #endif /* These reference counts were incremented in sctp_timer_start(). */ if (inp != NULL) { @@ -8281,22 +8266,7 @@ sctp_recv_icmp_tunneled_packet(udp_tun_icmp_param_t param) ntohs(inner_ip->ip_len), (uint32_t)ntohs(icmp->icmp_nextmtu)); #if defined(__Userspace__) - if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (stcb->sctp_socket != NULL)) { - struct socket *upcall_socket; - - upcall_socket = stcb->sctp_socket; - SOCK_LOCK(upcall_socket); - soref(upcall_socket); - SOCK_UNLOCK(upcall_socket); - if ((upcall_socket->so_upcall != NULL) && - (upcall_socket->so_error != 0)) { - (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT); - } - ACCEPT_LOCK(); - SOCK_LOCK(upcall_socket); - sorele(upcall_socket); - } + sctp_upcall_socket_if_error(stcb); #endif } else { if ((stcb == NULL) && (inp != NULL)) { @@ -8453,22 +8423,7 @@ sctp_recv_icmp6_tunneled_packet(udp_tun_icmp_param_t param) sctp6_notify(inp, stcb, net, type, code, ntohl(ip6cp->ip6c_icmp6->icmp6_mtu)); #if defined(__Userspace__) - if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (stcb->sctp_socket != NULL)) { - struct socket *upcall_socket; - - upcall_socket = stcb->sctp_socket; - SOCK_LOCK(upcall_socket); - soref(upcall_socket); - SOCK_UNLOCK(upcall_socket); - if ((upcall_socket->so_upcall != NULL) && - (upcall_socket->so_error != 0)) { - (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT); - } - ACCEPT_LOCK(); - SOCK_LOCK(upcall_socket); - sorele(upcall_socket); - } + sctp_upcall_socket_if_error(stcb); #endif } else { if ((stcb == NULL) && (inp != NULL)) { @@ -8723,3 +8678,76 @@ sctp_add_substate(struct sctp_tcb *stcb, int substate) #endif } + +#if defined(__Userspace__) +struct socket* sctp_get_upcall_socket(struct sctp_tcb * stcb) +{ + struct socket* upcall_socket = NULL; + if ((stcb != NULL) && + ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && + (stcb->sctp_socket != NULL)) { + upcall_socket = stcb->sctp_socket; + SOCK_LOCK(upcall_socket); + soref(upcall_socket); + SOCK_UNLOCK(upcall_socket); + } + return upcall_socket; +} + +struct socket* sctp_get_upcall_socket_or_accept_head(struct sctp_tcb * stcb) +{ + struct socket* upcall_socket = NULL; + if ((stcb != NULL) && + ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && + (stcb->sctp_socket != NULL)) { + ACCEPT_LOCK(); + if (stcb->sctp_socket->so_head != NULL) { + upcall_socket = stcb->sctp_socket->so_head; + } else { + upcall_socket = stcb->sctp_socket; + } + SOCK_LOCK(upcall_socket); + soref(upcall_socket); + SOCK_UNLOCK(upcall_socket); + ACCEPT_UNLOCK(); + } + return upcall_socket; +} + + +void sctp_do_upcall_socket_if_error(struct socket *upcall_socket) +{ + if (upcall_socket != NULL) { + if ((upcall_socket->so_upcall != NULL) && + (upcall_socket->so_error != 0)) { + (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT); + } + ACCEPT_LOCK(); + SOCK_LOCK(upcall_socket); + sorele(upcall_socket); + } +} + +void sctp_do_upcall_socket_if_readable_writeable_or_error(struct socket *upcall_socket) +{ + if (upcall_socket != NULL) { + if (upcall_socket->so_upcall != NULL) { + if (soreadable(upcall_socket) || + sowriteable(upcall_socket) || + upcall_socket->so_error != 0) { + (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT); + } + } + ACCEPT_LOCK(); + SOCK_LOCK(upcall_socket); + sorele(upcall_socket); + } +} + +void sctp_upcall_socket_if_error(struct sctp_tcb *stcb) +{ + struct socket *upcall_socket; + upcall_socket = sctp_get_upcall_socket(stcb); + sctp_do_upcall_socket_if_error(upcall_socket); +} +#endif diff --git a/usrsctplib/netinet/sctputil.h b/usrsctplib/netinet/sctputil.h index 5e0fc81f9..e624f896d 100755 --- a/usrsctplib/netinet/sctputil.h +++ b/usrsctplib/netinet/sctputil.h @@ -371,5 +371,13 @@ uint32_t sctp_msecs_to_ticks(uint32_t); uint32_t sctp_ticks_to_secs(uint32_t); uint32_t sctp_secs_to_ticks(uint32_t); +#if defined(__Userspace__) +void sctp_upcall_socket_if_error(struct sctp_tcb *); +struct socket* sctp_get_upcall_socket(struct sctp_tcb *); +struct socket* sctp_get_upcall_socket_or_accept_head(struct sctp_tcb * stcb); +void sctp_do_upcall_socket_if_error(struct socket *); +void sctp_do_upcall_socket_if_readable_writeable_or_error(struct socket *); +#endif + #endif /* _KERNEL */ #endif diff --git a/usrsctplib/netinet6/sctp6_usrreq.c b/usrsctplib/netinet6/sctp6_usrreq.c index e130b41ac..4f2ce1ee0 100644 --- a/usrsctplib/netinet6/sctp6_usrreq.c +++ b/usrsctplib/netinet6/sctp6_usrreq.c @@ -614,22 +614,7 @@ sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d) ip6cp->ip6c_icmp6->icmp6_code, ntohl(ip6cp->ip6c_icmp6->icmp6_mtu)); #if defined(__Userspace__) - if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (stcb->sctp_socket != NULL)) { - struct socket *upcall_socket; - - upcall_socket = stcb->sctp_socket; - SOCK_LOCK(upcall_socket); - soref(upcall_socket); - SOCK_UNLOCK(upcall_socket); - if ((upcall_socket->so_upcall != NULL) && - (upcall_socket->so_error != 0)) { - (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT); - } - ACCEPT_LOCK(); - SOCK_LOCK(upcall_socket); - sorele(upcall_socket); - } + stcp_upcall_socket_if_error(stcb); #endif } else { if ((stcb == NULL) && (inp != NULL)) { From a3b68cc7cf73f788c547f8e6aab3ab6e1163bbeb Mon Sep 17 00:00:00 2001 From: Jonathan Lennox Date: Mon, 22 Apr 2024 14:08:32 -0400 Subject: [PATCH 2/2] Add configure option to disable upcalls. --- configure.ac | 9 +++++++++ usrsctplib/netinet/sctputil.c | 12 ++++++++++++ usrsctplib/user_socket.c | 5 +++++ 3 files changed, 26 insertions(+) diff --git a/configure.ac b/configure.ac index 55f00991f..29364fe84 100644 --- a/configure.ac +++ b/configure.ac @@ -140,6 +140,15 @@ AC_ARG_ENABLE(programs, enable_programs=$enableval,enable_programs=yes) AM_CONDITIONAL([COND_PROGRAMS], [test "$enable_programs" = yes]) +AC_ARG_ENABLE(upcalls, + AC_HELP_STRING( [--enable-upcalls], + [enable socket upcall support @<:@default=yes@:>@]), + enable_upcalls=$enableval,enable_upcalls=yes) +if test x$enable_upcalls = xno; then + APPCFLAGS="$APPCFLAGS -DDISABLE_UPCALLS" + AC_DEFINE(DISABLE_UPCALLS, 1, [Disable upcall support]) +fi + AC_CHECK_TYPE(size_t) AC_CHECK_TYPE(ssize_t) diff --git a/usrsctplib/netinet/sctputil.c b/usrsctplib/netinet/sctputil.c index 6c5de480a..c190f1e03 100755 --- a/usrsctplib/netinet/sctputil.c +++ b/usrsctplib/netinet/sctputil.c @@ -8682,6 +8682,9 @@ sctp_add_substate(struct sctp_tcb *stcb, int substate) #if defined(__Userspace__) struct socket* sctp_get_upcall_socket(struct sctp_tcb * stcb) { +#ifdef DISABLE_UPCALLS + return NULL; +#else struct socket* upcall_socket = NULL; if ((stcb != NULL) && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && @@ -8692,10 +8695,14 @@ struct socket* sctp_get_upcall_socket(struct sctp_tcb * stcb) SOCK_UNLOCK(upcall_socket); } return upcall_socket; +#endif } struct socket* sctp_get_upcall_socket_or_accept_head(struct sctp_tcb * stcb) { +#ifdef DISABLE_UPCALLS + return NULL; +#else struct socket* upcall_socket = NULL; if ((stcb != NULL) && ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && @@ -8712,11 +8719,13 @@ struct socket* sctp_get_upcall_socket_or_accept_head(struct sctp_tcb * stcb) ACCEPT_UNLOCK(); } return upcall_socket; +#endif } void sctp_do_upcall_socket_if_error(struct socket *upcall_socket) { +#ifndef DISABLE_UPCALLS if (upcall_socket != NULL) { if ((upcall_socket->so_upcall != NULL) && (upcall_socket->so_error != 0)) { @@ -8726,10 +8735,12 @@ void sctp_do_upcall_socket_if_error(struct socket *upcall_socket) SOCK_LOCK(upcall_socket); sorele(upcall_socket); } +#endif } void sctp_do_upcall_socket_if_readable_writeable_or_error(struct socket *upcall_socket) { +#ifndef DISABLE_UPCALLS if (upcall_socket != NULL) { if (upcall_socket->so_upcall != NULL) { if (soreadable(upcall_socket) || @@ -8742,6 +8753,7 @@ void sctp_do_upcall_socket_if_readable_writeable_or_error(struct socket *upcall_ SOCK_LOCK(upcall_socket); sorele(upcall_socket); } +#endif } void sctp_upcall_socket_if_error(struct sctp_tcb *stcb) diff --git a/usrsctplib/user_socket.c b/usrsctplib/user_socket.c index cde6ecc41..ecfc17258 100755 --- a/usrsctplib/user_socket.c +++ b/usrsctplib/user_socket.c @@ -3369,6 +3369,10 @@ usrsctp_set_upcall(struct socket *so, void (*upcall)(struct socket *, void *, in return (-1); } +#ifdef DISABLE_UPCALLS + errno = ENOSYS; + return -1; +#else SOCK_LOCK(so); so->so_upcall = upcall; so->so_upcallarg = arg; @@ -3377,6 +3381,7 @@ usrsctp_set_upcall(struct socket *so, void (*upcall)(struct socket *, void *, in SOCK_UNLOCK(so); return (0); +#endif } #define USRSCTP_TUNABLE_SET_DEF(__field, __prefix) \