aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/sctp_asconf.c13
-rw-r--r--sys/netinet/sctp_constants.h3
-rw-r--r--sys/netinet/sctp_indata.c9
-rw-r--r--sys/netinet/sctp_input.c86
-rw-r--r--sys/netinet/sctp_output.c41
-rw-r--r--sys/netinet/sctp_output.h2
-rw-r--r--sys/netinet/sctp_pcb.c9
-rw-r--r--sys/netinet/sctp_timer.c3
-rw-r--r--sys/netinet/sctp_usrreq.c10
-rw-r--r--sys/netinet/sctp_var.h6
-rw-r--r--sys/netinet/sctputil.c15
11 files changed, 147 insertions, 50 deletions
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c
index e8fcdeda82e2..f9f3660f52fa 100644
--- a/sys/netinet/sctp_asconf.c
+++ b/sys/netinet/sctp_asconf.c
@@ -1018,7 +1018,6 @@ sctp_move_chunks_from_deleted_prim(struct sctp_tcb *stcb, struct sctp_nets *dst)
}
-extern int cur_oerr;
void
sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet)
@@ -1044,7 +1043,6 @@ sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet)
stcb->asoc.num_send_timers_up = 0;
}
SCTP_TCB_LOCK_ASSERT(stcb);
- cur_oerr = stcb->asoc.overall_error_count;
error = sctp_t3rxt_timer(stcb->sctp_ep, stcb,
stcb->asoc.deleted_primary);
if (error) {
@@ -1086,9 +1084,16 @@ sctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net)
if (chk->sent < SCTP_DATAGRAM_RESEND) {
chk->sent = SCTP_DATAGRAM_RESEND;
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
+ sctp_flight_size_decrease(chk);
+ sctp_total_flight_decrease(stcb, chk);
+ net->marked_retrans++;
+ stcb->asoc.marked_retrans++;
}
}
}
+ if (net->marked_retrans) {
+ sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
+ }
}
static void
@@ -1205,7 +1210,9 @@ sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr,
sctp_del_local_addr_restricted(stcb, addr);
if (sctp_is_mobility_feature_on(stcb->sctp_ep,
- SCTP_MOBILITY_BASE)) {
+ SCTP_MOBILITY_BASE) ||
+ sctp_is_mobility_feature_on(stcb->sctp_ep,
+ SCTP_MOBILITY_FASTHANDOFF)) {
sctp_path_check_and_react(stcb, addr);
return;
}
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 2621251d155d..fab56a3af002 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -1034,6 +1034,9 @@ __FBSDID("$FreeBSD$");
#define SCTP_SO_NOT_LOCKED 0
+#define SCTP_HOLDS_LOCK 1
+#define SCTP_NOT_LOCKED 0
+
/*-
* For address locks, do we hold the lock?
*/
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 842aca6fa508..e001a0c2dbe4 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -1571,8 +1571,8 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc,
asoc->highest_tsn_inside_map, MAX_TSN)) {
/* Nope not in the valid range dump it */
- SCTPDBG(SCTP_DEBUG_INDATA1, "My rwnd overrun1:tsn:%lx rwnd %lu sbspace:%ld\n",
- (u_long)tsn, (u_long)asoc->my_rwnd,
+ SCTPDBG(SCTP_DEBUG_INDATA1, "My rwnd overrun1:tsn:%x rwnd %x sbspace:%x\n",
+ tsn, asoc->my_rwnd,
sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv));
sctp_set_rwnd(stcb, asoc);
if ((asoc->cnt_on_all_streams +
@@ -2325,7 +2325,12 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
}
slide_end = lgap >> 3;
if (slide_end < slide_from) {
+#ifdef INVARIANTS
panic("impossible slide");
+#else
+ printf("impossible slide?\n");
+ return;
+#endif
}
distance = (slide_end - slide_from) + 1;
if (sctp_logging_level & SCTP_MAP_LOGGING_ENABLE) {
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index d9d10249f576..10f305cddd82 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);
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index b7e040ff2679..e80573e36838 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -4612,7 +4612,7 @@ sctp_are_there_new_addresses(struct sctp_association *asoc,
void
sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
struct mbuf *init_pkt, int iphlen, int offset, struct sctphdr *sh,
- struct sctp_init_chunk *init_chk, uint32_t vrf_id)
+ struct sctp_init_chunk *init_chk, uint32_t vrf_id, int hold_inp_lock)
{
struct sctp_association *asoc;
struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *mp_last;
@@ -4636,6 +4636,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
int abort_flag, padval;
int num_ext;
int p_len;
+ struct socket *so;
if (stcb)
asoc = &stcb->asoc;
@@ -4947,6 +4948,9 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
} else {
uint32_t vtag, itsn;
+ if (hold_inp_lock) {
+ SCTP_INP_RUNLOCK(inp);
+ }
if (asoc) {
atomic_add_int(&asoc->refcnt, 1);
SCTP_TCB_UNLOCK(stcb);
@@ -4963,12 +4967,22 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
/* get a TSN to use too */
initackm_out->msg.init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep));
}
+ if (hold_inp_lock) {
+ SCTP_INP_RLOCK(inp);
+ }
}
/* save away my tag to */
stc.my_vtag = initackm_out->msg.init.initiate_tag;
/* set up some of the credits. */
- initackm_out->msg.init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND));
+ so = inp->sctp_socket;
+ if (so == NULL) {
+ /* memory problem */
+ sctp_m_freem(m);
+ return;
+ } else {
+ initackm_out->msg.init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(so), SCTP_MINIMAL_RWND));
+ }
/* set what I want */
his_limit = ntohs(init_chk->init.num_inbound_streams);
/* choose what I want */
@@ -10962,7 +10976,10 @@ sctp_lower_sosend(struct socket *so,
if (inp == NULL) {
SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_OUTPUT, EFAULT);
error = EFAULT;
- goto out_unlocked;
+ if (i_pak) {
+ SCTP_RELEASE_PKT(i_pak);
+ }
+ return (error);
}
if ((uio == NULL) && (i_pak == NULL)) {
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EINVAL);
@@ -11193,6 +11210,11 @@ sctp_lower_sosend(struct socket *so,
}
/* get an asoc/stcb struct */
vrf_id = inp->def_vrf_id;
+#ifdef INVARIANTS
+ if (create_lock_applied == 0) {
+ panic("Error, should hold create lock and I don't?");
+ }
+#endif
stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0, vrf_id,
p
);
@@ -11342,11 +11364,16 @@ sctp_lower_sosend(struct socket *so,
}
}
/* Keep the stcb from being freed under our feet */
- if (free_cnt_applied)
+ if (free_cnt_applied) {
+#ifdef INVARIANTS
panic("refcnt already incremented");
- atomic_add_int(&stcb->asoc.refcnt, 1);
- free_cnt_applied = 1;
-
+#else
+ printf("refcnt:1 already incremented?\n");
+#endif
+ } else {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ free_cnt_applied = 1;
+ }
if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ECONNRESET);
error = ECONNRESET;
diff --git a/sys/netinet/sctp_output.h b/sys/netinet/sctp_output.h
index 512522ffed12..d37c163dd6a4 100644
--- a/sys/netinet/sctp_output.h
+++ b/sys/netinet/sctp_output.h
@@ -84,7 +84,7 @@ sctp_send_initiate(struct sctp_inpcb *, struct sctp_tcb *, int
void
sctp_send_initiate_ack(struct sctp_inpcb *, struct sctp_tcb *,
struct mbuf *, int, int, struct sctphdr *, struct sctp_init_chunk *,
- uint32_t);
+ uint32_t, int);
struct mbuf *
sctp_arethere_unrecognized_parameters(struct mbuf *, int, int *,
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index a7609762d1ff..b4666deb3a78 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -2908,6 +2908,9 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
*ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_3);
}
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_3;
+#if defined(SCTP_PANIC_ON_ABORT)
+ panic("inpcb_free does an abort");
+#endif
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
@@ -2991,6 +2994,10 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
*ippp = htonl(SCTP_FROM_SCTP_PCB + SCTP_LOC_5);
}
asoc->sctp_ep->last_abort_code = SCTP_FROM_SCTP_PCB + SCTP_LOC_5;
+#if defined(SCTP_PANIC_ON_ABORT)
+ panic("inpcb_free does an abort");
+#endif
+
sctp_send_abort_tcb(asoc, op_err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_OPEN) ||
@@ -3822,6 +3829,8 @@ sctp_remove_net(struct sctp_tcb *stcb, struct sctp_nets *net)
}
asoc->deleted_primary = net;
atomic_add_int(&net->ref_count, 1);
+ memset(&net->lastsa, 0, sizeof(net->lastsa));
+ memset(&net->lastsv, 0, sizeof(net->lastsv));
sctp_mobility_feature_on(stcb->sctp_ep,
SCTP_MOBILITY_PRIM_DELETED);
sctp_timer_start(SCTP_TIMER_TYPE_PRIM_DELETED,
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index d90c56d49325..e9382a5eb4b0 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -280,6 +280,9 @@ sctp_threshold_management(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
*ippp = htonl(SCTP_FROM_SCTP_TIMER + SCTP_LOC_1);
}
inp->last_abort_code = SCTP_FROM_SCTP_TIMER + SCTP_LOC_1;
+ printf("Aborting association threshold:%d overall error count:%d\n",
+ threshold,
+ stcb->asoc.overall_error_count);
sctp_abort_an_association(inp, stcb, SCTP_FAILED_THRESHOLD, oper, SCTP_SO_NOT_LOCKED);
return (1);
}
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 9d3c55b0b6bb..20de9c3c1020 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -792,6 +792,9 @@ sctp_disconnect(struct socket *so)
ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
ph->param_length = htons(SCTP_BUF_LEN(err));
}
+#if defined(SCTP_PANIC_ON_ABORT)
+ panic("disconnect does an abort");
+#endif
sctp_send_abort_tcb(stcb, err, SCTP_SO_LOCKED);
SCTP_STAT_INCR_COUNTER32(sctps_aborted);
}
@@ -883,6 +886,10 @@ sctp_disconnect(struct socket *so)
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4);
}
+#if defined(SCTP_PANIC_ON_ABORT)
+ panic("disconnect does an abort");
+#endif
+
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);
@@ -1023,6 +1030,9 @@ sctp_shutdown(struct socket *so)
ippp = (uint32_t *) (ph + 1);
*ippp = htonl(SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6);
}
+#if defined(SCTP_PANIC_ON_ABORT)
+ panic("shutdown does an abort");
+#endif
stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
sctp_abort_an_association(stcb->sctp_ep, stcb,
SCTP_RESPONSE_TO_USER_REQ,
diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h
index 8bc6ffdca823..c4af43338a52 100644
--- a/sys/netinet/sctp_var.h
+++ b/sys/netinet/sctp_var.h
@@ -54,9 +54,11 @@ extern struct pr_usrreqs sctp_usrreqs;
#define sctp_is_mobility_feature_on(inp, feature) (inp->sctp_mobility_features & feature)
#define sctp_is_mobility_feature_off(inp, feature) ((inp->sctp_mobility_features & feature) == 0)
-#define sctp_sbspace(asoc, sb) ((long) (((sb)->sb_hiwat > (asoc)->sb_cc) ? ((sb)->sb_hiwat - (asoc)->sb_cc) : 0))
+#define sctp_maxspace(sb) (max((sb)->sb_hiwat,SCTP_MINIMAL_RWND))
-#define sctp_sbspace_failedmsgs(sb) ((long) (((sb)->sb_hiwat > (sb)->sb_cc) ? ((sb)->sb_hiwat - (sb)->sb_cc) : 0))
+#define sctp_sbspace(asoc, sb) ((long) (sctp_maxspace(sb) > (asoc)->sb_cc) ? (sctp_maxspace(sb) - (asoc)->sb_cc) : 0)
+
+#define sctp_sbspace_failedmsgs(sb) ((long) ((sctp_maxspace(sb) > (sb)->sb_cc) ? (sctp_maxspace(sb) - (sb)->sb_cc) : 0))
#define sctp_sbspace_sub(a,b) ((a > b) ? (a - b) : 0)
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 19cb06677dc5..09a0e20e0301 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -3962,6 +3962,9 @@ sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
break;
}
switch (ch->chunk_type) {
+ case SCTP_COOKIE_ECHO:
+ /* We hit here only if the assoc is being freed */
+ return;
case SCTP_PACKET_DROPPED:
/* we don't respond to pkt-dropped */
return;
@@ -5265,10 +5268,16 @@ found_one:
* to increment, we need to use the atomic add to
* the refcnt
*/
- if (freecnt_applied)
+ if (freecnt_applied) {
+#ifdef INVARIANTS
panic("refcnt already incremented");
- atomic_add_int(&stcb->asoc.refcnt, 1);
- freecnt_applied = 1;
+#else
+ printf("refcnt already incremented?\n");
+#endif
+ } else {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ freecnt_applied = 1;
+ }
/*
* Setup to remember how much we have not yet told
* the peer our rwnd has opened up. Note we grab the