diff options
-rw-r--r-- | sys/netinet/sctp_asconf.c | 13 | ||||
-rw-r--r-- | sys/netinet/sctp_constants.h | 3 | ||||
-rw-r--r-- | sys/netinet/sctp_indata.c | 9 | ||||
-rw-r--r-- | sys/netinet/sctp_input.c | 86 | ||||
-rw-r--r-- | sys/netinet/sctp_output.c | 41 | ||||
-rw-r--r-- | sys/netinet/sctp_output.h | 2 | ||||
-rw-r--r-- | sys/netinet/sctp_pcb.c | 9 | ||||
-rw-r--r-- | sys/netinet/sctp_timer.c | 3 | ||||
-rw-r--r-- | sys/netinet/sctp_usrreq.c | 10 | ||||
-rw-r--r-- | sys/netinet/sctp_var.h | 6 | ||||
-rw-r--r-- | sys/netinet/sctputil.c | 15 |
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 |