summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet/sctp_usrreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet/sctp_usrreq.c')
-rw-r--r--freebsd/sys/netinet/sctp_usrreq.c71
1 files changed, 46 insertions, 25 deletions
diff --git a/freebsd/sys/netinet/sctp_usrreq.c b/freebsd/sys/netinet/sctp_usrreq.c
index 071d44c2..b519971c 100644
--- a/freebsd/sys/netinet/sctp_usrreq.c
+++ b/freebsd/sys/netinet/sctp_usrreq.c
@@ -391,6 +391,7 @@ sctp_getcred(SYSCTL_HANDLER_ARGS)
SCTP_INP_DECR_REF(inp);
goto cred_can_cont;
}
+
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
error = ENOENT;
goto out;
@@ -431,6 +432,7 @@ sctp_abort(struct socket *so)
if (inp == NULL) {
return;
}
+
sctp_must_try_again:
flags = inp->sctp_flags;
#ifdef SCTP_LOG_CLOSING
@@ -704,8 +706,7 @@ sctp_disconnect(struct socket *so)
if (((so->so_options & SO_LINGER) &&
(so->so_linger == 0)) ||
(so->so_rcv.sb_cc > 0)) {
- if (SCTP_GET_STATE(asoc) !=
- SCTP_STATE_COOKIE_WAIT) {
+ if (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) {
/* Left with Data unread */
struct mbuf *op_err;
@@ -714,8 +715,8 @@ sctp_disconnect(struct socket *so)
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
}
SCTP_INP_RUNLOCK(inp);
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
@@ -730,17 +731,16 @@ sctp_disconnect(struct socket *so)
if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
goto abort_anyway;
}
- if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
/* only send SHUTDOWN 1st time thru */
struct sctp_nets *netp;
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(stcb);
if (stcb->asoc.alternate) {
netp = stcb->asoc.alternate;
@@ -773,11 +773,11 @@ sctp_disconnect(struct socket *so)
netp = stcb->asoc.primary_destination;
}
- asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
netp);
if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
- asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
}
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
@@ -789,8 +789,8 @@ sctp_disconnect(struct socket *so)
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
- if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
- (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
+ (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
}
SCTP_INP_RUNLOCK(inp);
@@ -921,9 +921,9 @@ sctp_shutdown(struct socket *so)
SCTP_INP_RUNLOCK(inp);
return (0);
}
- if ((SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_WAIT) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_COOKIE_ECHOED) &&
- (SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN)) {
+ if ((SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_ECHOED) &&
+ (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN)) {
/*
* If we are not in or before ESTABLISHED, there is
* no protocol action required.
@@ -937,7 +937,7 @@ sctp_shutdown(struct socket *so)
} else {
netp = stcb->asoc.primary_destination;
}
- if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) &&
+ if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) &&
TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
(asoc->stream_queue_cnt == 0)) {
@@ -946,8 +946,7 @@ sctp_shutdown(struct socket *so)
}
/* there is nothing queued to send, so I'm done... */
SCTP_STAT_DECR_GAUGE32(sctps_currestab);
- SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
- SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
sctp_stop_timers_for_shutdown(stcb);
sctp_send_shutdown(stcb, netp);
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
@@ -957,9 +956,9 @@ sctp_shutdown(struct socket *so)
* We still got (or just got) data to send, so set
* SHUTDOWN_PENDING.
*/
- SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
- SCTP_ADD_SUBSTATE(asoc, SCTP_STATE_PARTIAL_MSG_LEFT);
+ SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
}
if (TAILQ_EMPTY(&asoc->send_queue) &&
TAILQ_EMPTY(&asoc->sent_queue) &&
@@ -1369,11 +1368,13 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
return (EADDRINUSE);
}
+
if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
(sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
+
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
SCTP_INP_RLOCK(inp);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
@@ -1438,6 +1439,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
goto out_now;
}
}
+
/* FIX ME: do we want to pass in a vrf on the connect call? */
vrf_id = inp->def_vrf_id;
@@ -1457,7 +1459,7 @@ sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
/* Set the connected flag so we can queue data */
soisconnecting(so);
}
- SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
+ SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
/* move to second address */
switch (sa->sa_family) {
#ifdef INET
@@ -1549,6 +1551,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
+
inp = (struct sctp_inpcb *)so->so_pcb;
if (inp == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
@@ -2393,6 +2396,7 @@ flags_out:
break;
}
}
+
if (stcb != NULL) {
/* Applies to the specific association */
paddrp->spp_flags = 0;
@@ -3262,6 +3266,7 @@ flags_out:
break;
}
}
+
if (stcb != NULL) {
if (net != NULL) {
thlds->spt_pathmaxrxt = net->failure_threshold;
@@ -3374,6 +3379,7 @@ flags_out:
break;
}
}
+
if (stcb != NULL) {
if (net) {
encaps->sue_port = net->port;
@@ -4252,6 +4258,8 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
error = EINVAL;
+ } else {
+ inp->auth_supported = 1;
}
SCTP_INP_WUNLOCK(inp);
break;
@@ -4397,6 +4405,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
error = EINVAL;
break;
}
+
hmaclist = sctp_alloc_hmaclist((uint16_t)shmac->shmac_number_of_idents);
if (hmaclist == NULL) {
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
@@ -4589,6 +4598,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_INP_RUNLOCK(inp);
}
+
}
break;
}
@@ -5272,12 +5282,14 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
+
if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
if (stcb)
SCTP_TCB_UNLOCK(stcb);
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return (EINVAL);
}
+
if (stcb != NULL) {
/************************TCB SPECIFIC SET ******************/
if (net != NULL) {
@@ -5413,6 +5425,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
net->failure_threshold = paddrp->spp_pathmaxrxt;
}
}
+
if (paddrp->spp_flags & SPP_HB_ENABLE) {
if (paddrp->spp_hbinterval != 0) {
stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
@@ -5523,6 +5536,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (paddrp->spp_pathmaxrxt != 0) {
inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
}
+
if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
else if (paddrp->spp_hbinterval != 0) {
@@ -5530,6 +5544,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
}
+
if (paddrp->spp_flags & SPP_HB_ENABLE) {
if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
@@ -6482,6 +6497,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
break;
}
}
+
if (stcb != NULL) {
if (net != NULL) {
net->port = encaps->sue_port;
@@ -6865,6 +6881,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
return EINVAL;
}
+
switch (addr->sa_family) {
#ifdef INET6
case AF_INET6:
@@ -6970,6 +6987,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
error = EALREADY;
goto out_now;
}
+
vrf_id = inp->def_vrf_id;
/* We are GOOD to go */
stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id,
@@ -6984,7 +7002,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
/* Set the connected flag so we can queue data */
soisconnecting(so);
}
- SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
+ SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
/* initialize authentication parameters for the assoc */
@@ -6996,6 +7014,7 @@ out_now:
if (create_lock_on) {
SCTP_ASOC_CREATE_UNLOCK(inp);
}
+
SCTP_INP_DECR_REF(inp);
return (error);
}
@@ -7134,6 +7153,7 @@ sctp_listen(struct socket *so, int backlog, struct thread *p)
return (EADDRINUSE);
}
}
+
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
/* We are already connected AND the TCP model */
@@ -7201,7 +7221,7 @@ sctp_accept(struct socket *so, struct sockaddr **addr)
SCTP_TCB_LOCK(stcb);
SCTP_INP_RUNLOCK(inp);
store = stcb->asoc.primary_destination->ro._l_addr;
- stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
+ SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
SCTP_TCB_UNLOCK(stcb);
switch (store.sa.sa_family) {
#ifdef INET
@@ -7336,6 +7356,7 @@ sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
SCTP_TCB_UNLOCK(stcb);
goto notConn;
}
+
vrf_id = inp->def_vrf_id;
sctp_ifa = sctp_source_address_selection(inp,
stcb,