summaryrefslogtreecommitdiffstats
path: root/sys/netinet/sctp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/sctp_input.c')
-rw-r--r--sys/netinet/sctp_input.c86
1 files changed, 54 insertions, 32 deletions
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index d9d1024..10f305c 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -87,6 +87,12 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_init: handling INIT tcb:%p\n",
stcb);
+ if (stcb == NULL) {
+ SCTP_INP_RLOCK(inp);
+ if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
+ goto outnow;
+ }
+ }
op_err = NULL;
init = &cp->init;
/* First are we accepting? */
@@ -102,7 +108,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
vrf_id);
if (stcb)
*abort_no_unlock = 1;
- return;
+ goto outnow;
}
if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) {
/* Invalid length */
@@ -111,7 +117,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
vrf_id);
if (stcb)
*abort_no_unlock = 1;
- return;
+ goto outnow;
}
/* validate parameters */
if (init->initiate_tag == 0) {
@@ -121,7 +127,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
vrf_id);
if (stcb)
*abort_no_unlock = 1;
- return;
+ goto outnow;
}
if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) {
/* invalid parameter... send abort */
@@ -130,7 +136,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
vrf_id);
if (stcb)
*abort_no_unlock = 1;
- return;
+ goto outnow;
}
if (init->num_inbound_streams == 0) {
/* protocol error... send abort */
@@ -139,7 +145,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
vrf_id);
if (stcb)
*abort_no_unlock = 1;
- return;
+ goto outnow;
}
if (init->num_outbound_streams == 0) {
/* protocol error... send abort */
@@ -148,7 +154,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
vrf_id);
if (stcb)
*abort_no_unlock = 1;
- return;
+ goto outnow;
}
init_limit = offset + ntohs(cp->ch.chunk_length);
if (sctp_validate_init_auth_params(m, offset + sizeof(*cp),
@@ -157,11 +163,16 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
sctp_abort_association(inp, stcb, m, iphlen, sh, NULL, vrf_id);
if (stcb)
*abort_no_unlock = 1;
- return;
+ goto outnow;
}
/* send an INIT-ACK w/cookie */
SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n");
- sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, sh, cp, vrf_id);
+ sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, sh, cp, vrf_id,
+ SCTP_HOLDS_LOCK);
+outnow:
+ if (stcb == NULL) {
+ SCTP_INP_RUNLOCK(inp);
+ }
}
/*
@@ -495,6 +506,7 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
struct sockaddr_in6 *sin6;
struct sctp_nets *r_net;
struct timeval tv;
+ int req_prim = 0;
if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) {
/* Invalid length */
@@ -549,28 +561,7 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
TAILQ_REMOVE(&stcb->asoc.nets, stcb->asoc.primary_destination, sctp_next);
TAILQ_INSERT_HEAD(&stcb->asoc.nets, stcb->asoc.primary_destination, sctp_next);
}
- /* Mobility adaptation */
- if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
- SCTP_MOBILITY_BASE) ||
- sctp_is_mobility_feature_on(stcb->sctp_ep,
- SCTP_MOBILITY_FASTHANDOFF)) &&
- sctp_is_mobility_feature_on(stcb->sctp_ep,
- SCTP_MOBILITY_PRIM_DELETED)) {
-
- sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7);
- if (sctp_is_mobility_feature_on(stcb->sctp_ep,
- SCTP_MOBILITY_FASTHANDOFF)) {
- sctp_assoc_immediate_retrans(stcb,
- stcb->asoc.primary_destination);
- }
- if (sctp_is_mobility_feature_on(stcb->sctp_ep,
- SCTP_MOBILITY_BASE)) {
- sctp_move_chunks_from_deleted_prim(stcb,
- stcb->asoc.primary_destination);
- }
- sctp_delete_prim_timer(stcb->sctp_ep, stcb,
- stcb->asoc.deleted_primary);
- }
+ req_prim = 1;
}
sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED);
@@ -610,6 +601,30 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
}
/* Now lets do a RTO with this */
r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy);
+ /* Mobility adaptation */
+ if (req_prim) {
+ if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
+ SCTP_MOBILITY_BASE) ||
+ sctp_is_mobility_feature_on(stcb->sctp_ep,
+ SCTP_MOBILITY_FASTHANDOFF)) &&
+ sctp_is_mobility_feature_on(stcb->sctp_ep,
+ SCTP_MOBILITY_PRIM_DELETED)) {
+
+ sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7);
+ if (sctp_is_mobility_feature_on(stcb->sctp_ep,
+ SCTP_MOBILITY_FASTHANDOFF)) {
+ sctp_assoc_immediate_retrans(stcb,
+ stcb->asoc.primary_destination);
+ }
+ if (sctp_is_mobility_feature_on(stcb->sctp_ep,
+ SCTP_MOBILITY_BASE)) {
+ sctp_move_chunks_from_deleted_prim(stcb,
+ stcb->asoc.primary_destination);
+ }
+ sctp_delete_prim_timer(stcb->sctp_ep, stcb,
+ stcb->asoc.deleted_primary);
+ }
+ }
}
static void
@@ -630,6 +645,15 @@ sctp_handle_abort(struct sctp_abort_chunk *cp,
/* notify user of the abort and clean up... */
sctp_abort_notification(stcb, 0, SCTP_SO_NOT_LOCKED);
/* free the tcb */
+#if defined(SCTP_PANIC_ON_ABORT)
+ printf("stcb:%p state:%d rport:%d net:%p\n",
+ stcb, stcb->asoc.state, stcb->rport, net);
+ if (!(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
+ panic("Received an ABORT");
+ } else {
+ printf("No panic its in state %x closed\n", stcb->asoc.state);
+ }
+#endif
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
(SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
@@ -1537,7 +1561,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
else
SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
- SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
SCTP_STAT_INCR_GAUGE32(sctps_currestab);
} else if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
SCTP_STAT_INCR_COUNTER32(sctps_restartestab);
@@ -1548,7 +1571,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
stcb->sctp_ep, stcb, asoc->primary_destination);
-
}
sctp_stop_all_cookie_timers(stcb);
sctp_toss_old_cookies(stcb, asoc);
OpenPOWER on IntegriCloud