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/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..c190f1e03 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,88 @@ sctp_add_substate(struct sctp_tcb *stcb, int substate) #endif } + +#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) && + (stcb->sctp_socket != NULL)) { + upcall_socket = stcb->sctp_socket; + SOCK_LOCK(upcall_socket); + soref(upcall_socket); + 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) && + (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; +#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)) { + (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT); + } + ACCEPT_LOCK(); + 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) || + 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); + } +#endif +} + +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)) { 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) \