Changeset View
Standalone View
sys/netinet/sctp_input.c
Show First 20 Lines • Show All 155 Lines • ▼ Show 20 Lines | op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), | ||||
"Problem with AUTH parameters"); | "Problem with AUTH parameters"); | ||||
sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, | sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, | ||||
mflowtype, mflowid, | mflowtype, mflowid, | ||||
vrf_id, port); | vrf_id, port); | ||||
if (stcb) | if (stcb) | ||||
*abort_no_unlock = 1; | *abort_no_unlock = 1; | ||||
goto outnow; | goto outnow; | ||||
} | } | ||||
/* We are only accepting if we have a socket with positive | /* We are only accepting if we have a listening socket. */ | ||||
* so_qlimit. */ | |||||
if ((stcb == NULL) && | if ((stcb == NULL) && | ||||
((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || | ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || | ||||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || | (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || | ||||
(inp->sctp_socket == NULL) || | (inp->sctp_socket == NULL) || | ||||
(inp->sctp_socket->so_qlimit == 0))) { | (!SOLISTENING(inp->sctp_socket)))) { | ||||
/* | /* | ||||
* FIX ME ?? What about TCP model and we have a | * FIX ME ?? What about TCP model and we have a | ||||
* match/restart case? Actually no fix is needed. the lookup | * match/restart case? Actually no fix is needed. the lookup | ||||
* will always find the existing assoc so stcb would not be | * will always find the existing assoc so stcb would not be | ||||
* NULL. It may be questionable to do this since we COULD | * NULL. It may be questionable to do this since we COULD | ||||
* just send back the INIT-ACK and hope that the app did | * just send back the INIT-ACK and hope that the app did | ||||
* accept()'s by the time the COOKIE was sent. But there is | * accept()'s by the time the COOKIE was sent. But there is | ||||
* a price to pay for COOKIE generation and I don't want to | * a price to pay for COOKIE generation and I don't want to | ||||
▲ Show 20 Lines • Show All 1,421 Lines • ▼ Show 20 Lines | case SCTP_STATE_COOKIE_ECHOED: | ||||
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { | if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { | ||||
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, | sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, | ||||
stcb->sctp_ep, stcb, asoc->primary_destination); | stcb->sctp_ep, stcb, asoc->primary_destination); | ||||
} | } | ||||
SCTP_STAT_INCR_GAUGE32(sctps_currestab); | SCTP_STAT_INCR_GAUGE32(sctps_currestab); | ||||
sctp_stop_all_cookie_timers(stcb); | sctp_stop_all_cookie_timers(stcb); | ||||
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || | if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || | ||||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && | (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && | ||||
(inp->sctp_socket->so_qlimit == 0) | (!SOLISTENING(inp->sctp_socket)) | ||||
) { | ) { | ||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) | #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) | ||||
struct socket *so; | struct socket *so; | ||||
#endif | #endif | ||||
/* | /* | ||||
* Here is where collision would go if we | * Here is where collision would go if we | ||||
* did a connect() and instead got a | * did a connect() and instead got a | ||||
* init/init-ack/cookie done before the | * init/init-ack/cookie done before the | ||||
▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | if (sctp_load_addresses_from_init(stcb, m, | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
if ((asoc->state & SCTP_STATE_COOKIE_WAIT) || | if ((asoc->state & SCTP_STATE_COOKIE_WAIT) || | ||||
(asoc->state & SCTP_STATE_COOKIE_ECHOED)) { | (asoc->state & SCTP_STATE_COOKIE_ECHOED)) { | ||||
*notification = SCTP_NOTIFY_ASSOC_UP; | *notification = SCTP_NOTIFY_ASSOC_UP; | ||||
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || | if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || | ||||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && | (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && | ||||
(inp->sctp_socket->so_qlimit == 0)) { | (!SOLISTENING(inp->sctp_socket))) { | ||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) | #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) | ||||
struct socket *so; | struct socket *so; | ||||
#endif | #endif | ||||
stcb->sctp_ep->sctp_flags |= | stcb->sctp_ep->sctp_flags |= | ||||
SCTP_PCB_FLAGS_CONNECTED; | SCTP_PCB_FLAGS_CONNECTED; | ||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) | #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) | ||||
so = SCTP_INP_SO(stcb->sctp_ep); | so = SCTP_INP_SO(stcb->sctp_ep); | ||||
atomic_add_int(&stcb->asoc.refcnt, 1); | atomic_add_int(&stcb->asoc.refcnt, 1); | ||||
▲ Show 20 Lines • Show All 494 Lines • ▼ Show 20 Lines | #endif | ||||
atomic_subtract_int(&stcb->asoc.refcnt, 1); | atomic_subtract_int(&stcb->asoc.refcnt, 1); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
/* set up to notify upper layer */ | /* set up to notify upper layer */ | ||||
*notification = SCTP_NOTIFY_ASSOC_UP; | *notification = SCTP_NOTIFY_ASSOC_UP; | ||||
if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || | if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || | ||||
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && | (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && | ||||
(inp->sctp_socket->so_qlimit == 0)) { | (!SOLISTENING(inp->sctp_socket))) { | ||||
/* | /* | ||||
* This is an endpoint that called connect() how it got a | * 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 | * cookie that is NEW is a bit of a mystery. It must be that | ||||
* the INIT was sent, but before it got there.. a complete | * the INIT was sent, but before it got there.. a complete | ||||
* INIT/INIT-ACK/COOKIE arrived. But of course then it | * INIT/INIT-ACK/COOKIE arrived. But of course then it | ||||
* should have went to the other code.. not here.. oh well.. | * should have went to the other code.. not here.. oh well.. | ||||
* a bit of protection is worth having.. | * a bit of protection is worth having.. | ||||
*/ | */ | ||||
Show All 9 Lines | if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
#endif | #endif | ||||
soisconnected(stcb->sctp_socket); | soisconnected(stcb->sctp_socket); | ||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) | #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) | ||||
SCTP_SOCKET_UNLOCK(so, 1); | SCTP_SOCKET_UNLOCK(so, 1); | ||||
#endif | #endif | ||||
} else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && | } else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && | ||||
(inp->sctp_socket->so_qlimit)) { | SOLISTENING(inp->sctp_socket)) { | ||||
/* | /* | ||||
* We don't want to do anything with this one. Since it is | * We don't want to do anything with this one. Since it is | ||||
* the listening guy. The timer will get started for | * the listening guy. The timer will get started for | ||||
* accepted connections in the caller. | * accepted connections in the caller. | ||||
*/ | */ | ||||
; | ; | ||||
} | } | ||||
/* since we did not send a HB make sure we don't double things */ | /* since we did not send a HB make sure we don't double things */ | ||||
▲ Show 20 Lines • Show All 2,845 Lines • ▼ Show 20 Lines | case SCTP_COOKIE_ECHO: | ||||
/* | /* | ||||
* First are we accepting? We do this again here | * First are we accepting? We do this again here | ||||
* since it is possible that a previous endpoint WAS | * since it is possible that a previous endpoint WAS | ||||
* listening responded to a INIT-ACK and then | * listening responded to a INIT-ACK and then | ||||
* closed. We opened and bound.. and are now no | * closed. We opened and bound.. and are now no | ||||
* longer listening. | * longer listening. | ||||
*/ | */ | ||||
if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) { | if ((stcb == NULL) && (!SOLISTENING(inp->sctp_socket))) { | ||||
tuexen: Why don't we need to check if the accept queue is already full? This was done in the old code… | |||||
glebiusUnsubmitted Not Done Inline ActionsHere I trusted the comment, not the code. Comment says that we are checking against socket still listening. The SCTP code always used not the SO_ACCEPTCONN flag but so_qlimit for this check, since it tweaked so_qlimit to unlisten a socket. The usual check in SCTP look like: (so->so_qlimit > 0) I believe, for some obscure reason this place has different check, but effectively should have the same. Trusting the comment, as I said. If you think that queue overflow is also a case we should check for, than this should be: (stcb == NULL && (!SOLISTENING(inp->sctp_socket) || (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) Is calling sctp_abort_association() the right thing to do for listen queue overflow? glebius: Here I trusted the comment, not the code. Comment says that we are checking against socket… | |||||
tuexenUnsubmitted Not Done Inline ActionsThe condition above is the one you want to use. That should fix this. tuexen: The condition above is the one you want to use. That should fix this. | |||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && | if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && | ||||
(SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) { | (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) { | ||||
op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); | op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); | ||||
sctp_abort_association(inp, stcb, m, iphlen, | sctp_abort_association(inp, stcb, m, iphlen, | ||||
src, dst, sh, op_err, | src, dst, sh, op_err, | ||||
mflowtype, mflowid, | mflowtype, mflowid, | ||||
vrf_id, port); | vrf_id, port); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 993 Lines • Show Last 20 Lines |
Why don't we need to check if the accept queue is already full? This was done in the old code but doesn't seem to be the case any more for the new code?