diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c index b4a0d089bf63..7bad54c1f6f1 100644 --- a/sys/netinet/sctp_indata.c +++ b/sys/netinet/sctp_indata.c @@ -1729,7 +1729,6 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, sctp_alloc_a_readq(stcb, control); sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn, protocol_id, - stcb->asoc.context, strmno, strmseq, chunk_flags, dmbuf); @@ -1857,7 +1856,6 @@ sctp_process_a_data_chunk(struct sctp_tcb *stcb, struct sctp_association *asoc, sctp_alloc_a_readq(stcb, control); sctp_build_readq_entry_mac(control, stcb, asoc->context, net, tsn, protocol_id, - stcb->asoc.context, strmno, strmseq, chunk_flags, dmbuf); diff --git a/sys/netinet/sctp_indata.h b/sys/netinet/sctp_indata.h index 5eaa1f4ba412..79a86e2a6ff0 100644 --- a/sys/netinet/sctp_indata.h +++ b/sys/netinet/sctp_indata.h @@ -47,14 +47,14 @@ sctp_build_readq_entry(struct sctp_tcb *stcb, struct mbuf *dm); -#define sctp_build_readq_entry_mac(_ctl, in_it, a, net, tsn, ppid, context, stream_no, stream_seq, flags, dm) do { \ +#define sctp_build_readq_entry_mac(_ctl, in_it, context, net, tsn, ppid, stream_no, stream_seq, flags, dm) do { \ if (_ctl) { \ atomic_add_int(&((net)->ref_count), 1); \ (_ctl)->sinfo_stream = stream_no; \ (_ctl)->sinfo_ssn = stream_seq; \ (_ctl)->sinfo_flags = (flags << 8); \ (_ctl)->sinfo_ppid = ppid; \ - (_ctl)->sinfo_context = a; \ + (_ctl)->sinfo_context = context; \ (_ctl)->sinfo_timetolive = 0; \ (_ctl)->sinfo_tsn = tsn; \ (_ctl)->sinfo_cumtsn = tsn; \ diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 0528d3df229f..fac3cd7b1933 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -1028,12 +1028,13 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, SCTP_SOCKET_UNLOCK(so, 1); #endif } - /* are the queues empty? */ +#ifdef INVARIANTS if (!TAILQ_EMPTY(&asoc->send_queue) || !TAILQ_EMPTY(&asoc->sent_queue) || !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { - sctp_report_all_outbound(stcb, 0, 0, SCTP_SO_NOT_LOCKED); + panic("Queues are not empty when handling SHUTDOWN-ACK"); } +#endif /* stop the timer */ sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9); /* send SHUTDOWN-COMPLETE */ @@ -1875,9 +1876,14 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, cookie->tie_tag_peer_vtag != 0) { struct sctpasochead *head; +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + struct socket *so; + +#endif + if (asoc->peer_supports_nat) { /* - * This is a gross gross hack. just call the + * This is a gross gross hack. Just call the * cookie_new code since we are allowing a duplicate * association. I hope this works... */ @@ -1939,6 +1945,10 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, asoc->mapping_array_size); } SCTP_TCB_UNLOCK(stcb); +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + so = SCTP_INP_SO(stcb->sctp_ep); + SCTP_SOCKET_LOCK(so, 1); +#endif SCTP_INP_INFO_WLOCK(); SCTP_INP_WLOCK(stcb->sctp_ep); SCTP_TCB_LOCK(stcb); @@ -1946,7 +1956,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, /* send up all the data */ SCTP_TCB_SEND_LOCK(stcb); - sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_NOT_LOCKED); + sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED); for (i = 0; i < stcb->asoc.streamoutcnt; i++) { stcb->asoc.strmout[i].chunks_on_queues = 0; stcb->asoc.strmout[i].stream_no = i; @@ -1968,11 +1978,15 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, */ LIST_INSERT_HEAD(head, stcb, sctp_asocs); - /* process the INIT info (peer's info) */ SCTP_TCB_SEND_UNLOCK(stcb); SCTP_INP_WUNLOCK(stcb->sctp_ep); SCTP_INP_INFO_WUNLOCK(); - +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) + SCTP_SOCKET_UNLOCK(so, 1); +#endif + asoc->total_flight = 0; + asoc->total_flight_count = 0; + /* process the INIT info (peer's info) */ retval = sctp_process_init(init_cp, stcb); if (retval < 0) { if (how_indx < sizeof(asoc->cookie_how)) @@ -3196,13 +3210,14 @@ sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSE /* notify upper layer protocol */ if (stcb->sctp_socket) { sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); - /* are the queues empty? they should be */ - if (!TAILQ_EMPTY(&asoc->send_queue) || - !TAILQ_EMPTY(&asoc->sent_queue) || - !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { - sctp_report_all_outbound(stcb, 0, 0, SCTP_SO_NOT_LOCKED); - } } +#ifdef INVARIANTS + if (!TAILQ_EMPTY(&asoc->send_queue) || + !TAILQ_EMPTY(&asoc->sent_queue) || + !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { + panic("Queues are not empty when handling SHUTDOWN-COMPLETE"); + } +#endif /* stop the timer */ sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_22); SCTP_STAT_INCR_COUNTER32(sctps_shutdown); @@ -3491,18 +3506,13 @@ sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * } static void -sctp_reset_out_streams(struct sctp_tcb *stcb, int number_entries, uint16_t * list) +sctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list) { - int i; + uint32_t i; + uint16_t temp; - if (number_entries == 0) { - for (i = 0; i < stcb->asoc.streamoutcnt; i++) { - stcb->asoc.strmout[i].next_sequence_send = 0; - } - } else if (number_entries) { + if (number_entries > 0) { for (i = 0; i < number_entries; i++) { - uint16_t temp; - temp = ntohs(list[i]); if (temp >= stcb->asoc.streamoutcnt) { /* no such stream */ @@ -3510,6 +3520,10 @@ sctp_reset_out_streams(struct sctp_tcb *stcb, int number_entries, uint16_t * lis } stcb->asoc.strmout[temp].next_sequence_send = 0; } + } else { + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { + stcb->asoc.strmout[i].next_sequence_send = 0; + } } sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); } @@ -3596,7 +3610,7 @@ sctp_handle_stream_reset_response(struct sctp_tcb *stcb, struct sctp_association *asoc = &stcb->asoc; struct sctp_tmit_chunk *chk; struct sctp_stream_reset_out_request *srparam; - int number_entries; + uint32_t number_entries; if (asoc->stream_reset_outstanding == 0) { /* duplicate */ diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c index e98ca0c69f10..00f685ff6a4f 100644 --- a/sys/netinet/sctp_pcb.c +++ b/sys/netinet/sctp_pcb.c @@ -4451,23 +4451,21 @@ sctp_delete_from_timewait(uint32_t tag, uint16_t lport, uint16_t rport) int i; chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; - if (!LIST_EMPTY(chain)) { - LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { - for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { - if ((twait_block->vtag_block[i].v_tag == tag) && - (twait_block->vtag_block[i].lport == lport) && - (twait_block->vtag_block[i].rport == rport)) { - twait_block->vtag_block[i].tv_sec_at_expire = 0; - twait_block->vtag_block[i].v_tag = 0; - twait_block->vtag_block[i].lport = 0; - twait_block->vtag_block[i].rport = 0; - found = 1; - break; - } - } - if (found) + LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { + for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { + if ((twait_block->vtag_block[i].v_tag == tag) && + (twait_block->vtag_block[i].lport == lport) && + (twait_block->vtag_block[i].rport == rport)) { + twait_block->vtag_block[i].tv_sec_at_expire = 0; + twait_block->vtag_block[i].v_tag = 0; + twait_block->vtag_block[i].lport = 0; + twait_block->vtag_block[i].rport = 0; + found = 1; break; + } } + if (found) + break; } } @@ -4481,19 +4479,17 @@ sctp_is_in_timewait(uint32_t tag, uint16_t lport, uint16_t rport) SCTP_INP_INFO_WLOCK(); chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; - if (!LIST_EMPTY(chain)) { - LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { - for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { - if ((twait_block->vtag_block[i].v_tag == tag) && - (twait_block->vtag_block[i].lport == lport) && - (twait_block->vtag_block[i].rport == rport)) { - found = 1; - break; - } - } - if (found) + LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { + for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { + if ((twait_block->vtag_block[i].v_tag == tag) && + (twait_block->vtag_block[i].lport == lport) && + (twait_block->vtag_block[i].rport == rport)) { + found = 1; break; + } } + if (found) + break; } SCTP_INP_INFO_WUNLOCK(); return (found); @@ -4515,42 +4511,40 @@ sctp_add_vtag_to_timewait(uint32_t tag, uint32_t time, uint16_t lport, uint16_t (void)SCTP_GETTIME_TIMEVAL(&now); chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; set = 0; - if (!LIST_EMPTY(chain)) { + LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { /* Block(s) present, lets find space, and expire on the fly */ - LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { - for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { - if ((twait_block->vtag_block[i].v_tag == 0) && - !set) { - twait_block->vtag_block[i].tv_sec_at_expire = - now.tv_sec + time; + for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { + if ((twait_block->vtag_block[i].v_tag == 0) && + !set) { + twait_block->vtag_block[i].tv_sec_at_expire = + now.tv_sec + time; + twait_block->vtag_block[i].v_tag = tag; + twait_block->vtag_block[i].lport = lport; + twait_block->vtag_block[i].rport = rport; + set = 1; + } else if ((twait_block->vtag_block[i].v_tag) && + ((long)twait_block->vtag_block[i].tv_sec_at_expire < now.tv_sec)) { + /* Audit expires this guy */ + twait_block->vtag_block[i].tv_sec_at_expire = 0; + twait_block->vtag_block[i].v_tag = 0; + twait_block->vtag_block[i].lport = 0; + twait_block->vtag_block[i].rport = 0; + if (set == 0) { + /* Reuse it for my new tag */ + twait_block->vtag_block[i].tv_sec_at_expire = now.tv_sec + time; twait_block->vtag_block[i].v_tag = tag; twait_block->vtag_block[i].lport = lport; twait_block->vtag_block[i].rport = rport; set = 1; - } else if ((twait_block->vtag_block[i].v_tag) && - ((long)twait_block->vtag_block[i].tv_sec_at_expire < now.tv_sec)) { - /* Audit expires this guy */ - twait_block->vtag_block[i].tv_sec_at_expire = 0; - twait_block->vtag_block[i].v_tag = 0; - twait_block->vtag_block[i].lport = 0; - twait_block->vtag_block[i].rport = 0; - if (set == 0) { - /* Reuse it for my new tag */ - twait_block->vtag_block[i].tv_sec_at_expire = now.tv_sec + time; - twait_block->vtag_block[i].v_tag = tag; - twait_block->vtag_block[i].lport = lport; - twait_block->vtag_block[i].rport = rport; - set = 1; - } } } - if (set) { - /* - * We only do up to the block where we can - * place our tag for audits - */ - break; - } + } + if (set) { + /* + * We only do up to the block where we can place our + * tag for audits + */ + break; } } /* Need to add a new block to chain */ @@ -6700,30 +6694,28 @@ sctp_is_vtag_good(uint32_t tag, uint16_t lport, uint16_t rport, struct timeval * chain = &SCTP_BASE_INFO(vtag_timewait)[(tag % SCTP_STACK_VTAG_HASH_SIZE)]; /* Now what about timed wait ? */ - if (!LIST_EMPTY(chain)) { + LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { /* * Block(s) are present, lets see if we have this tag in the * list */ - LIST_FOREACH(twait_block, chain, sctp_nxt_tagblock) { - for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { - if (twait_block->vtag_block[i].v_tag == 0) { - /* not used */ - continue; - } else if ((long)twait_block->vtag_block[i].tv_sec_at_expire < - now->tv_sec) { - /* Audit expires this guy */ - twait_block->vtag_block[i].tv_sec_at_expire = 0; - twait_block->vtag_block[i].v_tag = 0; - twait_block->vtag_block[i].lport = 0; - twait_block->vtag_block[i].rport = 0; - } else if ((twait_block->vtag_block[i].v_tag == tag) && - (twait_block->vtag_block[i].lport == lport) && - (twait_block->vtag_block[i].rport == rport)) { - /* Bad tag, sorry :< */ - SCTP_INP_INFO_RUNLOCK(); - return (0); - } + for (i = 0; i < SCTP_NUMBER_IN_VTAG_BLOCK; i++) { + if (twait_block->vtag_block[i].v_tag == 0) { + /* not used */ + continue; + } else if ((long)twait_block->vtag_block[i].tv_sec_at_expire < + now->tv_sec) { + /* Audit expires this guy */ + twait_block->vtag_block[i].tv_sec_at_expire = 0; + twait_block->vtag_block[i].v_tag = 0; + twait_block->vtag_block[i].lport = 0; + twait_block->vtag_block[i].rport = 0; + } else if ((twait_block->vtag_block[i].v_tag == tag) && + (twait_block->vtag_block[i].lport == lport) && + (twait_block->vtag_block[i].rport == rport)) { + /* Bad tag, sorry :< */ + SCTP_INP_INFO_RUNLOCK(); + return (0); } } }