From 5d08768a2b4ca4e283e6ee487d619584ca3bae1d Mon Sep 17 00:00:00 2001 From: Michael Tuexen Date: Fri, 26 May 2017 16:29:00 +0000 Subject: [PATCH] Use the SCTP_PCB_FLAGS_ACCEPTING flags to check for listeners. While there, use a macro for checking the listen state to allow for easier changes if required. This done to help glebius@ with his listen changes. --- sys/netinet/sctp_input.c | 19 +++++++++---------- sys/netinet/sctp_os_bsd.h | 6 ++++-- sys/netinet/sctp_output.c | 2 +- sys/netinet/sctp_pcb.c | 4 ++-- sys/netinet/sctp_sysctl.c | 1 + sys/netinet/sctp_usrreq.c | 13 ++++++++----- 6 files changed, 25 insertions(+), 20 deletions(-) diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 956b15978c89..18df92eada73 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -161,13 +161,11 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, *abort_no_unlock = 1; goto outnow; } - /* We are only accepting if we have a socket with positive - * so_qlimit. */ + /* We are only accepting if we have a listening socket. */ if ((stcb == NULL) && ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || - (inp->sctp_socket == NULL) || - (inp->sctp_socket->so_qlimit == 0))) { + (!SCTP_IS_LISTENING(inp)))) { /* * FIX ME ?? What about TCP model and we have a * match/restart case? Actually no fix is needed. the lookup @@ -1605,8 +1603,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, sctp_stop_all_cookie_timers(stcb); if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && - (inp->sctp_socket->so_qlimit == 0) - ) { + (!SCTP_IS_LISTENING(inp))) { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; #endif @@ -1806,7 +1803,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && - (inp->sctp_socket->so_qlimit == 0)) { + (!SCTP_IS_LISTENING(inp))) { #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) struct socket *so; #endif @@ -2317,7 +2314,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, *notification = SCTP_NOTIFY_ASSOC_UP; if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && - (inp->sctp_socket->so_qlimit == 0)) { + (!SCTP_IS_LISTENING(inp))) { /* * This is an endpoint that called connect() how it got a * cookie that is NEW is a bit of a mystery. It must be that @@ -2343,7 +2340,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, SCTP_SOCKET_UNLOCK(so, 1); #endif } else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && - (inp->sctp_socket->so_qlimit)) { + (SCTP_IS_LISTENING(inp))) { /* * We don't want to do anything with this one. Since it is * the listening guy. The timer will get started for @@ -5205,7 +5202,9 @@ sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, * longer listening. */ - if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) { + if ((stcb == NULL) && + (!SCTP_IS_LISTENING(inp) || + inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) { if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) { op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h index b439b593af30..1251dfc7eef0 100644 --- a/sys/netinet/sctp_os_bsd.h +++ b/sys/netinet/sctp_os_bsd.h @@ -462,8 +462,6 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, #define SCTP_SHA256_UPDATE SHA256_Update #define SCTP_SHA256_FINAL(x,y) SHA256_Final((caddr_t)x, y) -#endif - #define SCTP_DECREMENT_AND_CHECK_REFCOUNT(addr) (atomic_fetchadd_int(addr, -1) == 1) #if defined(INVARIANTS) #define SCTP_SAVE_ATOMIC_DECREMENT(addr, val) \ @@ -484,3 +482,7 @@ sctp_get_mbuf_for_msg(unsigned int space_needed, } \ } #endif + +#define SCTP_IS_LISTENING(inp) ((inp->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING) != 0) + +#endif diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c index 85d3053a6582..f4d5b179af88 100644 --- a/sys/netinet/sctp_output.c +++ b/sys/netinet/sctp_output.c @@ -12595,7 +12595,7 @@ sctp_lower_sosend(struct socket *so, (void *)addr, sndlen); if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && - (inp->sctp_socket->so_qlimit)) { + SCTP_IS_LISTENING(inp)) { /* The listener can NOT send */ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, ENOTCONN); error = ENOTCONN; diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index 551a9cb914cc..521975fc040c 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -1311,7 +1311,7 @@ sctp_findassociation_ep_addr(struct sctp_inpcb **inp_p, struct sockaddr *remote, * it is the acceptor, then do the special_lookup to hash * and find the real inp. */ - if ((inp->sctp_socket) && (inp->sctp_socket->so_qlimit)) { + if ((inp->sctp_socket) && SCTP_IS_LISTENING(inp)) { /* to is peer addr, from is my addr */ stcb = sctp_tcb_special_locate(inp_p, remote, local, netp, inp->def_vrf_id); @@ -1884,7 +1884,7 @@ sctp_swap_inpcb_for_listen(struct sctp_inpcb *inp) if (tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { continue; } - if (tinp->sctp_socket->so_qlimit) { + if (SCTP_IS_LISTENING(tinp)) { continue; } SCTP_INP_WLOCK(tinp); diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c index 149419971b8e..802377f8e18d 100644 --- a/sys/netinet/sctp_sysctl.c +++ b/sys/netinet/sctp_sysctl.c @@ -410,6 +410,7 @@ sctp_sysctl_handle_assoclist(SYSCTL_HANDLER_ARGS) xinpcb.socket = inp->sctp_socket; so = inp->sctp_socket; if ((so == NULL) || + (!SCTP_IS_LISTENING(inp)) || (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { xinpcb.qlen = 0; xinpcb.maxqlen = 0; diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c index 75d817559bc1..c17550f8db14 100644 --- a/sys/netinet/sctp_usrreq.c +++ b/sys/netinet/sctp_usrreq.c @@ -7039,7 +7039,7 @@ sctp_listen(struct socket *so, int backlog, struct thread *p) if (tinp && (tinp != inp) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (tinp->sctp_socket->so_qlimit)) { + (SCTP_IS_LISTENING(tinp))) { /* * we have a listener already and * its not this inp. @@ -7083,7 +7083,7 @@ sctp_listen(struct socket *so, int backlog, struct thread *p) if (tinp && (tinp != inp) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) && ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && - (tinp->sctp_socket->so_qlimit)) { + (SCTP_IS_LISTENING(tinp))) { /* * we have a listener already and its not * this inp. @@ -7137,6 +7137,7 @@ sctp_listen(struct socket *so, int backlog, struct thread *p) return (error); } } + SCTP_INP_WLOCK(inp); SOCK_LOCK(so); /* It appears for 7.0 and on, we must always call this. */ solisten_proto(so, backlog); @@ -7144,11 +7145,13 @@ sctp_listen(struct socket *so, int backlog, struct thread *p) /* remove the ACCEPTCONN flag for one-to-many sockets */ so->so_options &= ~SO_ACCEPTCONN; } - if (backlog == 0) { - /* turning off listen */ - so->so_options &= ~SO_ACCEPTCONN; + if (backlog > 0) { + inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING; + } else { + inp->sctp_flags &= ~SCTP_PCB_FLAGS_ACCEPTING; } SOCK_UNLOCK(so); + SCTP_INP_WUNLOCK(inp); return (error); }