1163953Srrs/*- 2185694Srrs * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. 3235828Stuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 4235828Stuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 5163953Srrs * 6163953Srrs * Redistribution and use in source and binary forms, with or without 7163953Srrs * modification, are permitted provided that the following conditions are met: 8163953Srrs * 9163953Srrs * a) Redistributions of source code must retain the above copyright notice, 10228653Stuexen * this list of conditions and the following disclaimer. 11163953Srrs * 12163953Srrs * b) Redistributions in binary form must reproduce the above copyright 13163953Srrs * notice, this list of conditions and the following disclaimer in 14228653Stuexen * the documentation and/or other materials provided with the distribution. 15163953Srrs * 16163953Srrs * c) Neither the name of Cisco Systems, Inc. nor the names of its 17163953Srrs * contributors may be used to endorse or promote products derived 18163953Srrs * from this software without specific prior written permission. 19163953Srrs * 20163953Srrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21163953Srrs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22163953Srrs * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23163953Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24163953Srrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25163953Srrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26163953Srrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27163953Srrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28163953Srrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29163953Srrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30163953Srrs * THE POSSIBILITY OF SUCH DAMAGE. 31163953Srrs */ 32163953Srrs 33163953Srrs#include <sys/cdefs.h> 34163953Srrs__FBSDID("$FreeBSD$"); 35163953Srrs 36163953Srrs#include <netinet/sctp_os.h> 37163953Srrs#include <netinet/sctp_var.h> 38167598Srrs#include <netinet/sctp_sysctl.h> 39163953Srrs#include <netinet/sctp_pcb.h> 40163953Srrs#include <netinet/sctp_header.h> 41163953Srrs#include <netinet/sctputil.h> 42163953Srrs#include <netinet/sctp_output.h> 43163953Srrs#include <netinet/sctp_input.h> 44163953Srrs#include <netinet/sctp_auth.h> 45163953Srrs#include <netinet/sctp_indata.h> 46163953Srrs#include <netinet/sctp_asconf.h> 47170091Srrs#include <netinet/sctp_bsd_addr.h> 48172091Srrs#include <netinet/sctp_timer.h> 49188067Srrs#include <netinet/sctp_crc32.h> 50270350Stuexen#if defined(INET) || defined(INET6) 51179157Srrs#include <netinet/udp.h> 52270350Stuexen#endif 53218211Srrs#include <sys/smp.h> 54163953Srrs 55163953Srrs 56163953Srrs 57163953Srrsstatic void 58163953Srrssctp_stop_all_cookie_timers(struct sctp_tcb *stcb) 59163953Srrs{ 60163953Srrs struct sctp_nets *net; 61163953Srrs 62165220Srrs /* 63165220Srrs * This now not only stops all cookie timers it also stops any INIT 64165220Srrs * timers as well. This will make sure that the timers are stopped 65165220Srrs * in all collision cases. 66165220Srrs */ 67163953Srrs SCTP_TCB_LOCK_ASSERT(stcb); 68163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 69165220Srrs if (net->rxt_timer.type == SCTP_TIMER_TYPE_COOKIE) { 70163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, 71163953Srrs stcb->sctp_ep, 72163953Srrs stcb, 73165220Srrs net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_1); 74165220Srrs } else if (net->rxt_timer.type == SCTP_TIMER_TYPE_INIT) { 75165220Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, 76165220Srrs stcb->sctp_ep, 77165220Srrs stcb, 78165220Srrs net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_2); 79163953Srrs } 80163953Srrs } 81163953Srrs} 82163953Srrs 83163953Srrs/* INIT handler */ 84163953Srrsstatic void 85237715Stuexensctp_handle_init(struct mbuf *m, int iphlen, int offset, 86237715Stuexen struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 87237049Stuexen struct sctp_init_chunk *cp, struct sctp_inpcb *inp, 88237049Stuexen struct sctp_tcb *stcb, int *abort_no_unlock, 89237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 90237049Stuexen uint32_t vrf_id, uint16_t port) 91163953Srrs{ 92163953Srrs struct sctp_init *init; 93163953Srrs struct mbuf *op_err; 94163953Srrs 95169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_init: handling INIT tcb:%p\n", 96240148Stuexen (void *)stcb); 97172396Srrs if (stcb == NULL) { 98172396Srrs SCTP_INP_RLOCK(inp); 99172396Srrs } 100229774Stuexen /* validate length */ 101163953Srrs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) { 102267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 103237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 104237049Stuexen use_mflowid, mflowid, 105179157Srrs vrf_id, port); 106168299Srrs if (stcb) 107168299Srrs *abort_no_unlock = 1; 108172396Srrs goto outnow; 109163953Srrs } 110163953Srrs /* validate parameters */ 111229774Stuexen init = &cp->init; 112163953Srrs if (init->initiate_tag == 0) { 113163953Srrs /* protocol error... send abort */ 114267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 115237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 116237049Stuexen use_mflowid, mflowid, 117179157Srrs vrf_id, port); 118168299Srrs if (stcb) 119168299Srrs *abort_no_unlock = 1; 120172396Srrs goto outnow; 121163953Srrs } 122163953Srrs if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) { 123163953Srrs /* invalid parameter... send abort */ 124267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 125237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 126237049Stuexen use_mflowid, mflowid, 127179157Srrs vrf_id, port); 128171440Srrs if (stcb) 129171440Srrs *abort_no_unlock = 1; 130172396Srrs goto outnow; 131163953Srrs } 132163953Srrs if (init->num_inbound_streams == 0) { 133163953Srrs /* protocol error... send abort */ 134267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 135237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 136237049Stuexen use_mflowid, mflowid, 137179157Srrs vrf_id, port); 138168299Srrs if (stcb) 139168299Srrs *abort_no_unlock = 1; 140172396Srrs goto outnow; 141163953Srrs } 142163953Srrs if (init->num_outbound_streams == 0) { 143163953Srrs /* protocol error... send abort */ 144267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 145237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 146237049Stuexen use_mflowid, mflowid, 147179157Srrs vrf_id, port); 148168299Srrs if (stcb) 149168299Srrs *abort_no_unlock = 1; 150172396Srrs goto outnow; 151163953Srrs } 152163953Srrs if (sctp_validate_init_auth_params(m, offset + sizeof(*cp), 153229774Stuexen offset + ntohs(cp->ch.chunk_length))) { 154163953Srrs /* auth parameter(s) error... send abort */ 155267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 156267723Stuexen "Problem with AUTH parameters"); 157267723Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 158237049Stuexen use_mflowid, mflowid, 159237049Stuexen vrf_id, port); 160168299Srrs if (stcb) 161168299Srrs *abort_no_unlock = 1; 162172396Srrs goto outnow; 163163953Srrs } 164229774Stuexen /* 165229774Stuexen * We are only accepting if we have a socket with positive 166229774Stuexen * so_qlimit. 167229774Stuexen */ 168229774Stuexen if ((stcb == NULL) && 169229774Stuexen ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 170229774Stuexen (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 171229774Stuexen (inp->sctp_socket == NULL) || 172229774Stuexen (inp->sctp_socket->so_qlimit == 0))) { 173229774Stuexen /* 174229774Stuexen * FIX ME ?? What about TCP model and we have a 175229774Stuexen * match/restart case? Actually no fix is needed. the lookup 176229774Stuexen * will always find the existing assoc so stcb would not be 177229774Stuexen * NULL. It may be questionable to do this since we COULD 178229774Stuexen * just send back the INIT-ACK and hope that the app did 179229774Stuexen * accept()'s by the time the COOKIE was sent. But there is 180229774Stuexen * a price to pay for COOKIE generation and I don't want to 181229774Stuexen * pay it on the chance that the app will actually do some 182229774Stuexen * accepts(). The App just looses and should NOT be in this 183229774Stuexen * state :-) 184229774Stuexen */ 185229805Stuexen if (SCTP_BASE_SYSCTL(sctp_blackhole) == 0) { 186267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 187267723Stuexen "No listener"); 188267723Stuexen sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, 189237049Stuexen use_mflowid, mflowid, 190237049Stuexen vrf_id, port); 191229805Stuexen } 192229774Stuexen goto outnow; 193229774Stuexen } 194229774Stuexen if ((stcb != NULL) && 195229774Stuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT)) { 196229774Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending SHUTDOWN-ACK\n"); 197229774Stuexen sctp_send_shutdown_ack(stcb, NULL); 198229774Stuexen sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 199229774Stuexen } else { 200229774Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n"); 201237715Stuexen sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, src, dst, 202237715Stuexen sh, cp, 203237049Stuexen use_mflowid, mflowid, 204237049Stuexen vrf_id, port, 205229774Stuexen ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED)); 206229774Stuexen } 207172396Srrsoutnow: 208172396Srrs if (stcb == NULL) { 209172396Srrs SCTP_INP_RUNLOCK(inp); 210172396Srrs } 211163953Srrs} 212163953Srrs 213163953Srrs/* 214163953Srrs * process peer "INIT/INIT-ACK" chunk returns value < 0 on error 215163953Srrs */ 216171158Srrs 217171158Srrsint 218221627Stuexensctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked 219221627Stuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 220221627Stuexen SCTP_UNUSED 221221627Stuexen#endif 222221627Stuexen) 223171158Srrs{ 224171158Srrs int unsent_data = 0; 225217760Stuexen unsigned int i; 226217760Stuexen struct sctp_stream_queue_pending *sp; 227171158Srrs struct sctp_association *asoc; 228171158Srrs 229171158Srrs /* 230171158Srrs * This function returns the number of streams that have true unsent 231171158Srrs * data on them. Note that as it looks through it will clean up any 232171158Srrs * places that have old data that has been sent but left at top of 233171158Srrs * stream queue. 234171158Srrs */ 235171158Srrs asoc = &stcb->asoc; 236171158Srrs SCTP_TCB_SEND_LOCK(stcb); 237217760Stuexen if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 238217760Stuexen /* Check to see if some data queued */ 239217760Stuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 240217760Stuexen /* sa_ignore FREED_MEMORY */ 241217760Stuexen sp = TAILQ_FIRST(&stcb->asoc.strmout[i].outqueue); 242217760Stuexen if (sp == NULL) { 243217760Stuexen continue; 244217760Stuexen } 245171158Srrs if ((sp->msg_is_complete) && 246171158Srrs (sp->length == 0) && 247171158Srrs (sp->sender_all_done)) { 248171158Srrs /* 249171158Srrs * We are doing differed cleanup. Last time 250171158Srrs * through when we took all the data the 251171158Srrs * sender_all_done was not set. 252171158Srrs */ 253171158Srrs if (sp->put_last_out == 0) { 254171158Srrs SCTP_PRINTF("Gak, put out entire msg with NO end!-1\n"); 255171158Srrs SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d\n", 256171158Srrs sp->sender_all_done, 257171158Srrs sp->length, 258171158Srrs sp->msg_is_complete, 259171158Srrs sp->put_last_out); 260171158Srrs } 261217760Stuexen atomic_subtract_int(&stcb->asoc.stream_queue_cnt, 1); 262217760Stuexen TAILQ_REMOVE(&stcb->asoc.strmout[i].outqueue, sp, next); 263212712Stuexen if (sp->net) { 264212712Stuexen sctp_free_remote_addr(sp->net); 265212712Stuexen sp->net = NULL; 266212712Stuexen } 267171158Srrs if (sp->data) { 268171158Srrs sctp_m_freem(sp->data); 269171158Srrs sp->data = NULL; 270171158Srrs } 271221627Stuexen sctp_free_a_strmoq(stcb, sp, so_locked); 272171158Srrs } else { 273171158Srrs unsent_data++; 274216822Stuexen break; 275171158Srrs } 276171158Srrs } 277171158Srrs } 278171158Srrs SCTP_TCB_SEND_UNLOCK(stcb); 279171158Srrs return (unsent_data); 280171158Srrs} 281171158Srrs 282163953Srrsstatic int 283228653Stuexensctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) 284163953Srrs{ 285163953Srrs struct sctp_init *init; 286163953Srrs struct sctp_association *asoc; 287163953Srrs struct sctp_nets *lnet; 288163953Srrs unsigned int i; 289163953Srrs 290163953Srrs init = &cp->init; 291163953Srrs asoc = &stcb->asoc; 292163953Srrs /* save off parameters */ 293163953Srrs asoc->peer_vtag = ntohl(init->initiate_tag); 294163953Srrs asoc->peers_rwnd = ntohl(init->a_rwnd); 295218129Srrs /* init tsn's */ 296218129Srrs asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1; 297218129Srrs 298212712Stuexen if (!TAILQ_EMPTY(&asoc->nets)) { 299163953Srrs /* update any ssthresh's that may have a default */ 300163953Srrs TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) { 301163953Srrs lnet->ssthresh = asoc->peers_rwnd; 302179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) { 303170744Srrs sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_INITIALIZATION); 304170744Srrs } 305163953Srrs } 306163953Srrs } 307164181Srrs SCTP_TCB_SEND_LOCK(stcb); 308163953Srrs if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) { 309163953Srrs unsigned int newcnt; 310163953Srrs struct sctp_stream_out *outs; 311216822Stuexen struct sctp_stream_queue_pending *sp, *nsp; 312216822Stuexen struct sctp_tmit_chunk *chk, *nchk; 313163953Srrs 314196260Stuexen /* abandon the upper streams */ 315163953Srrs newcnt = ntohs(init->num_inbound_streams); 316216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { 317216822Stuexen if (chk->rec.data.stream_number >= newcnt) { 318216822Stuexen TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); 319216822Stuexen asoc->send_queue_cnt--; 320242714Stuexen if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 321242714Stuexen asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 322242714Stuexen#ifdef INVARIANTS 323242714Stuexen } else { 324242714Stuexen panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 325242714Stuexen#endif 326242714Stuexen } 327216822Stuexen if (chk->data != NULL) { 328216822Stuexen sctp_free_bufspace(stcb, asoc, chk, 1); 329235416Stuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 330235416Stuexen 0, chk, SCTP_SO_NOT_LOCKED); 331216822Stuexen if (chk->data) { 332216822Stuexen sctp_m_freem(chk->data); 333216822Stuexen chk->data = NULL; 334196260Stuexen } 335196260Stuexen } 336221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 337216822Stuexen /* sa_ignore FREED_MEMORY */ 338196260Stuexen } 339196260Stuexen } 340163953Srrs if (asoc->strmout) { 341163953Srrs for (i = newcnt; i < asoc->pre_open_streams; i++) { 342163953Srrs outs = &asoc->strmout[i]; 343216822Stuexen TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { 344196260Stuexen TAILQ_REMOVE(&outs->outqueue, sp, next); 345163953Srrs asoc->stream_queue_cnt--; 346163953Srrs sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, 347235416Stuexen stcb, 0, sp, SCTP_SO_NOT_LOCKED); 348163953Srrs if (sp->data) { 349163953Srrs sctp_m_freem(sp->data); 350163953Srrs sp->data = NULL; 351163953Srrs } 352212712Stuexen if (sp->net) { 353212712Stuexen sctp_free_remote_addr(sp->net); 354212712Stuexen sp->net = NULL; 355212712Stuexen } 356163953Srrs /* Free the chunk */ 357221627Stuexen sctp_free_a_strmoq(stcb, sp, SCTP_SO_NOT_LOCKED); 358169655Srrs /* sa_ignore FREED_MEMORY */ 359163953Srrs } 360163953Srrs } 361163953Srrs } 362196260Stuexen /* cut back the count */ 363163953Srrs asoc->pre_open_streams = newcnt; 364163953Srrs } 365164181Srrs SCTP_TCB_SEND_UNLOCK(stcb); 366188854Srrs asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams; 367218129Srrs 368185694Srrs /* EY - nr_sack: initialize highest tsn in nr_mapping_array */ 369185694Srrs asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 370179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 371170744Srrs sctp_log_map(0, 5, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 372170744Srrs } 373163953Srrs /* This is the next one we expect */ 374163953Srrs asoc->str_reset_seq_in = asoc->asconf_seq_in + 1; 375163953Srrs 376163953Srrs asoc->mapping_array_base_tsn = ntohl(init->initial_tsn); 377180955Srrs asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->asconf_seq_in; 378218129Srrs 379163953Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 380163953Srrs /* open the requested streams */ 381170091Srrs 382163953Srrs if (asoc->strmin != NULL) { 383163953Srrs /* Free the old ones */ 384216822Stuexen struct sctp_queued_to_read *ctl, *nctl; 385164181Srrs 386164181Srrs for (i = 0; i < asoc->streamincnt; i++) { 387216822Stuexen TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) { 388164181Srrs TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next); 389164181Srrs sctp_free_remote_addr(ctl->whoFrom); 390171158Srrs ctl->whoFrom = NULL; 391164181Srrs sctp_m_freem(ctl->data); 392164181Srrs ctl->data = NULL; 393164181Srrs sctp_free_a_readq(stcb, ctl); 394164181Srrs } 395164181Srrs } 396170091Srrs SCTP_FREE(asoc->strmin, SCTP_M_STRMI); 397163953Srrs } 398252779Stuexen if (asoc->max_inbound_streams > ntohs(init->num_outbound_streams)) { 399252779Stuexen asoc->streamincnt = ntohs(init->num_outbound_streams); 400252779Stuexen } else { 401252779Stuexen asoc->streamincnt = asoc->max_inbound_streams; 402164181Srrs } 403163953Srrs SCTP_MALLOC(asoc->strmin, struct sctp_stream_in *, asoc->streamincnt * 404170091Srrs sizeof(struct sctp_stream_in), SCTP_M_STRMI); 405163953Srrs if (asoc->strmin == NULL) { 406163953Srrs /* we didn't get memory for the streams! */ 407169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "process_init: couldn't get memory for the streams!\n"); 408163953Srrs return (-1); 409163953Srrs } 410163953Srrs for (i = 0; i < asoc->streamincnt; i++) { 411163953Srrs asoc->strmin[i].stream_no = i; 412163953Srrs asoc->strmin[i].last_sequence_delivered = 0xffff; 413163953Srrs TAILQ_INIT(&asoc->strmin[i].inqueue); 414168943Srrs asoc->strmin[i].delivery_started = 0; 415163953Srrs } 416163953Srrs /* 417163953Srrs * load_address_from_init will put the addresses into the 418163953Srrs * association when the COOKIE is processed or the INIT-ACK is 419163953Srrs * processed. Both types of COOKIE's existing and new call this 420163953Srrs * routine. It will remove addresses that are no longer in the 421163953Srrs * association (for the restarting case where addresses are 422163953Srrs * removed). Up front when the INIT arrives we will discard it if it 423163953Srrs * is a restart and new addresses have been added. 424163953Srrs */ 425169655Srrs /* sa_ignore MEMLEAK */ 426163953Srrs return (0); 427163953Srrs} 428163953Srrs 429163953Srrs/* 430163953Srrs * INIT-ACK message processing/consumption returns value < 0 on error 431163953Srrs */ 432163953Srrsstatic int 433237715Stuexensctp_process_init_ack(struct mbuf *m, int iphlen, int offset, 434237715Stuexen struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 435237049Stuexen struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 436237049Stuexen struct sctp_nets *net, int *abort_no_unlock, 437237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 438237049Stuexen uint32_t vrf_id) 439163953Srrs{ 440163953Srrs struct sctp_association *asoc; 441163953Srrs struct mbuf *op_err; 442163953Srrs int retval, abort_flag; 443163953Srrs uint32_t initack_limit; 444185694Srrs int nat_friendly = 0; 445163953Srrs 446163953Srrs /* First verify that we have no illegal param's */ 447163953Srrs abort_flag = 0; 448163953Srrs 449163953Srrs op_err = sctp_arethere_unrecognized_parameters(m, 450163953Srrs (offset + sizeof(struct sctp_init_chunk)), 451185694Srrs &abort_flag, (struct sctp_chunkhdr *)cp, &nat_friendly); 452163953Srrs if (abort_flag) { 453163953Srrs /* Send an abort and notify peer */ 454235360Stuexen sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 455170056Srrs *abort_no_unlock = 1; 456163953Srrs return (-1); 457163953Srrs } 458163953Srrs asoc = &stcb->asoc; 459185694Srrs asoc->peer_supports_nat = (uint8_t) nat_friendly; 460163953Srrs /* process the peer's parameters in the INIT-ACK */ 461228653Stuexen retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb); 462163953Srrs if (retval < 0) { 463163953Srrs return (retval); 464163953Srrs } 465163953Srrs initack_limit = offset + ntohs(cp->ch.chunk_length); 466163953Srrs /* load all addresses */ 467228653Stuexen if ((retval = sctp_load_addresses_from_init(stcb, m, 468237715Stuexen (offset + sizeof(struct sctp_init_chunk)), initack_limit, 469237715Stuexen src, dst, NULL))) { 470267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 471267723Stuexen "Problem with address parameters"); 472169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 473169420Srrs "Load addresses from INIT causes an abort %d\n", 474169420Srrs retval); 475237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 476267723Stuexen src, dst, sh, op_err, 477237049Stuexen use_mflowid, mflowid, 478237049Stuexen vrf_id, net->port); 479168299Srrs *abort_no_unlock = 1; 480163953Srrs return (-1); 481163953Srrs } 482171477Srrs /* if the peer doesn't support asconf, flush the asconf queue */ 483270362Stuexen if (asoc->asconf_supported == 0) { 484216822Stuexen struct sctp_asconf_addr *param, *nparam; 485171477Srrs 486216822Stuexen TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) { 487216822Stuexen TAILQ_REMOVE(&asoc->asconf_queue, param, next); 488216822Stuexen SCTP_FREE(param, SCTP_M_ASC_ADDR); 489171477Srrs } 490171477Srrs } 491163953Srrs stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs, 492163953Srrs stcb->asoc.local_hmacs); 493163953Srrs if (op_err) { 494163953Srrs sctp_queue_op_err(stcb, op_err); 495163953Srrs /* queuing will steal away the mbuf chain to the out queue */ 496163953Srrs op_err = NULL; 497163953Srrs } 498163953Srrs /* extract the cookie and queue it to "echo" it back... */ 499179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 500171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 501171943Srrs stcb->asoc.overall_error_count, 502171943Srrs 0, 503171943Srrs SCTP_FROM_SCTP_INPUT, 504171943Srrs __LINE__); 505171943Srrs } 506163953Srrs stcb->asoc.overall_error_count = 0; 507163953Srrs net->error_count = 0; 508163953Srrs 509163953Srrs /* 510163953Srrs * Cancel the INIT timer, We do this first before queueing the 511163953Srrs * cookie. We always cancel at the primary to assue that we are 512163953Srrs * canceling the timer started by the INIT which always goes to the 513163953Srrs * primary. 514163953Srrs */ 515163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb, 516165220Srrs asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4); 517163953Srrs 518165220Srrs /* calculate the RTO */ 519218186Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy, 520219397Srrs SCTP_RTT_FROM_NON_DATA); 521165220Srrs 522163953Srrs retval = sctp_send_cookie_echo(m, offset, stcb, net); 523163953Srrs if (retval < 0) { 524163953Srrs /* 525163953Srrs * No cookie, we probably should send a op error. But in any 526163953Srrs * case if there is no cookie in the INIT-ACK, we can 527163953Srrs * abandon the peer, its broke. 528163953Srrs */ 529163953Srrs if (retval == -3) { 530163953Srrs /* We abort with an error of missing mandatory param */ 531267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_MISSING_PARAM, ""); 532163953Srrs if (op_err) { 533163953Srrs /* 534163953Srrs * Expand beyond to include the mandatory 535163953Srrs * param cookie 536163953Srrs */ 537163953Srrs struct sctp_inv_mandatory_param *mp; 538163953Srrs 539165647Srrs SCTP_BUF_LEN(op_err) = 540163953Srrs sizeof(struct sctp_inv_mandatory_param); 541163953Srrs mp = mtod(op_err, 542163953Srrs struct sctp_inv_mandatory_param *); 543163953Srrs /* Subtract the reserved param */ 544163953Srrs mp->length = 545163953Srrs htons(sizeof(struct sctp_inv_mandatory_param) - 2); 546163953Srrs mp->num_param = htonl(1); 547163953Srrs mp->param = htons(SCTP_STATE_COOKIE); 548163953Srrs mp->resv = 0; 549163953Srrs } 550163953Srrs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 551237715Stuexen src, dst, sh, op_err, 552237049Stuexen use_mflowid, mflowid, 553237049Stuexen vrf_id, net->port); 554168299Srrs *abort_no_unlock = 1; 555163953Srrs } 556163953Srrs return (retval); 557163953Srrs } 558163953Srrs return (0); 559163953Srrs} 560163953Srrs 561163953Srrsstatic void 562163953Srrssctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, 563163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 564163953Srrs{ 565271746Stuexen union sctp_sockstore store; 566212225Srrs struct sctp_nets *r_net, *f_net; 567163953Srrs struct timeval tv; 568172396Srrs int req_prim = 0; 569224641Stuexen uint16_t old_error_counter; 570163953Srrs 571163953Srrs if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) { 572163953Srrs /* Invalid length */ 573163953Srrs return; 574163953Srrs } 575163953Srrs memset(&store, 0, sizeof(store)); 576221249Stuexen switch (cp->heartbeat.hb_info.addr_family) { 577221249Stuexen#ifdef INET 578221249Stuexen case AF_INET: 579221249Stuexen if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) { 580271746Stuexen store.sin.sin_family = cp->heartbeat.hb_info.addr_family; 581271746Stuexen store.sin.sin_len = cp->heartbeat.hb_info.addr_len; 582271746Stuexen store.sin.sin_port = stcb->rport; 583271746Stuexen memcpy(&store.sin.sin_addr, cp->heartbeat.hb_info.address, 584271746Stuexen sizeof(store.sin.sin_addr)); 585221249Stuexen } else { 586221249Stuexen return; 587221249Stuexen } 588221249Stuexen break; 589221249Stuexen#endif 590221249Stuexen#ifdef INET6 591221249Stuexen case AF_INET6: 592221249Stuexen if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) { 593271746Stuexen store.sin6.sin6_family = cp->heartbeat.hb_info.addr_family; 594271746Stuexen store.sin6.sin6_len = cp->heartbeat.hb_info.addr_len; 595271746Stuexen store.sin6.sin6_port = stcb->rport; 596271746Stuexen memcpy(&store.sin6.sin6_addr, cp->heartbeat.hb_info.address, sizeof(struct in6_addr)); 597221249Stuexen } else { 598221249Stuexen return; 599221249Stuexen } 600221249Stuexen break; 601221249Stuexen#endif 602221249Stuexen default: 603163953Srrs return; 604163953Srrs } 605271746Stuexen r_net = sctp_findnet(stcb, &store.sa); 606163953Srrs if (r_net == NULL) { 607169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n"); 608163953Srrs return; 609163953Srrs } 610163953Srrs if ((r_net && (r_net->dest_state & SCTP_ADDR_UNCONFIRMED)) && 611163953Srrs (r_net->heartbeat_random1 == cp->heartbeat.hb_info.random_value1) && 612163953Srrs (r_net->heartbeat_random2 == cp->heartbeat.hb_info.random_value2)) { 613163953Srrs /* 614163953Srrs * If the its a HB and it's random value is correct when can 615163953Srrs * confirm the destination. 616163953Srrs */ 617163953Srrs r_net->dest_state &= ~SCTP_ADDR_UNCONFIRMED; 618167598Srrs if (r_net->dest_state & SCTP_ADDR_REQ_PRIMARY) { 619167598Srrs stcb->asoc.primary_destination = r_net; 620167598Srrs r_net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY; 621212225Srrs f_net = TAILQ_FIRST(&stcb->asoc.nets); 622212225Srrs if (f_net != r_net) { 623167598Srrs /* 624167598Srrs * first one on the list is NOT the primary 625167598Srrs * sctp_cmpaddr() is much more efficent if 626167598Srrs * the primary is the first on the list, 627167598Srrs * make it so. 628167598Srrs */ 629212225Srrs TAILQ_REMOVE(&stcb->asoc.nets, r_net, sctp_next); 630212225Srrs TAILQ_INSERT_HEAD(&stcb->asoc.nets, r_net, sctp_next); 631167598Srrs } 632172396Srrs req_prim = 1; 633167598Srrs } 634163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 635172090Srrs stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED); 636224641Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 637224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 638163953Srrs } 639224641Stuexen old_error_counter = r_net->error_count; 640163953Srrs r_net->error_count = 0; 641163953Srrs r_net->hb_responded = 1; 642163953Srrs tv.tv_sec = cp->heartbeat.hb_info.time_value_1; 643163953Srrs tv.tv_usec = cp->heartbeat.hb_info.time_value_2; 644224641Stuexen /* Now lets do a RTO with this */ 645224641Stuexen r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy, 646224641Stuexen SCTP_RTT_FROM_NON_DATA); 647224641Stuexen if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) { 648163953Srrs r_net->dest_state |= SCTP_ADDR_REACHABLE; 649163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 650235414Stuexen 0, (void *)r_net, SCTP_SO_NOT_LOCKED); 651163953Srrs } 652224641Stuexen if (r_net->dest_state & SCTP_ADDR_PF) { 653224641Stuexen r_net->dest_state &= ~SCTP_ADDR_PF; 654224641Stuexen stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net); 655224641Stuexen } 656224641Stuexen if (old_error_counter > 0) { 657224641Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 658224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 659224641Stuexen } 660224641Stuexen if (r_net == stcb->asoc.primary_destination) { 661224641Stuexen if (stcb->asoc.alternate) { 662224641Stuexen /* release the alternate, primary is good */ 663224641Stuexen sctp_free_remote_addr(stcb->asoc.alternate); 664224641Stuexen stcb->asoc.alternate = NULL; 665171440Srrs } 666171440Srrs } 667172396Srrs /* Mobility adaptation */ 668172396Srrs if (req_prim) { 669172396Srrs if ((sctp_is_mobility_feature_on(stcb->sctp_ep, 670172396Srrs SCTP_MOBILITY_BASE) || 671172396Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 672172396Srrs SCTP_MOBILITY_FASTHANDOFF)) && 673172396Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 674172396Srrs SCTP_MOBILITY_PRIM_DELETED)) { 675172396Srrs 676172396Srrs sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7); 677172396Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 678172396Srrs SCTP_MOBILITY_FASTHANDOFF)) { 679172396Srrs sctp_assoc_immediate_retrans(stcb, 680172396Srrs stcb->asoc.primary_destination); 681172396Srrs } 682172396Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 683172396Srrs SCTP_MOBILITY_BASE)) { 684212712Stuexen sctp_move_chunks_from_net(stcb, 685212712Stuexen stcb->asoc.deleted_primary); 686172396Srrs } 687172396Srrs sctp_delete_prim_timer(stcb->sctp_ep, stcb, 688172396Srrs stcb->asoc.deleted_primary); 689172396Srrs } 690172396Srrs } 691163953Srrs} 692163953Srrs 693185694Srrsstatic int 694185694Srrssctp_handle_nat_colliding_state(struct sctp_tcb *stcb) 695185694Srrs{ 696185694Srrs /* 697185694Srrs * return 0 means we want you to proceed with the abort non-zero 698185694Srrs * means no abort processing 699185694Srrs */ 700185694Srrs struct sctpasochead *head; 701185694Srrs 702185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) { 703185694Srrs /* generate a new vtag and send init */ 704185694Srrs LIST_REMOVE(stcb, sctp_asocs); 705185694Srrs stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 706185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 707185694Srrs /* 708185694Srrs * put it in the bucket in the vtag hash of assoc's for the 709185694Srrs * system 710185694Srrs */ 711185694Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 712185694Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 713185694Srrs return (1); 714185694Srrs } 715185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 716185694Srrs /* 717185694Srrs * treat like a case where the cookie expired i.e.: - dump 718185694Srrs * current cookie. - generate a new vtag. - resend init. 719185694Srrs */ 720185694Srrs /* generate a new vtag and send init */ 721185694Srrs LIST_REMOVE(stcb, sctp_asocs); 722185694Srrs stcb->asoc.state &= ~SCTP_STATE_COOKIE_ECHOED; 723185694Srrs stcb->asoc.state |= SCTP_STATE_COOKIE_WAIT; 724185694Srrs sctp_stop_all_cookie_timers(stcb); 725185694Srrs sctp_toss_old_cookies(stcb, &stcb->asoc); 726185694Srrs stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 727185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 728185694Srrs /* 729185694Srrs * put it in the bucket in the vtag hash of assoc's for the 730185694Srrs * system 731185694Srrs */ 732185694Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 733185694Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 734185694Srrs return (1); 735185694Srrs } 736185694Srrs return (0); 737185694Srrs} 738185694Srrs 739185694Srrsstatic int 740185694Srrssctp_handle_nat_missing_state(struct sctp_tcb *stcb, 741185694Srrs struct sctp_nets *net) 742185694Srrs{ 743185694Srrs /* 744185694Srrs * return 0 means we want you to proceed with the abort non-zero 745185694Srrs * means no abort processing 746185694Srrs */ 747270362Stuexen if (stcb->asoc.auth_supported == 0) { 748185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n"); 749185694Srrs return (0); 750185694Srrs } 751185694Srrs sctp_asconf_send_nat_state_update(stcb, net); 752185694Srrs return (1); 753185694Srrs} 754185694Srrs 755185694Srrs 756163953Srrsstatic void 757235360Stuexensctp_handle_abort(struct sctp_abort_chunk *abort, 758163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 759163953Srrs{ 760237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 761172090Srrs struct socket *so; 762172090Srrs 763172090Srrs#endif 764185694Srrs uint16_t len; 765235360Stuexen uint16_t error; 766172090Srrs 767169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n"); 768163953Srrs if (stcb == NULL) 769163953Srrs return; 770163953Srrs 771235360Stuexen len = ntohs(abort->ch.chunk_length); 772185694Srrs if (len > sizeof(struct sctp_chunkhdr)) { 773185694Srrs /* 774185694Srrs * Need to check the cause codes for our two magic nat 775185694Srrs * aborts which don't kill the assoc necessarily. 776185694Srrs */ 777185694Srrs struct sctp_missing_nat_state *natc; 778185694Srrs 779235360Stuexen natc = (struct sctp_missing_nat_state *)(abort + 1); 780235360Stuexen error = ntohs(natc->cause); 781235360Stuexen if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) { 782185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 783235360Stuexen abort->ch.chunk_flags); 784185694Srrs if (sctp_handle_nat_colliding_state(stcb)) { 785185694Srrs return; 786185694Srrs } 787235360Stuexen } else if (error == SCTP_CAUSE_NAT_MISSING_STATE) { 788185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 789235360Stuexen abort->ch.chunk_flags); 790185694Srrs if (sctp_handle_nat_missing_state(stcb, net)) { 791185694Srrs return; 792185694Srrs } 793185694Srrs } 794235360Stuexen } else { 795235360Stuexen error = 0; 796185694Srrs } 797163953Srrs /* stop any receive timers */ 798171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_6); 799163953Srrs /* notify user of the abort and clean up... */ 800235403Stuexen sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED); 801163953Srrs /* free the tcb */ 802163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_aborted); 803163953Srrs if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 804163953Srrs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 805163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 806163953Srrs } 807168859Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 808168859Srrs sctp_print_out_track_log(stcb); 809168859Srrs#endif 810237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 811172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 812172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 813172090Srrs SCTP_TCB_UNLOCK(stcb); 814172090Srrs SCTP_SOCKET_LOCK(so, 1); 815172090Srrs SCTP_TCB_LOCK(stcb); 816172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 817172090Srrs#endif 818171990Srrs stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 819171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 820171943Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_6); 821237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 822172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 823172090Srrs#endif 824169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n"); 825163953Srrs} 826163953Srrs 827163953Srrsstatic void 828224641Stuexensctp_start_net_timers(struct sctp_tcb *stcb) 829224641Stuexen{ 830224641Stuexen uint32_t cnt_hb_sent; 831224641Stuexen struct sctp_nets *net; 832224641Stuexen 833224641Stuexen cnt_hb_sent = 0; 834224641Stuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 835224641Stuexen /* 836224641Stuexen * For each network start: 1) A pmtu timer. 2) A HB timer 3) 837224641Stuexen * If the dest in unconfirmed send a hb as well if under 838224641Stuexen * max_hb_burst have been sent. 839224641Stuexen */ 840224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net); 841224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 842224641Stuexen if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) && 843224641Stuexen (cnt_hb_sent < SCTP_BASE_SYSCTL(sctp_hb_maxburst))) { 844224641Stuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 845224641Stuexen cnt_hb_sent++; 846224641Stuexen } 847224641Stuexen } 848224641Stuexen if (cnt_hb_sent) { 849224641Stuexen sctp_chunk_output(stcb->sctp_ep, stcb, 850224641Stuexen SCTP_OUTPUT_FROM_COOKIE_ACK, 851224641Stuexen SCTP_SO_NOT_LOCKED); 852224641Stuexen } 853224641Stuexen} 854224641Stuexen 855224641Stuexen 856224641Stuexenstatic void 857163953Srrssctp_handle_shutdown(struct sctp_shutdown_chunk *cp, 858163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag) 859163953Srrs{ 860163953Srrs struct sctp_association *asoc; 861163953Srrs int some_on_streamwheel; 862163953Srrs 863237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 864172090Srrs struct socket *so; 865172090Srrs 866172090Srrs#endif 867172090Srrs 868169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 869169420Srrs "sctp_handle_shutdown: handling SHUTDOWN\n"); 870163953Srrs if (stcb == NULL) 871163953Srrs return; 872165220Srrs asoc = &stcb->asoc; 873165220Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 874165220Srrs (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 875163953Srrs return; 876163953Srrs } 877163953Srrs if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) { 878163953Srrs /* Shutdown NOT the expected size */ 879163953Srrs return; 880163953Srrs } else { 881228653Stuexen sctp_update_acked(stcb, cp, abort_flag); 882199477Stuexen if (*abort_flag) { 883199477Stuexen return; 884199477Stuexen } 885163953Srrs } 886165220Srrs if (asoc->control_pdapi) { 887163953Srrs /* 888163953Srrs * With a normal shutdown we assume the end of last record. 889163953Srrs */ 890163953Srrs SCTP_INP_READ_LOCK(stcb->sctp_ep); 891165220Srrs asoc->control_pdapi->end_added = 1; 892165220Srrs asoc->control_pdapi->pdapi_aborted = 1; 893165220Srrs asoc->control_pdapi = NULL; 894163953Srrs SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 895237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 896172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 897172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 898172090Srrs SCTP_TCB_UNLOCK(stcb); 899172090Srrs SCTP_SOCKET_LOCK(so, 1); 900172090Srrs SCTP_TCB_LOCK(stcb); 901172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 902172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 903172090Srrs /* assoc was freed while we were unlocked */ 904172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 905172090Srrs return; 906172090Srrs } 907172090Srrs#endif 908163996Srrs sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 909237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 910172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 911172090Srrs#endif 912163953Srrs } 913163953Srrs /* goto SHUTDOWN_RECEIVED state to block new requests */ 914163953Srrs if (stcb->sctp_socket) { 915163953Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 916170056Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) && 917163953Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 918171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_RECEIVED); 919172703Srrs SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 920163953Srrs /* 921163953Srrs * notify upper layer that peer has initiated a 922163953Srrs * shutdown 923163953Srrs */ 924172090Srrs sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 925163953Srrs 926163953Srrs /* reset time */ 927169378Srrs (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 928163953Srrs } 929163953Srrs } 930163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) { 931163953Srrs /* 932163953Srrs * stop the shutdown timer, since we WILL move to 933163953Srrs * SHUTDOWN-ACK-SENT. 934163953Srrs */ 935171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_8); 936163953Srrs } 937171158Srrs /* Now is there unsent data on a stream somewhere? */ 938221627Stuexen some_on_streamwheel = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED); 939163953Srrs 940163953Srrs if (!TAILQ_EMPTY(&asoc->send_queue) || 941163953Srrs !TAILQ_EMPTY(&asoc->sent_queue) || 942163953Srrs some_on_streamwheel) { 943163953Srrs /* By returning we will push more data out */ 944163953Srrs return; 945163953Srrs } else { 946163953Srrs /* no outstanding data to send, so move on... */ 947163953Srrs /* send SHUTDOWN-ACK */ 948163953Srrs /* move to SHUTDOWN-ACK-SENT state */ 949166675Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 950166675Srrs (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 951163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 952163953Srrs } 953171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); 954172703Srrs SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 955214918Stuexen sctp_stop_timers_for_shutdown(stcb); 956246588Stuexen sctp_send_shutdown_ack(stcb, net); 957163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, 958163953Srrs stcb, net); 959163953Srrs } 960163953Srrs} 961163953Srrs 962163953Srrsstatic void 963228653Stuexensctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, 964204141Stuexen struct sctp_tcb *stcb, 965204141Stuexen struct sctp_nets *net) 966163953Srrs{ 967163953Srrs struct sctp_association *asoc; 968163953Srrs 969237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 970172090Srrs struct socket *so; 971172090Srrs 972172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 973172090Srrs#endif 974169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 975169420Srrs "sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n"); 976163953Srrs if (stcb == NULL) 977163953Srrs return; 978163953Srrs 979163953Srrs asoc = &stcb->asoc; 980163953Srrs /* process according to association state */ 981204141Stuexen if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 982204141Stuexen (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 983204141Stuexen /* unexpected SHUTDOWN-ACK... do OOTB handling... */ 984204141Stuexen sctp_send_shutdown_complete(stcb, net, 1); 985204141Stuexen SCTP_TCB_UNLOCK(stcb); 986204141Stuexen return; 987204141Stuexen } 988163953Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) && 989163953Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { 990163953Srrs /* unexpected SHUTDOWN-ACK... so ignore... */ 991163953Srrs SCTP_TCB_UNLOCK(stcb); 992163953Srrs return; 993163953Srrs } 994165220Srrs if (asoc->control_pdapi) { 995163953Srrs /* 996163953Srrs * With a normal shutdown we assume the end of last record. 997163953Srrs */ 998163953Srrs SCTP_INP_READ_LOCK(stcb->sctp_ep); 999165220Srrs asoc->control_pdapi->end_added = 1; 1000165220Srrs asoc->control_pdapi->pdapi_aborted = 1; 1001165220Srrs asoc->control_pdapi = NULL; 1002163953Srrs SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 1003237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1004172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1005172090Srrs SCTP_TCB_UNLOCK(stcb); 1006172090Srrs SCTP_SOCKET_LOCK(so, 1); 1007172090Srrs SCTP_TCB_LOCK(stcb); 1008172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1009172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1010172090Srrs /* assoc was freed while we were unlocked */ 1011172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1012172090Srrs return; 1013172090Srrs } 1014172090Srrs#endif 1015163996Srrs sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 1016237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1017172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1018172090Srrs#endif 1019163953Srrs } 1020252585Stuexen#ifdef INVARIANTS 1021163953Srrs if (!TAILQ_EMPTY(&asoc->send_queue) || 1022163953Srrs !TAILQ_EMPTY(&asoc->sent_queue) || 1023217760Stuexen !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 1024252585Stuexen panic("Queues are not empty when handling SHUTDOWN-ACK"); 1025163953Srrs } 1026252585Stuexen#endif 1027163953Srrs /* stop the timer */ 1028171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9); 1029163953Srrs /* send SHUTDOWN-COMPLETE */ 1030204141Stuexen sctp_send_shutdown_complete(stcb, net, 0); 1031163953Srrs /* notify upper layer protocol */ 1032163953Srrs if (stcb->sctp_socket) { 1033163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1034163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 1035229774Stuexen stcb->sctp_socket->so_snd.sb_cc = 0; 1036163953Srrs } 1037230379Stuexen sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1038163953Srrs } 1039163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 1040163953Srrs /* free the TCB but first save off the ep */ 1041237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1042172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1043172090Srrs SCTP_TCB_UNLOCK(stcb); 1044172090Srrs SCTP_SOCKET_LOCK(so, 1); 1045172090Srrs SCTP_TCB_LOCK(stcb); 1046172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1047172090Srrs#endif 1048171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 1049171440Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_10); 1050237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1051172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1052172090Srrs#endif 1053163953Srrs} 1054163953Srrs 1055163953Srrs/* 1056163953Srrs * Skip past the param header and then we will find the chunk that caused the 1057163953Srrs * problem. There are two possiblities ASCONF or FWD-TSN other than that and 1058163953Srrs * our peer must be broken. 1059163953Srrs */ 1060163953Srrsstatic void 1061163953Srrssctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr, 1062163953Srrs struct sctp_nets *net) 1063163953Srrs{ 1064163953Srrs struct sctp_chunkhdr *chk; 1065163953Srrs 1066163953Srrs chk = (struct sctp_chunkhdr *)((caddr_t)phdr + sizeof(*phdr)); 1067163953Srrs switch (chk->chunk_type) { 1068163953Srrs case SCTP_ASCONF_ACK: 1069163953Srrs case SCTP_ASCONF: 1070163953Srrs sctp_asconf_cleanup(stcb, net); 1071163953Srrs break; 1072163953Srrs case SCTP_FORWARD_CUM_TSN: 1073270357Stuexen stcb->asoc.prsctp_supported = 0; 1074163953Srrs break; 1075163953Srrs default: 1076169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1077169420Srrs "Peer does not support chunk type %d(%x)??\n", 1078169420Srrs chk->chunk_type, (uint32_t) chk->chunk_type); 1079163953Srrs break; 1080163953Srrs } 1081163953Srrs} 1082163953Srrs 1083163953Srrs/* 1084163953Srrs * Skip past the param header and then we will find the param that caused the 1085163953Srrs * problem. There are a number of param's in a ASCONF OR the prsctp param 1086163953Srrs * these will turn of specific features. 1087270362Stuexen * XXX: Is this the right thing to do? 1088163953Srrs */ 1089163953Srrsstatic void 1090163953Srrssctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr) 1091163953Srrs{ 1092163953Srrs struct sctp_paramhdr *pbad; 1093163953Srrs 1094163953Srrs pbad = phdr + 1; 1095163953Srrs switch (ntohs(pbad->param_type)) { 1096163953Srrs /* pr-sctp draft */ 1097163953Srrs case SCTP_PRSCTP_SUPPORTED: 1098270357Stuexen stcb->asoc.prsctp_supported = 0; 1099163953Srrs break; 1100163953Srrs case SCTP_SUPPORTED_CHUNK_EXT: 1101163953Srrs break; 1102163953Srrs /* draft-ietf-tsvwg-addip-sctp */ 1103185694Srrs case SCTP_HAS_NAT_SUPPORT: 1104185694Srrs stcb->asoc.peer_supports_nat = 0; 1105185694Srrs break; 1106163953Srrs case SCTP_ADD_IP_ADDRESS: 1107163953Srrs case SCTP_DEL_IP_ADDRESS: 1108163953Srrs case SCTP_SET_PRIM_ADDR: 1109270362Stuexen stcb->asoc.asconf_supported = 0; 1110163953Srrs break; 1111163953Srrs case SCTP_SUCCESS_REPORT: 1112163953Srrs case SCTP_ERROR_CAUSE_IND: 1113169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support success? or error cause?\n"); 1114169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1115169420Srrs "Turning off ASCONF to this strange peer\n"); 1116270362Stuexen stcb->asoc.asconf_supported = 0; 1117163953Srrs break; 1118163953Srrs default: 1119169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1120169420Srrs "Peer does not support param type %d(%x)??\n", 1121169420Srrs pbad->param_type, (uint32_t) pbad->param_type); 1122163953Srrs break; 1123163953Srrs } 1124163953Srrs} 1125163953Srrs 1126163953Srrsstatic int 1127163953Srrssctp_handle_error(struct sctp_chunkhdr *ch, 1128163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 1129163953Srrs{ 1130163953Srrs int chklen; 1131163953Srrs struct sctp_paramhdr *phdr; 1132235418Stuexen uint16_t error, error_type; 1133163953Srrs uint16_t error_len; 1134163953Srrs struct sctp_association *asoc; 1135163953Srrs int adjust; 1136163953Srrs 1137237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1138172090Srrs struct socket *so; 1139172090Srrs 1140172090Srrs#endif 1141172090Srrs 1142163953Srrs /* parse through all of the errors and process */ 1143163953Srrs asoc = &stcb->asoc; 1144163953Srrs phdr = (struct sctp_paramhdr *)((caddr_t)ch + 1145163953Srrs sizeof(struct sctp_chunkhdr)); 1146163953Srrs chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr); 1147235418Stuexen error = 0; 1148163953Srrs while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) { 1149163953Srrs /* Process an Error Cause */ 1150163953Srrs error_type = ntohs(phdr->param_type); 1151163953Srrs error_len = ntohs(phdr->param_length); 1152163953Srrs if ((error_len > chklen) || (error_len == 0)) { 1153163953Srrs /* invalid param length for this param */ 1154169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Bogus length in error param- chunk left:%d errorlen:%d\n", 1155169420Srrs chklen, error_len); 1156163953Srrs return (0); 1157163953Srrs } 1158235418Stuexen if (error == 0) { 1159235418Stuexen /* report the first error cause */ 1160235418Stuexen error = error_type; 1161235418Stuexen } 1162163953Srrs switch (error_type) { 1163163953Srrs case SCTP_CAUSE_INVALID_STREAM: 1164163953Srrs case SCTP_CAUSE_MISSING_PARAM: 1165163953Srrs case SCTP_CAUSE_INVALID_PARAM: 1166163953Srrs case SCTP_CAUSE_NO_USER_DATA: 1167169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Software error we got a %d back? We have a bug :/ (or do they?)\n", 1168169420Srrs error_type); 1169163953Srrs break; 1170185694Srrs case SCTP_CAUSE_NAT_COLLIDING_STATE: 1171185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 1172185694Srrs ch->chunk_flags); 1173185694Srrs if (sctp_handle_nat_colliding_state(stcb)) { 1174185694Srrs return (0); 1175185694Srrs } 1176185694Srrs break; 1177185694Srrs case SCTP_CAUSE_NAT_MISSING_STATE: 1178185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 1179185694Srrs ch->chunk_flags); 1180185694Srrs if (sctp_handle_nat_missing_state(stcb, net)) { 1181185694Srrs return (0); 1182185694Srrs } 1183185694Srrs break; 1184163953Srrs case SCTP_CAUSE_STALE_COOKIE: 1185163953Srrs /* 1186163953Srrs * We only act if we have echoed a cookie and are 1187163953Srrs * waiting. 1188163953Srrs */ 1189163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 1190163953Srrs int *p; 1191163953Srrs 1192163953Srrs p = (int *)((caddr_t)phdr + sizeof(*phdr)); 1193163953Srrs /* Save the time doubled */ 1194163953Srrs asoc->cookie_preserve_req = ntohl(*p) << 1; 1195163953Srrs asoc->stale_cookie_count++; 1196163953Srrs if (asoc->stale_cookie_count > 1197163953Srrs asoc->max_init_times) { 1198235403Stuexen sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); 1199163953Srrs /* now free the asoc */ 1200237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1201172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1202172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1203172090Srrs SCTP_TCB_UNLOCK(stcb); 1204172090Srrs SCTP_SOCKET_LOCK(so, 1); 1205172090Srrs SCTP_TCB_LOCK(stcb); 1206172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1207172090Srrs#endif 1208171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 1209171943Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_11); 1210237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1211172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1212172090Srrs#endif 1213163953Srrs return (-1); 1214163953Srrs } 1215163953Srrs /* blast back to INIT state */ 1216185694Srrs sctp_toss_old_cookies(stcb, &stcb->asoc); 1217163953Srrs asoc->state &= ~SCTP_STATE_COOKIE_ECHOED; 1218163953Srrs asoc->state |= SCTP_STATE_COOKIE_WAIT; 1219163953Srrs sctp_stop_all_cookie_timers(stcb); 1220172090Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 1221163953Srrs } 1222163953Srrs break; 1223163953Srrs case SCTP_CAUSE_UNRESOLVABLE_ADDR: 1224163953Srrs /* 1225163953Srrs * Nothing we can do here, we don't do hostname 1226163953Srrs * addresses so if the peer does not like my IPv6 1227163953Srrs * (or IPv4 for that matter) it does not matter. If 1228163953Srrs * they don't support that type of address, they can 1229163953Srrs * NOT possibly get that packet type... i.e. with no 1230163953Srrs * IPv6 you can't recieve a IPv6 packet. so we can 1231163953Srrs * safely ignore this one. If we ever added support 1232163953Srrs * for HOSTNAME Addresses, then we would need to do 1233163953Srrs * something here. 1234163953Srrs */ 1235163953Srrs break; 1236163953Srrs case SCTP_CAUSE_UNRECOG_CHUNK: 1237163953Srrs sctp_process_unrecog_chunk(stcb, phdr, net); 1238163953Srrs break; 1239163953Srrs case SCTP_CAUSE_UNRECOG_PARAM: 1240163953Srrs sctp_process_unrecog_param(stcb, phdr); 1241163953Srrs break; 1242163953Srrs case SCTP_CAUSE_COOKIE_IN_SHUTDOWN: 1243163953Srrs /* 1244163953Srrs * We ignore this since the timer will drive out a 1245163953Srrs * new cookie anyway and there timer will drive us 1246163953Srrs * to send a SHUTDOWN_COMPLETE. We can't send one 1247163953Srrs * here since we don't have their tag. 1248163953Srrs */ 1249163953Srrs break; 1250163953Srrs case SCTP_CAUSE_DELETING_LAST_ADDR: 1251163953Srrs case SCTP_CAUSE_RESOURCE_SHORTAGE: 1252163953Srrs case SCTP_CAUSE_DELETING_SRC_ADDR: 1253163953Srrs /* 1254163953Srrs * We should NOT get these here, but in a 1255166086Srrs * ASCONF-ACK. 1256163953Srrs */ 1257169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Peer sends ASCONF errors in a Operational Error?<%d>?\n", 1258169420Srrs error_type); 1259163953Srrs break; 1260163953Srrs case SCTP_CAUSE_OUT_OF_RESC: 1261163953Srrs /* 1262163953Srrs * And what, pray tell do we do with the fact that 1263163953Srrs * the peer is out of resources? Not really sure we 1264166086Srrs * could do anything but abort. I suspect this 1265163953Srrs * should have came WITH an abort instead of in a 1266163953Srrs * OP-ERROR. 1267163953Srrs */ 1268163953Srrs break; 1269163953Srrs default: 1270169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_handle_error: unknown error type = 0x%xh\n", 1271169420Srrs error_type); 1272163953Srrs break; 1273163953Srrs } 1274163953Srrs adjust = SCTP_SIZE32(error_len); 1275163953Srrs chklen -= adjust; 1276163953Srrs phdr = (struct sctp_paramhdr *)((caddr_t)phdr + adjust); 1277163953Srrs } 1278235418Stuexen sctp_ulp_notify(SCTP_NOTIFY_REMOTE_ERROR, stcb, error, ch, SCTP_SO_NOT_LOCKED); 1279163953Srrs return (0); 1280163953Srrs} 1281163953Srrs 1282163953Srrsstatic int 1283237715Stuexensctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, 1284237715Stuexen struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 1285237049Stuexen struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 1286237049Stuexen struct sctp_nets *net, int *abort_no_unlock, 1287237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 1288237049Stuexen uint32_t vrf_id) 1289163953Srrs{ 1290163953Srrs struct sctp_init_ack *init_ack; 1291163953Srrs struct mbuf *op_err; 1292163953Srrs 1293169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1294169420Srrs "sctp_handle_init_ack: handling INIT-ACK\n"); 1295169420Srrs 1296163953Srrs if (stcb == NULL) { 1297169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1298169420Srrs "sctp_handle_init_ack: TCB is null\n"); 1299163953Srrs return (-1); 1300163953Srrs } 1301163953Srrs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) { 1302163953Srrs /* Invalid length */ 1303267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1304237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1305237715Stuexen src, dst, sh, op_err, 1306237049Stuexen use_mflowid, mflowid, 1307237049Stuexen vrf_id, net->port); 1308168299Srrs *abort_no_unlock = 1; 1309163953Srrs return (-1); 1310163953Srrs } 1311163953Srrs init_ack = &cp->init; 1312163953Srrs /* validate parameters */ 1313163953Srrs if (init_ack->initiate_tag == 0) { 1314163953Srrs /* protocol error... send an abort */ 1315267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1316237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1317237715Stuexen src, dst, sh, op_err, 1318237049Stuexen use_mflowid, mflowid, 1319237049Stuexen vrf_id, net->port); 1320168299Srrs *abort_no_unlock = 1; 1321163953Srrs return (-1); 1322163953Srrs } 1323163953Srrs if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) { 1324163953Srrs /* protocol error... send an abort */ 1325267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1326237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1327237715Stuexen src, dst, sh, op_err, 1328237049Stuexen use_mflowid, mflowid, 1329237049Stuexen vrf_id, net->port); 1330168299Srrs *abort_no_unlock = 1; 1331163953Srrs return (-1); 1332163953Srrs } 1333163953Srrs if (init_ack->num_inbound_streams == 0) { 1334163953Srrs /* protocol error... send an abort */ 1335267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1336237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1337237715Stuexen src, dst, sh, op_err, 1338237049Stuexen use_mflowid, mflowid, 1339237049Stuexen vrf_id, net->port); 1340168299Srrs *abort_no_unlock = 1; 1341163953Srrs return (-1); 1342163953Srrs } 1343163953Srrs if (init_ack->num_outbound_streams == 0) { 1344163953Srrs /* protocol error... send an abort */ 1345267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1346237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1347237715Stuexen src, dst, sh, op_err, 1348237049Stuexen use_mflowid, mflowid, 1349237049Stuexen vrf_id, net->port); 1350168299Srrs *abort_no_unlock = 1; 1351163953Srrs return (-1); 1352163953Srrs } 1353163953Srrs /* process according to association state... */ 1354171943Srrs switch (stcb->asoc.state & SCTP_STATE_MASK) { 1355163953Srrs case SCTP_STATE_COOKIE_WAIT: 1356163953Srrs /* this is the expected state for this chunk */ 1357163953Srrs /* process the INIT-ACK parameters */ 1358163953Srrs if (stcb->asoc.primary_destination->dest_state & 1359163953Srrs SCTP_ADDR_UNCONFIRMED) { 1360163953Srrs /* 1361163953Srrs * The primary is where we sent the INIT, we can 1362163953Srrs * always consider it confirmed when the INIT-ACK is 1363163953Srrs * returned. Do this before we load addresses 1364163953Srrs * though. 1365163953Srrs */ 1366163953Srrs stcb->asoc.primary_destination->dest_state &= 1367163953Srrs ~SCTP_ADDR_UNCONFIRMED; 1368163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 1369172090Srrs stcb, 0, (void *)stcb->asoc.primary_destination, SCTP_SO_NOT_LOCKED); 1370163953Srrs } 1371237715Stuexen if (sctp_process_init_ack(m, iphlen, offset, src, dst, sh, cp, stcb, 1372237049Stuexen net, abort_no_unlock, 1373237049Stuexen use_mflowid, mflowid, 1374237049Stuexen vrf_id) < 0) { 1375163953Srrs /* error in parsing parameters */ 1376163953Srrs return (-1); 1377163953Srrs } 1378163953Srrs /* update our state */ 1379169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to COOKIE-ECHOED state\n"); 1380171943Srrs SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_ECHOED); 1381163953Srrs 1382163953Srrs /* reset the RTO calc */ 1383179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1384171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1385171943Srrs stcb->asoc.overall_error_count, 1386171943Srrs 0, 1387171943Srrs SCTP_FROM_SCTP_INPUT, 1388171943Srrs __LINE__); 1389171943Srrs } 1390163953Srrs stcb->asoc.overall_error_count = 0; 1391169378Srrs (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 1392163953Srrs /* 1393163953Srrs * collapse the init timer back in case of a exponential 1394165220Srrs * backoff 1395163953Srrs */ 1396163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep, 1397163953Srrs stcb, net); 1398163953Srrs /* 1399163953Srrs * the send at the end of the inbound data processing will 1400163953Srrs * cause the cookie to be sent 1401163953Srrs */ 1402163953Srrs break; 1403163953Srrs case SCTP_STATE_SHUTDOWN_SENT: 1404163953Srrs /* incorrect state... discard */ 1405163953Srrs break; 1406163953Srrs case SCTP_STATE_COOKIE_ECHOED: 1407163953Srrs /* incorrect state... discard */ 1408163953Srrs break; 1409163953Srrs case SCTP_STATE_OPEN: 1410163953Srrs /* incorrect state... discard */ 1411163953Srrs break; 1412163953Srrs case SCTP_STATE_EMPTY: 1413163953Srrs case SCTP_STATE_INUSE: 1414163953Srrs default: 1415163953Srrs /* incorrect state... discard */ 1416163953Srrs return (-1); 1417163953Srrs break; 1418163953Srrs } 1419169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Leaving handle-init-ack end\n"); 1420163953Srrs return (0); 1421163953Srrs} 1422163953Srrs 1423185694Srrsstatic struct sctp_tcb * 1424185694Srrssctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 1425237715Stuexen struct sockaddr *src, struct sockaddr *dst, 1426185694Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 1427185694Srrs struct sctp_inpcb *inp, struct sctp_nets **netp, 1428185694Srrs struct sockaddr *init_src, int *notification, 1429185694Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1430237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 1431185694Srrs uint32_t vrf_id, uint16_t port); 1432163953Srrs 1433185694Srrs 1434163953Srrs/* 1435163953Srrs * handle a state cookie for an existing association m: input packet mbuf 1436163953Srrs * chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a 1437163953Srrs * "split" mbuf and the cookie signature does not exist offset: offset into 1438163953Srrs * mbuf to the cookie-echo chunk 1439163953Srrs */ 1440163953Srrsstatic struct sctp_tcb * 1441163953Srrssctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, 1442237715Stuexen struct sockaddr *src, struct sockaddr *dst, 1443163953Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 1444185694Srrs struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp, 1445228653Stuexen struct sockaddr *init_src, int *notification, 1446237049Stuexen int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1447237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 1448237049Stuexen uint32_t vrf_id, uint16_t port) 1449163953Srrs{ 1450163953Srrs struct sctp_association *asoc; 1451163953Srrs struct sctp_init_chunk *init_cp, init_buf; 1452163953Srrs struct sctp_init_ack_chunk *initack_cp, initack_buf; 1453185694Srrs struct sctp_nets *net; 1454185694Srrs struct mbuf *op_err; 1455165220Srrs int init_offset, initack_offset, i; 1456163953Srrs int retval; 1457164205Srrs int spec_flag = 0; 1458170140Srrs uint32_t how_indx; 1459163953Srrs 1460270363Stuexen#if defined(SCTP_DETAILED_STR_STATS) 1461270363Stuexen int j; 1462270363Stuexen 1463270363Stuexen#endif 1464270363Stuexen 1465185694Srrs net = *netp; 1466163953Srrs /* I know that the TCB is non-NULL from the caller */ 1467163953Srrs asoc = &stcb->asoc; 1468166675Srrs for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); how_indx++) { 1469166023Srrs if (asoc->cookie_how[how_indx] == 0) 1470166023Srrs break; 1471166023Srrs } 1472166023Srrs if (how_indx < sizeof(asoc->cookie_how)) { 1473166023Srrs asoc->cookie_how[how_indx] = 1; 1474166023Srrs } 1475163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 1476163953Srrs /* SHUTDOWN came in after sending INIT-ACK */ 1477163953Srrs sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination); 1478267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, ""); 1479237715Stuexen sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, 1480237049Stuexen use_mflowid, mflowid, 1481179157Srrs vrf_id, net->port); 1482166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1483166023Srrs asoc->cookie_how[how_indx] = 2; 1484163953Srrs return (NULL); 1485163953Srrs } 1486163953Srrs /* 1487163953Srrs * find and validate the INIT chunk in the cookie (peer's info) the 1488163953Srrs * INIT should start after the cookie-echo header struct (chunk 1489163953Srrs * header, state cookie header struct) 1490163953Srrs */ 1491163953Srrs init_offset = offset += sizeof(struct sctp_cookie_echo_chunk); 1492163953Srrs 1493163953Srrs init_cp = (struct sctp_init_chunk *) 1494163953Srrs sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 1495163953Srrs (uint8_t *) & init_buf); 1496163953Srrs if (init_cp == NULL) { 1497163953Srrs /* could not pull a INIT chunk in cookie */ 1498163953Srrs return (NULL); 1499163953Srrs } 1500163953Srrs if (init_cp->ch.chunk_type != SCTP_INITIATION) { 1501163953Srrs return (NULL); 1502163953Srrs } 1503163953Srrs /* 1504163953Srrs * find and validate the INIT-ACK chunk in the cookie (my info) the 1505163953Srrs * INIT-ACK follows the INIT chunk 1506163953Srrs */ 1507228907Stuexen initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 1508163953Srrs initack_cp = (struct sctp_init_ack_chunk *) 1509163953Srrs sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 1510163953Srrs (uint8_t *) & initack_buf); 1511163953Srrs if (initack_cp == NULL) { 1512163953Srrs /* could not pull INIT-ACK chunk in cookie */ 1513163953Srrs return (NULL); 1514163953Srrs } 1515163953Srrs if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 1516163953Srrs return (NULL); 1517163953Srrs } 1518163953Srrs if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1519163953Srrs (ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag)) { 1520163953Srrs /* 1521163953Srrs * case D in Section 5.2.4 Table 2: MMAA process accordingly 1522163953Srrs * to get into the OPEN state 1523163953Srrs */ 1524166023Srrs if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 1525172091Srrs /*- 1526172091Srrs * Opps, this means that we somehow generated two vtag's 1527172091Srrs * the same. I.e. we did: 1528172091Srrs * Us Peer 1529172091Srrs * <---INIT(tag=a)------ 1530172091Srrs * ----INIT-ACK(tag=t)--> 1531172091Srrs * ----INIT(tag=t)------> *1 1532172091Srrs * <---INIT-ACK(tag=a)--- 1533172091Srrs * <----CE(tag=t)------------- *2 1534172091Srrs * 1535172091Srrs * At point *1 we should be generating a different 1536172091Srrs * tag t'. Which means we would throw away the CE and send 1537172091Srrs * ours instead. Basically this is case C (throw away side). 1538172091Srrs */ 1539172091Srrs if (how_indx < sizeof(asoc->cookie_how)) 1540172091Srrs asoc->cookie_how[how_indx] = 17; 1541172091Srrs return (NULL); 1542172091Srrs 1543166023Srrs } 1544267720Stuexen switch (SCTP_GET_STATE(asoc)) { 1545163953Srrs case SCTP_STATE_COOKIE_WAIT: 1546166023Srrs case SCTP_STATE_COOKIE_ECHOED: 1547163953Srrs /* 1548169352Srrs * INIT was sent but got a COOKIE_ECHO with the 1549166023Srrs * correct tags... just accept it...but we must 1550166023Srrs * process the init so that we can make sure we have 1551166023Srrs * the right seq no's. 1552163953Srrs */ 1553163953Srrs /* First we must process the INIT !! */ 1554228653Stuexen retval = sctp_process_init(init_cp, stcb); 1555163953Srrs if (retval < 0) { 1556166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1557166023Srrs asoc->cookie_how[how_indx] = 3; 1558163953Srrs return (NULL); 1559163953Srrs } 1560163953Srrs /* we have already processed the INIT so no problem */ 1561163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, 1562171440Srrs net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_12); 1563171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_13); 1564163953Srrs /* update current state */ 1565166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 1566166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 1567166675Srrs else 1568166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1569171943Srrs 1570171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1571163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1572163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1573163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1574163953Srrs } 1575166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1576165220Srrs sctp_stop_all_cookie_timers(stcb); 1577163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1578163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1579163953Srrs (inp->sctp_socket->so_qlimit == 0) 1580163953Srrs ) { 1581237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1582172090Srrs struct socket *so; 1583172090Srrs 1584172090Srrs#endif 1585163953Srrs /* 1586163953Srrs * Here is where collision would go if we 1587163953Srrs * did a connect() and instead got a 1588163953Srrs * init/init-ack/cookie done before the 1589163953Srrs * init-ack came back.. 1590163953Srrs */ 1591163953Srrs stcb->sctp_ep->sctp_flags |= 1592163953Srrs SCTP_PCB_FLAGS_CONNECTED; 1593237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1594172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1595172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1596172090Srrs SCTP_TCB_UNLOCK(stcb); 1597172090Srrs SCTP_SOCKET_LOCK(so, 1); 1598172090Srrs SCTP_TCB_LOCK(stcb); 1599172090Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1600172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1601172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1602172090Srrs return (NULL); 1603172090Srrs } 1604172090Srrs#endif 1605172090Srrs soisconnected(stcb->sctp_socket); 1606237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1607172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1608172090Srrs#endif 1609163953Srrs } 1610163953Srrs /* notify upper layer */ 1611163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 1612163953Srrs /* 1613163953Srrs * since we did not send a HB make sure we don't 1614163953Srrs * double things 1615163953Srrs */ 1616163953Srrs net->hb_responded = 1; 1617170642Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, 1618218186Srrs &cookie->time_entered, 1619218186Srrs sctp_align_unsafe_makecopy, 1620219397Srrs SCTP_RTT_FROM_NON_DATA); 1621163953Srrs 1622163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 1623163953Srrs (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) { 1624163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 1625163953Srrs inp, stcb, NULL); 1626163953Srrs } 1627163953Srrs break; 1628163953Srrs default: 1629163953Srrs /* 1630163953Srrs * we're in the OPEN state (or beyond), so peer must 1631163953Srrs * have simply lost the COOKIE-ACK 1632163953Srrs */ 1633163953Srrs break; 1634267720Stuexen } /* end switch */ 1635165220Srrs sctp_stop_all_cookie_timers(stcb); 1636163953Srrs /* 1637163953Srrs * We ignore the return code here.. not sure if we should 1638163953Srrs * somehow abort.. but we do have an existing asoc. This 1639163953Srrs * really should not fail. 1640163953Srrs */ 1641228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1642163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1643237715Stuexen initack_offset, src, dst, init_src)) { 1644166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1645166023Srrs asoc->cookie_how[how_indx] = 4; 1646163953Srrs return (NULL); 1647163953Srrs } 1648163953Srrs /* respond with a COOKIE-ACK */ 1649165220Srrs sctp_toss_old_cookies(stcb, asoc); 1650163953Srrs sctp_send_cookie_ack(stcb); 1651166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1652166023Srrs asoc->cookie_how[how_indx] = 5; 1653163953Srrs return (stcb); 1654169352Srrs } 1655163953Srrs if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 1656163953Srrs ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag && 1657163953Srrs cookie->tie_tag_my_vtag == 0 && 1658163953Srrs cookie->tie_tag_peer_vtag == 0) { 1659163953Srrs /* 1660163953Srrs * case C in Section 5.2.4 Table 2: XMOO silently discard 1661163953Srrs */ 1662166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1663166023Srrs asoc->cookie_how[how_indx] = 6; 1664163953Srrs return (NULL); 1665163953Srrs } 1666185694Srrs /* 1667185694Srrs * If nat support, and the below and stcb is established, send back 1668185694Srrs * a ABORT(colliding state) if we are established. 1669185694Srrs */ 1670185694Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) && 1671185694Srrs (asoc->peer_supports_nat) && 1672185694Srrs ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1673185694Srrs ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 1674185694Srrs (asoc->peer_vtag == 0)))) { 1675163953Srrs /* 1676185694Srrs * Special case - Peer's support nat. We may have two init's 1677185694Srrs * that we gave out the same tag on since one was not 1678185694Srrs * established.. i.e. we get INIT from host-1 behind the nat 1679185694Srrs * and we respond tag-a, we get a INIT from host-2 behind 1680185694Srrs * the nat and we get tag-a again. Then we bring up host-1 1681185694Srrs * (or 2's) assoc, Then comes the cookie from hsot-2 (or 1). 1682185694Srrs * Now we have colliding state. We must send an abort here 1683185694Srrs * with colliding state indication. 1684185694Srrs */ 1685267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_NAT_COLLIDING_STATE, ""); 1686237715Stuexen sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, 1687237049Stuexen use_mflowid, mflowid, 1688237049Stuexen vrf_id, port); 1689185694Srrs return (NULL); 1690185694Srrs } 1691185694Srrs if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1692185694Srrs ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 1693185694Srrs (asoc->peer_vtag == 0))) { 1694185694Srrs /* 1695163953Srrs * case B in Section 5.2.4 Table 2: MXAA or MOAA my info 1696163953Srrs * should be ok, re-accept peer info 1697163953Srrs */ 1698166023Srrs if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 1699166023Srrs /* 1700166023Srrs * Extension of case C. If we hit this, then the 1701166023Srrs * random number generator returned the same vtag 1702166023Srrs * when we first sent our INIT-ACK and when we later 1703166023Srrs * sent our INIT. The side with the seq numbers that 1704166023Srrs * are different will be the one that normnally 1705166023Srrs * would have hit case C. This in effect "extends" 1706166023Srrs * our vtags in this collision case to be 64 bits. 1707166023Srrs * The same collision could occur aka you get both 1708166023Srrs * vtag and seq number the same twice in a row.. but 1709166023Srrs * is much less likely. If it did happen then we 1710166023Srrs * would proceed through and bring up the assoc.. we 1711166023Srrs * may end up with the wrong stream setup however.. 1712166023Srrs * which would be bad.. but there is no way to 1713166023Srrs * tell.. until we send on a stream that does not 1714166023Srrs * exist :-) 1715166023Srrs */ 1716166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1717166023Srrs asoc->cookie_how[how_indx] = 7; 1718166023Srrs 1719166023Srrs return (NULL); 1720166023Srrs } 1721166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1722166023Srrs asoc->cookie_how[how_indx] = 8; 1723171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_14); 1724163953Srrs sctp_stop_all_cookie_timers(stcb); 1725163953Srrs /* 1726163953Srrs * since we did not send a HB make sure we don't double 1727163953Srrs * things 1728163953Srrs */ 1729163953Srrs net->hb_responded = 1; 1730163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 1731163953Srrs sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 1732163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, 1733163953Srrs NULL); 1734163953Srrs } 1735163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 1736164205Srrs asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 1737164205Srrs 1738164205Srrs if (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) { 1739164205Srrs /* 1740164205Srrs * Ok the peer probably discarded our data (if we 1741164205Srrs * echoed a cookie+data). So anything on the 1742164205Srrs * sent_queue should be marked for retransmit, we 1743164205Srrs * may not get something to kick us so it COULD 1744164205Srrs * still take a timeout to move these.. but it can't 1745164205Srrs * hurt to mark them. 1746164205Srrs */ 1747164205Srrs struct sctp_tmit_chunk *chk; 1748163953Srrs 1749164205Srrs TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 1750164205Srrs if (chk->sent < SCTP_DATAGRAM_RESEND) { 1751164205Srrs chk->sent = SCTP_DATAGRAM_RESEND; 1752171440Srrs sctp_flight_size_decrease(chk); 1753171440Srrs sctp_total_flight_decrease(stcb, chk); 1754168124Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1755164205Srrs spec_flag++; 1756164205Srrs } 1757164205Srrs } 1758164205Srrs 1759164205Srrs } 1760163953Srrs /* process the INIT info (peer's info) */ 1761228653Stuexen retval = sctp_process_init(init_cp, stcb); 1762163953Srrs if (retval < 0) { 1763166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1764166023Srrs asoc->cookie_how[how_indx] = 9; 1765163953Srrs return (NULL); 1766163953Srrs } 1767228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1768163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1769237715Stuexen initack_offset, src, dst, init_src)) { 1770166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1771166023Srrs asoc->cookie_how[how_indx] = 10; 1772163953Srrs return (NULL); 1773163953Srrs } 1774163953Srrs if ((asoc->state & SCTP_STATE_COOKIE_WAIT) || 1775163953Srrs (asoc->state & SCTP_STATE_COOKIE_ECHOED)) { 1776163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 1777163953Srrs 1778163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1779163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1780163953Srrs (inp->sctp_socket->so_qlimit == 0)) { 1781237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1782172090Srrs struct socket *so; 1783172090Srrs 1784172090Srrs#endif 1785163953Srrs stcb->sctp_ep->sctp_flags |= 1786163953Srrs SCTP_PCB_FLAGS_CONNECTED; 1787237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1788172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1789172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1790172090Srrs SCTP_TCB_UNLOCK(stcb); 1791172090Srrs SCTP_SOCKET_LOCK(so, 1); 1792172090Srrs SCTP_TCB_LOCK(stcb); 1793172090Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1794172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1795172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1796172090Srrs return (NULL); 1797172090Srrs } 1798172090Srrs#endif 1799172090Srrs soisconnected(stcb->sctp_socket); 1800237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1801172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1802172090Srrs#endif 1803163953Srrs } 1804166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 1805166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 1806166675Srrs else 1807166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1808166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1809166675Srrs } else if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 1810166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_restartestab); 1811166675Srrs } else { 1812166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1813163953Srrs } 1814171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1815163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1816163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1817163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1818163953Srrs } 1819163953Srrs sctp_stop_all_cookie_timers(stcb); 1820165220Srrs sctp_toss_old_cookies(stcb, asoc); 1821163953Srrs sctp_send_cookie_ack(stcb); 1822164205Srrs if (spec_flag) { 1823164205Srrs /* 1824164205Srrs * only if we have retrans set do we do this. What 1825164205Srrs * this call does is get only the COOKIE-ACK out and 1826164205Srrs * then when we return the normal call to 1827164205Srrs * sctp_chunk_output will get the retrans out behind 1828164205Srrs * this. 1829164205Srrs */ 1830172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_COOKIE_ACK, SCTP_SO_NOT_LOCKED); 1831164205Srrs } 1832166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1833166023Srrs asoc->cookie_how[how_indx] = 11; 1834166023Srrs 1835163953Srrs return (stcb); 1836163953Srrs } 1837163953Srrs if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 1838163953Srrs ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) && 1839163953Srrs cookie->tie_tag_my_vtag == asoc->my_vtag_nonce && 1840163953Srrs cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce && 1841163953Srrs cookie->tie_tag_peer_vtag != 0) { 1842163953Srrs struct sctpasochead *head; 1843163953Srrs 1844252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1845252585Stuexen struct socket *so; 1846252585Stuexen 1847252585Stuexen#endif 1848252585Stuexen 1849185694Srrs if (asoc->peer_supports_nat) { 1850185694Srrs /* 1851252585Stuexen * This is a gross gross hack. Just call the 1852185694Srrs * cookie_new code since we are allowing a duplicate 1853185694Srrs * association. I hope this works... 1854185694Srrs */ 1855237715Stuexen return (sctp_process_cookie_new(m, iphlen, offset, src, dst, 1856237715Stuexen sh, cookie, cookie_len, 1857185694Srrs inp, netp, init_src, notification, 1858185694Srrs auth_skipped, auth_offset, auth_len, 1859237049Stuexen use_mflowid, mflowid, 1860185694Srrs vrf_id, port)); 1861185694Srrs } 1862163953Srrs /* 1863163953Srrs * case A in Section 5.2.4 Table 2: XXMM (peer restarted) 1864163953Srrs */ 1865165220Srrs /* temp code */ 1866166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1867166023Srrs asoc->cookie_how[how_indx] = 12; 1868171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_15); 1869171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); 1870165647Srrs 1871163953Srrs /* notify upper layer */ 1872163953Srrs *notification = SCTP_NOTIFY_ASSOC_RESTART; 1873165220Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1874166675Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN) && 1875166675Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 1876166675Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 1877166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1878166675Srrs } 1879166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 1880166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_restartestab); 1881166675Srrs } else if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { 1882166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_collisionestab); 1883166675Srrs } 1884165647Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1885171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1886165647Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1887165647Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1888165647Srrs 1889165647Srrs } else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) { 1890165647Srrs /* move to OPEN state, if not in SHUTDOWN_SENT */ 1891171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1892165647Srrs } 1893165647Srrs asoc->pre_open_streams = 1894165647Srrs ntohs(initack_cp->init.num_outbound_streams); 1895165647Srrs asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 1896165647Srrs asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 1897179157Srrs asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 1898165647Srrs 1899165647Srrs asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 1900165647Srrs 1901165647Srrs asoc->str_reset_seq_in = asoc->init_seq_number; 1902165647Srrs 1903165647Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 1904170138Srrs if (asoc->mapping_array) { 1905165647Srrs memset(asoc->mapping_array, 0, 1906165647Srrs asoc->mapping_array_size); 1907170138Srrs } 1908205627Srrs if (asoc->nr_mapping_array) { 1909185694Srrs memset(asoc->nr_mapping_array, 0, 1910206137Stuexen asoc->mapping_array_size); 1911185694Srrs } 1912165220Srrs SCTP_TCB_UNLOCK(stcb); 1913252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1914252585Stuexen so = SCTP_INP_SO(stcb->sctp_ep); 1915252585Stuexen SCTP_SOCKET_LOCK(so, 1); 1916252585Stuexen#endif 1917165220Srrs SCTP_INP_INFO_WLOCK(); 1918165220Srrs SCTP_INP_WLOCK(stcb->sctp_ep); 1919165220Srrs SCTP_TCB_LOCK(stcb); 1920165220Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1921163953Srrs /* send up all the data */ 1922164205Srrs SCTP_TCB_SEND_LOCK(stcb); 1923165220Srrs 1924252585Stuexen sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED); 1925165220Srrs for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 1926243157Stuexen stcb->asoc.strmout[i].chunks_on_queues = 0; 1927270363Stuexen#if defined(SCTP_DETAILED_STR_STATS) 1928270363Stuexen for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) { 1929270363Stuexen asoc->strmout[i].abandoned_sent[j] = 0; 1930270363Stuexen asoc->strmout[i].abandoned_unsent[j] = 0; 1931270363Stuexen } 1932270363Stuexen#else 1933270363Stuexen asoc->strmout[i].abandoned_sent[0] = 0; 1934270363Stuexen asoc->strmout[i].abandoned_unsent[0] = 0; 1935270363Stuexen#endif 1936165220Srrs stcb->asoc.strmout[i].stream_no = i; 1937242627Stuexen stcb->asoc.strmout[i].next_sequence_send = 0; 1938165220Srrs stcb->asoc.strmout[i].last_msg_incomplete = 0; 1939165220Srrs } 1940163953Srrs /* process the INIT-ACK info (my info) */ 1941163953Srrs asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 1942163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 1943163953Srrs 1944163953Srrs /* pull from vtag hash */ 1945163953Srrs LIST_REMOVE(stcb, sctp_asocs); 1946163953Srrs /* re-insert to new vtag position */ 1947179783Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, 1948179783Srrs SCTP_BASE_INFO(hashasocmark))]; 1949163953Srrs /* 1950163953Srrs * put it in the bucket in the vtag hash of assoc's for the 1951163953Srrs * system 1952163953Srrs */ 1953163953Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 1954163953Srrs 1955164205Srrs SCTP_TCB_SEND_UNLOCK(stcb); 1956165220Srrs SCTP_INP_WUNLOCK(stcb->sctp_ep); 1957165220Srrs SCTP_INP_INFO_WUNLOCK(); 1958252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1959252585Stuexen SCTP_SOCKET_UNLOCK(so, 1); 1960252585Stuexen#endif 1961252585Stuexen asoc->total_flight = 0; 1962252585Stuexen asoc->total_flight_count = 0; 1963252585Stuexen /* process the INIT info (peer's info) */ 1964228653Stuexen retval = sctp_process_init(init_cp, stcb); 1965163953Srrs if (retval < 0) { 1966166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1967166023Srrs asoc->cookie_how[how_indx] = 13; 1968166023Srrs 1969163953Srrs return (NULL); 1970163953Srrs } 1971163953Srrs /* 1972163953Srrs * since we did not send a HB make sure we don't double 1973163953Srrs * things 1974163953Srrs */ 1975163953Srrs net->hb_responded = 1; 1976163953Srrs 1977228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1978163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1979237715Stuexen initack_offset, src, dst, init_src)) { 1980166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1981166023Srrs asoc->cookie_how[how_indx] = 14; 1982166023Srrs 1983163953Srrs return (NULL); 1984163953Srrs } 1985163953Srrs /* respond with a COOKIE-ACK */ 1986163953Srrs sctp_stop_all_cookie_timers(stcb); 1987165220Srrs sctp_toss_old_cookies(stcb, asoc); 1988163953Srrs sctp_send_cookie_ack(stcb); 1989166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1990166023Srrs asoc->cookie_how[how_indx] = 15; 1991163953Srrs 1992163953Srrs return (stcb); 1993163953Srrs } 1994166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1995166023Srrs asoc->cookie_how[how_indx] = 16; 1996163953Srrs /* all other cases... */ 1997163953Srrs return (NULL); 1998163953Srrs} 1999163953Srrs 2000166086Srrs 2001163953Srrs/* 2002163953Srrs * handle a state cookie for a new association m: input packet mbuf chain-- 2003163953Srrs * assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a "split" mbuf 2004163953Srrs * and the cookie signature does not exist offset: offset into mbuf to the 2005163953Srrs * cookie-echo chunk length: length of the cookie chunk to: where the init 2006163953Srrs * was from returns a new TCB 2007163953Srrs */ 2008237049Stuexenstatic struct sctp_tcb * 2009163953Srrssctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 2010237715Stuexen struct sockaddr *src, struct sockaddr *dst, 2011163953Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 2012163953Srrs struct sctp_inpcb *inp, struct sctp_nets **netp, 2013163953Srrs struct sockaddr *init_src, int *notification, 2014169352Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 2015237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 2016179157Srrs uint32_t vrf_id, uint16_t port) 2017163953Srrs{ 2018163953Srrs struct sctp_tcb *stcb; 2019163953Srrs struct sctp_init_chunk *init_cp, init_buf; 2020163953Srrs struct sctp_init_ack_chunk *initack_cp, initack_buf; 2021271746Stuexen union sctp_sockstore store; 2022163953Srrs struct sctp_association *asoc; 2023163953Srrs int init_offset, initack_offset, initack_limit; 2024163953Srrs int retval; 2025163953Srrs int error = 0; 2026166675Srrs uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE]; 2027163953Srrs 2028237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2029172090Srrs struct socket *so; 2030172090Srrs 2031172090Srrs so = SCTP_INP_SO(inp); 2032172090Srrs#endif 2033172090Srrs 2034163953Srrs /* 2035163953Srrs * find and validate the INIT chunk in the cookie (peer's info) the 2036163953Srrs * INIT should start after the cookie-echo header struct (chunk 2037163953Srrs * header, state cookie header struct) 2038163953Srrs */ 2039163953Srrs init_offset = offset + sizeof(struct sctp_cookie_echo_chunk); 2040163953Srrs init_cp = (struct sctp_init_chunk *) 2041163953Srrs sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 2042163953Srrs (uint8_t *) & init_buf); 2043163953Srrs if (init_cp == NULL) { 2044163953Srrs /* could not pull a INIT chunk in cookie */ 2045169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 2046169420Srrs "process_cookie_new: could not pull INIT chunk hdr\n"); 2047163953Srrs return (NULL); 2048163953Srrs } 2049163953Srrs if (init_cp->ch.chunk_type != SCTP_INITIATION) { 2050169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "HUH? process_cookie_new: could not find INIT chunk!\n"); 2051163953Srrs return (NULL); 2052163953Srrs } 2053228907Stuexen initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 2054163953Srrs /* 2055163953Srrs * find and validate the INIT-ACK chunk in the cookie (my info) the 2056163953Srrs * INIT-ACK follows the INIT chunk 2057163953Srrs */ 2058163953Srrs initack_cp = (struct sctp_init_ack_chunk *) 2059163953Srrs sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 2060163953Srrs (uint8_t *) & initack_buf); 2061163953Srrs if (initack_cp == NULL) { 2062163953Srrs /* could not pull INIT-ACK chunk in cookie */ 2063169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: could not pull INIT-ACK chunk hdr\n"); 2064163953Srrs return (NULL); 2065163953Srrs } 2066163953Srrs if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 2067163953Srrs return (NULL); 2068163953Srrs } 2069163953Srrs /* 2070163953Srrs * NOTE: We can't use the INIT_ACK's chk_length to determine the 2071163953Srrs * "initack_limit" value. This is because the chk_length field 2072163953Srrs * includes the length of the cookie, but the cookie is omitted when 2073163953Srrs * the INIT and INIT_ACK are tacked onto the cookie... 2074163953Srrs */ 2075163953Srrs initack_limit = offset + cookie_len; 2076163953Srrs 2077163953Srrs /* 2078163953Srrs * now that we know the INIT/INIT-ACK are in place, create a new TCB 2079163953Srrs * and popluate 2080163953Srrs */ 2081171531Srrs 2082171531Srrs /* 2083171531Srrs * Here we do a trick, we set in NULL for the proc/thread argument. 2084171531Srrs * We do this since in effect we only use the p argument when the 2085171531Srrs * socket is unbound and we must do an implicit bind. Since we are 2086171531Srrs * getting a cookie, we cannot be unbound. 2087171531Srrs */ 2088206137Stuexen stcb = sctp_aloc_assoc(inp, init_src, &error, 2089171531Srrs ntohl(initack_cp->init.initiate_tag), vrf_id, 2090171531Srrs (struct thread *)NULL 2091171531Srrs ); 2092163953Srrs if (stcb == NULL) { 2093163953Srrs struct mbuf *op_err; 2094163953Srrs 2095163953Srrs /* memory problem? */ 2096169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 2097169420Srrs "process_cookie_new: no room for another TCB!\n"); 2098267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 2099163953Srrs sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 2100237715Stuexen src, dst, sh, op_err, 2101237049Stuexen use_mflowid, mflowid, 2102237049Stuexen vrf_id, port); 2103163953Srrs return (NULL); 2104163953Srrs } 2105163953Srrs /* get the correct sctp_nets */ 2106169420Srrs if (netp) 2107169420Srrs *netp = sctp_findnet(stcb, init_src); 2108169420Srrs 2109163953Srrs asoc = &stcb->asoc; 2110163953Srrs /* get scope variables out of cookie */ 2111246595Stuexen asoc->scope.ipv4_local_scope = cookie->ipv4_scope; 2112246595Stuexen asoc->scope.site_scope = cookie->site_scope; 2113246595Stuexen asoc->scope.local_scope = cookie->local_scope; 2114246595Stuexen asoc->scope.loopback_scope = cookie->loopback_scope; 2115163953Srrs 2116246595Stuexen if ((asoc->scope.ipv4_addr_legal != cookie->ipv4_addr_legal) || 2117246595Stuexen (asoc->scope.ipv6_addr_legal != cookie->ipv6_addr_legal)) { 2118163953Srrs struct mbuf *op_err; 2119163953Srrs 2120163953Srrs /* 2121163953Srrs * Houston we have a problem. The EP changed while the 2122163953Srrs * cookie was in flight. Only recourse is to abort the 2123163953Srrs * association. 2124163953Srrs */ 2125170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2126267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 2127163953Srrs sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 2128237715Stuexen src, dst, sh, op_err, 2129237049Stuexen use_mflowid, mflowid, 2130237049Stuexen vrf_id, port); 2131237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2132172090Srrs SCTP_TCB_UNLOCK(stcb); 2133172090Srrs SCTP_SOCKET_LOCK(so, 1); 2134172090Srrs SCTP_TCB_LOCK(stcb); 2135172090Srrs#endif 2136171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 2137171440Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); 2138237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2139172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2140172090Srrs#endif 2141172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2142163953Srrs return (NULL); 2143163953Srrs } 2144163953Srrs /* process the INIT-ACK info (my info) */ 2145185694Srrs asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 2146163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 2147163953Srrs asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 2148163953Srrs asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 2149163953Srrs asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 2150179157Srrs asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 2151163953Srrs asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 2152163953Srrs asoc->str_reset_seq_in = asoc->init_seq_number; 2153163953Srrs 2154163953Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 2155163953Srrs 2156163953Srrs /* process the INIT info (peer's info) */ 2157169420Srrs if (netp) 2158228653Stuexen retval = sctp_process_init(init_cp, stcb); 2159169420Srrs else 2160169420Srrs retval = 0; 2161163953Srrs if (retval < 0) { 2162170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2163237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2164172090Srrs SCTP_TCB_UNLOCK(stcb); 2165172090Srrs SCTP_SOCKET_LOCK(so, 1); 2166172090Srrs SCTP_TCB_LOCK(stcb); 2167172090Srrs#endif 2168171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); 2169237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2170172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2171172090Srrs#endif 2172172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2173163953Srrs return (NULL); 2174163953Srrs } 2175163953Srrs /* load all addresses */ 2176228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 2177237715Stuexen init_offset + sizeof(struct sctp_init_chunk), initack_offset, 2178237715Stuexen src, dst, init_src)) { 2179170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2180237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2181172090Srrs SCTP_TCB_UNLOCK(stcb); 2182172090Srrs SCTP_SOCKET_LOCK(so, 1); 2183172090Srrs SCTP_TCB_LOCK(stcb); 2184172090Srrs#endif 2185171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_17); 2186237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2187172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2188172090Srrs#endif 2189172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2190163953Srrs return (NULL); 2191163953Srrs } 2192163953Srrs /* 2193163953Srrs * verify any preceding AUTH chunk that was skipped 2194163953Srrs */ 2195163953Srrs /* pull the local authentication parameters from the cookie/init-ack */ 2196163953Srrs sctp_auth_get_cookie_params(stcb, m, 2197163953Srrs initack_offset + sizeof(struct sctp_init_ack_chunk), 2198163953Srrs initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk))); 2199163953Srrs if (auth_skipped) { 2200163953Srrs struct sctp_auth_chunk *auth; 2201163953Srrs 2202163953Srrs auth = (struct sctp_auth_chunk *) 2203166675Srrs sctp_m_getptr(m, auth_offset, auth_len, auth_chunk_buf); 2204169420Srrs if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, auth_offset)) { 2205163953Srrs /* auth HMAC failed, dump the assoc and packet */ 2206169420Srrs SCTPDBG(SCTP_DEBUG_AUTH1, 2207169420Srrs "COOKIE-ECHO: AUTH failed\n"); 2208171440Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2209237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2210172090Srrs SCTP_TCB_UNLOCK(stcb); 2211172090Srrs SCTP_SOCKET_LOCK(so, 1); 2212172090Srrs SCTP_TCB_LOCK(stcb); 2213172090Srrs#endif 2214171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_18); 2215237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2216172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2217172090Srrs#endif 2218172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2219163953Srrs return (NULL); 2220163953Srrs } else { 2221163953Srrs /* remaining chunks checked... good to go */ 2222163953Srrs stcb->asoc.authenticated = 1; 2223163953Srrs } 2224163953Srrs } 2225163953Srrs /* update current state */ 2226169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 2227171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 2228163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 2229163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 2230163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 2231163953Srrs } 2232165220Srrs sctp_stop_all_cookie_timers(stcb); 2233163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_passiveestab); 2234163953Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 2235163953Srrs 2236163953Srrs /* 2237163953Srrs * if we're doing ASCONFs, check to see if we have any new local 2238163953Srrs * addresses that need to get added to the peer (eg. addresses 2239163953Srrs * changed while cookie echo in flight). This needs to be done 2240163953Srrs * after we go to the OPEN state to do the correct asconf 2241163953Srrs * processing. else, make sure we have the correct addresses in our 2242163953Srrs * lists 2243163953Srrs */ 2244163953Srrs 2245163953Srrs /* warning, we re-use sin, sin6, sa_store here! */ 2246163953Srrs /* pull in local_address (our "from" address) */ 2247221249Stuexen switch (cookie->laddr_type) { 2248221249Stuexen#ifdef INET 2249221249Stuexen case SCTP_IPV4_ADDRESS: 2250163953Srrs /* source addr is IPv4 */ 2251271746Stuexen memset(&store.sin, 0, sizeof(struct sockaddr_in)); 2252271746Stuexen store.sin.sin_family = AF_INET; 2253271746Stuexen store.sin.sin_len = sizeof(struct sockaddr_in); 2254271746Stuexen store.sin.sin_addr.s_addr = cookie->laddress[0]; 2255221249Stuexen break; 2256221249Stuexen#endif 2257221249Stuexen#ifdef INET6 2258221249Stuexen case SCTP_IPV6_ADDRESS: 2259163953Srrs /* source addr is IPv6 */ 2260271746Stuexen memset(&store.sin6, 0, sizeof(struct sockaddr_in6)); 2261271746Stuexen store.sin6.sin6_family = AF_INET6; 2262271746Stuexen store.sin6.sin6_len = sizeof(struct sockaddr_in6); 2263271746Stuexen store.sin6.sin6_scope_id = cookie->scope_id; 2264271746Stuexen memcpy(&store.sin6.sin6_addr, cookie->laddress, sizeof(struct in6_addr)); 2265221249Stuexen break; 2266221249Stuexen#endif 2267221249Stuexen default: 2268170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2269237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2270172090Srrs SCTP_TCB_UNLOCK(stcb); 2271172090Srrs SCTP_SOCKET_LOCK(so, 1); 2272172090Srrs SCTP_TCB_LOCK(stcb); 2273172090Srrs#endif 2274171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_19); 2275237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2276172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2277172090Srrs#endif 2278172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2279163953Srrs return (NULL); 2280163953Srrs } 2281163953Srrs 2282163953Srrs /* set up to notify upper layer */ 2283163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 2284163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2285163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 2286163953Srrs (inp->sctp_socket->so_qlimit == 0)) { 2287163953Srrs /* 2288163953Srrs * This is an endpoint that called connect() how it got a 2289163953Srrs * cookie that is NEW is a bit of a mystery. It must be that 2290163953Srrs * the INIT was sent, but before it got there.. a complete 2291163953Srrs * INIT/INIT-ACK/COOKIE arrived. But of course then it 2292163953Srrs * should have went to the other code.. not here.. oh well.. 2293163953Srrs * a bit of protection is worth having.. 2294163953Srrs */ 2295163953Srrs stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 2296237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2297172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2298172090Srrs SCTP_TCB_UNLOCK(stcb); 2299172090Srrs SCTP_SOCKET_LOCK(so, 1); 2300172090Srrs SCTP_TCB_LOCK(stcb); 2301172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2302172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 2303172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2304172090Srrs return (NULL); 2305172090Srrs } 2306172090Srrs#endif 2307172090Srrs soisconnected(stcb->sctp_socket); 2308237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2309172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2310172090Srrs#endif 2311163953Srrs } else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 2312163953Srrs (inp->sctp_socket->so_qlimit)) { 2313163953Srrs /* 2314163953Srrs * We don't want to do anything with this one. Since it is 2315163953Srrs * the listening guy. The timer will get started for 2316163953Srrs * accepted connections in the caller. 2317163953Srrs */ 2318163953Srrs ; 2319163953Srrs } 2320163953Srrs /* since we did not send a HB make sure we don't double things */ 2321169420Srrs if ((netp) && (*netp)) 2322169420Srrs (*netp)->hb_responded = 1; 2323163953Srrs 2324163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 2325163953Srrs sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 2326163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL); 2327163953Srrs } 2328165220Srrs /* calculate the RTT */ 2329171440Srrs (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 2330170642Srrs if ((netp) && (*netp)) { 2331169420Srrs (*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp, 2332218186Srrs &cookie->time_entered, sctp_align_unsafe_makecopy, 2333219397Srrs SCTP_RTT_FROM_NON_DATA); 2334170642Srrs } 2335172190Srrs /* respond with a COOKIE-ACK */ 2336163953Srrs sctp_send_cookie_ack(stcb); 2337172190Srrs 2338172190Srrs /* 2339172190Srrs * check the address lists for any ASCONFs that need to be sent 2340172190Srrs * AFTER the cookie-ack is sent 2341172190Srrs */ 2342172190Srrs sctp_check_address_list(stcb, m, 2343172190Srrs initack_offset + sizeof(struct sctp_init_ack_chunk), 2344172190Srrs initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)), 2345271746Stuexen &store.sa, cookie->local_scope, cookie->site_scope, 2346172190Srrs cookie->ipv4_scope, cookie->loopback_scope); 2347172190Srrs 2348172190Srrs 2349163953Srrs return (stcb); 2350163953Srrs} 2351163953Srrs 2352185694Srrs/* 2353185694Srrs * CODE LIKE THIS NEEDS TO RUN IF the peer supports the NAT extension, i.e 2354185694Srrs * we NEED to make sure we are not already using the vtag. If so we 2355185694Srrs * need to send back an ABORT-TRY-AGAIN-WITH-NEW-TAG No middle box bit! 2356185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag, 2357185694Srrs SCTP_BASE_INFO(hashasocmark))]; 2358185694Srrs LIST_FOREACH(stcb, head, sctp_asocs) { 2359185694Srrs if ((stcb->asoc.my_vtag == tag) && (stcb->rport == rport) && (inp == stcb->sctp_ep)) { 2360185694Srrs -- SEND ABORT - TRY AGAIN -- 2361185694Srrs } 2362185694Srrs } 2363185694Srrs*/ 2364163953Srrs 2365163953Srrs/* 2366163953Srrs * handles a COOKIE-ECHO message stcb: modified to either a new or left as 2367163953Srrs * existing (non-NULL) TCB 2368163953Srrs */ 2369163953Srrsstatic struct mbuf * 2370163953Srrssctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, 2371237715Stuexen struct sockaddr *src, struct sockaddr *dst, 2372163953Srrs struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp, 2373163953Srrs struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp, 2374169352Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 2375237049Stuexen struct sctp_tcb **locked_tcb, 2376237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 2377237049Stuexen uint32_t vrf_id, uint16_t port) 2378163953Srrs{ 2379163953Srrs struct sctp_state_cookie *cookie; 2380163953Srrs struct sctp_tcb *l_stcb = *stcb; 2381163953Srrs struct sctp_inpcb *l_inp; 2382163953Srrs struct sockaddr *to; 2383163953Srrs struct sctp_pcb *ep; 2384163953Srrs struct mbuf *m_sig; 2385163953Srrs uint8_t calc_sig[SCTP_SIGNATURE_SIZE], tmp_sig[SCTP_SIGNATURE_SIZE]; 2386163953Srrs uint8_t *sig; 2387163953Srrs uint8_t cookie_ok = 0; 2388237541Stuexen unsigned int sig_offset, cookie_offset; 2389163953Srrs unsigned int cookie_len; 2390163953Srrs struct timeval now; 2391163953Srrs struct timeval time_expires; 2392163953Srrs int notification = 0; 2393163953Srrs struct sctp_nets *netl; 2394163953Srrs int had_a_existing_tcb = 0; 2395216887Stuexen int send_int_conf = 0; 2396163953Srrs 2397221249Stuexen#ifdef INET 2398221249Stuexen struct sockaddr_in sin; 2399221249Stuexen 2400221249Stuexen#endif 2401221249Stuexen#ifdef INET6 2402221249Stuexen struct sockaddr_in6 sin6; 2403221249Stuexen 2404221249Stuexen#endif 2405221249Stuexen 2406169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2407169420Srrs "sctp_handle_cookie: handling COOKIE-ECHO\n"); 2408163953Srrs 2409163953Srrs if (inp_p == NULL) { 2410163953Srrs return (NULL); 2411163953Srrs } 2412163953Srrs cookie = &cp->cookie; 2413163953Srrs cookie_offset = offset + sizeof(struct sctp_chunkhdr); 2414163953Srrs cookie_len = ntohs(cp->ch.chunk_length); 2415163953Srrs 2416163953Srrs if ((cookie->peerport != sh->src_port) && 2417163953Srrs (cookie->myport != sh->dest_port) && 2418163953Srrs (cookie->my_vtag != sh->v_tag)) { 2419163953Srrs /* 2420163953Srrs * invalid ports or bad tag. Note that we always leave the 2421163953Srrs * v_tag in the header in network order and when we stored 2422163953Srrs * it in the my_vtag slot we also left it in network order. 2423169352Srrs * This maintains the match even though it may be in the 2424163953Srrs * opposite byte order of the machine :-> 2425163953Srrs */ 2426163953Srrs return (NULL); 2427163953Srrs } 2428237541Stuexen if (cookie_len < sizeof(struct sctp_cookie_echo_chunk) + 2429163953Srrs sizeof(struct sctp_init_chunk) + 2430163953Srrs sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) { 2431237541Stuexen /* cookie too small */ 2432163953Srrs return (NULL); 2433163953Srrs } 2434163953Srrs /* 2435163953Srrs * split off the signature into its own mbuf (since it should not be 2436163953Srrs * calculated in the sctp_hmac_m() call). 2437163953Srrs */ 2438163953Srrs sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE; 2439243882Sglebius m_sig = m_split(m, sig_offset, M_NOWAIT); 2440163953Srrs if (m_sig == NULL) { 2441163953Srrs /* out of memory or ?? */ 2442163953Srrs return (NULL); 2443163953Srrs } 2444178202Srrs#ifdef SCTP_MBUF_LOGGING 2445179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 2446178202Srrs struct mbuf *mat; 2447178202Srrs 2448234461Stuexen for (mat = m_sig; mat; mat = SCTP_BUF_NEXT(mat)) { 2449178202Srrs if (SCTP_BUF_IS_EXTENDED(mat)) { 2450178202Srrs sctp_log_mb(mat, SCTP_MBUF_SPLIT); 2451178202Srrs } 2452178202Srrs } 2453178202Srrs } 2454178202Srrs#endif 2455178202Srrs 2456163953Srrs /* 2457163953Srrs * compute the signature/digest for the cookie 2458163953Srrs */ 2459163953Srrs ep = &(*inp_p)->sctp_ep; 2460163953Srrs l_inp = *inp_p; 2461163953Srrs if (l_stcb) { 2462163953Srrs SCTP_TCB_UNLOCK(l_stcb); 2463163953Srrs } 2464163953Srrs SCTP_INP_RLOCK(l_inp); 2465163953Srrs if (l_stcb) { 2466163953Srrs SCTP_TCB_LOCK(l_stcb); 2467163953Srrs } 2468163953Srrs /* which cookie is it? */ 2469163953Srrs if ((cookie->time_entered.tv_sec < (long)ep->time_of_secret_change) && 2470163953Srrs (ep->current_secret_number != ep->last_secret_number)) { 2471163953Srrs /* it's the old cookie */ 2472169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2473163953Srrs (uint8_t *) ep->secret_key[(int)ep->last_secret_number], 2474170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2475163953Srrs } else { 2476163953Srrs /* it's the current cookie */ 2477169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2478163953Srrs (uint8_t *) ep->secret_key[(int)ep->current_secret_number], 2479170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2480163953Srrs } 2481163953Srrs /* get the signature */ 2482163953Srrs SCTP_INP_RUNLOCK(l_inp); 2483163953Srrs sig = (uint8_t *) sctp_m_getptr(m_sig, 0, SCTP_SIGNATURE_SIZE, (uint8_t *) & tmp_sig); 2484163953Srrs if (sig == NULL) { 2485163953Srrs /* couldn't find signature */ 2486164085Srrs sctp_m_freem(m_sig); 2487163953Srrs return (NULL); 2488163953Srrs } 2489163953Srrs /* compare the received digest with the computed digest */ 2490163953Srrs if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) != 0) { 2491163953Srrs /* try the old cookie? */ 2492163953Srrs if ((cookie->time_entered.tv_sec == (long)ep->time_of_secret_change) && 2493163953Srrs (ep->current_secret_number != ep->last_secret_number)) { 2494163953Srrs /* compute digest with old */ 2495169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2496163953Srrs (uint8_t *) ep->secret_key[(int)ep->last_secret_number], 2497170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2498163953Srrs /* compare */ 2499163953Srrs if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) == 0) 2500163953Srrs cookie_ok = 1; 2501163953Srrs } 2502163953Srrs } else { 2503163953Srrs cookie_ok = 1; 2504163953Srrs } 2505163953Srrs 2506163953Srrs /* 2507163953Srrs * Now before we continue we must reconstruct our mbuf so that 2508163953Srrs * normal processing of any other chunks will work. 2509163953Srrs */ 2510163953Srrs { 2511163953Srrs struct mbuf *m_at; 2512163953Srrs 2513163953Srrs m_at = m; 2514165647Srrs while (SCTP_BUF_NEXT(m_at) != NULL) { 2515165647Srrs m_at = SCTP_BUF_NEXT(m_at); 2516163953Srrs } 2517165647Srrs SCTP_BUF_NEXT(m_at) = m_sig; 2518163953Srrs } 2519163953Srrs 2520163953Srrs if (cookie_ok == 0) { 2521169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "handle_cookie_echo: cookie signature validation failed!\n"); 2522169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2523169420Srrs "offset = %u, cookie_offset = %u, sig_offset = %u\n", 2524169420Srrs (uint32_t) offset, cookie_offset, sig_offset); 2525163953Srrs return (NULL); 2526163953Srrs } 2527163953Srrs /* 2528163953Srrs * check the cookie timestamps to be sure it's not stale 2529163953Srrs */ 2530169378Srrs (void)SCTP_GETTIME_TIMEVAL(&now); 2531163953Srrs /* Expire time is in Ticks, so we convert to seconds */ 2532169655Srrs time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life); 2533163953Srrs time_expires.tv_usec = cookie->time_entered.tv_usec; 2534180387Srrs /* 2535180387Srrs * TODO sctp_constants.h needs alternative time macros when _KERNEL 2536180387Srrs * is undefined. 2537180387Srrs */ 2538163953Srrs if (timevalcmp(&now, &time_expires, >)) { 2539163953Srrs /* cookie is stale! */ 2540163953Srrs struct mbuf *op_err; 2541163953Srrs struct sctp_stale_cookie_msg *scm; 2542163953Srrs uint32_t tim; 2543163953Srrs 2544163953Srrs op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg), 2545243882Sglebius 0, M_NOWAIT, 1, MT_DATA); 2546163953Srrs if (op_err == NULL) { 2547163953Srrs /* FOOBAR */ 2548163953Srrs return (NULL); 2549163953Srrs } 2550163953Srrs /* Set the len */ 2551165647Srrs SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg); 2552163953Srrs scm = mtod(op_err, struct sctp_stale_cookie_msg *); 2553163953Srrs scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE); 2554163953Srrs scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) + 2555163953Srrs (sizeof(uint32_t)))); 2556163953Srrs /* seconds to usec */ 2557163953Srrs tim = (now.tv_sec - time_expires.tv_sec) * 1000000; 2558163953Srrs /* add in usec */ 2559163953Srrs if (tim == 0) 2560163953Srrs tim = now.tv_usec - cookie->time_entered.tv_usec; 2561163953Srrs scm->time_usec = htonl(tim); 2562237715Stuexen sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, 2563237049Stuexen use_mflowid, mflowid, 2564179157Srrs vrf_id, port); 2565163953Srrs return (NULL); 2566163953Srrs } 2567163953Srrs /* 2568163953Srrs * Now we must see with the lookup address if we have an existing 2569163953Srrs * asoc. This will only happen if we were in the COOKIE-WAIT state 2570163953Srrs * and a INIT collided with us and somewhere the peer sent the 2571163953Srrs * cookie on another address besides the single address our assoc 2572163953Srrs * had for him. In this case we will have one of the tie-tags set at 2573163953Srrs * least AND the address field in the cookie can be used to look it 2574163953Srrs * up. 2575163953Srrs */ 2576163953Srrs to = NULL; 2577221249Stuexen switch (cookie->addr_type) { 2578221249Stuexen#ifdef INET6 2579221249Stuexen case SCTP_IPV6_ADDRESS: 2580163953Srrs memset(&sin6, 0, sizeof(sin6)); 2581163953Srrs sin6.sin6_family = AF_INET6; 2582163953Srrs sin6.sin6_len = sizeof(sin6); 2583163953Srrs sin6.sin6_port = sh->src_port; 2584163953Srrs sin6.sin6_scope_id = cookie->scope_id; 2585163953Srrs memcpy(&sin6.sin6_addr.s6_addr, cookie->address, 2586163953Srrs sizeof(sin6.sin6_addr.s6_addr)); 2587163953Srrs to = (struct sockaddr *)&sin6; 2588221249Stuexen break; 2589221249Stuexen#endif 2590221249Stuexen#ifdef INET 2591221249Stuexen case SCTP_IPV4_ADDRESS: 2592163953Srrs memset(&sin, 0, sizeof(sin)); 2593163953Srrs sin.sin_family = AF_INET; 2594163953Srrs sin.sin_len = sizeof(sin); 2595163953Srrs sin.sin_port = sh->src_port; 2596163953Srrs sin.sin_addr.s_addr = cookie->address[0]; 2597163953Srrs to = (struct sockaddr *)&sin; 2598221249Stuexen break; 2599221249Stuexen#endif 2600221249Stuexen default: 2601169420Srrs /* This should not happen */ 2602169420Srrs return (NULL); 2603163953Srrs } 2604163953Srrs if ((*stcb == NULL) && to) { 2605163953Srrs /* Yep, lets check */ 2606237715Stuexen *stcb = sctp_findassociation_ep_addr(inp_p, to, netp, dst, NULL); 2607163953Srrs if (*stcb == NULL) { 2608163953Srrs /* 2609163953Srrs * We should have only got back the same inp. If we 2610163953Srrs * got back a different ep we have a problem. The 2611163953Srrs * original findep got back l_inp and now 2612163953Srrs */ 2613163953Srrs if (l_inp != *inp_p) { 2614169420Srrs SCTP_PRINTF("Bad problem find_ep got a diff inp then special_locate?\n"); 2615163953Srrs } 2616165220Srrs } else { 2617165220Srrs if (*locked_tcb == NULL) { 2618165220Srrs /* 2619165220Srrs * In this case we found the assoc only 2620165220Srrs * after we locked the create lock. This 2621165220Srrs * means we are in a colliding case and we 2622165220Srrs * must make sure that we unlock the tcb if 2623165220Srrs * its one of the cases where we throw away 2624165220Srrs * the incoming packets. 2625165220Srrs */ 2626165220Srrs *locked_tcb = *stcb; 2627165220Srrs 2628165220Srrs /* 2629165220Srrs * We must also increment the inp ref count 2630165220Srrs * since the ref_count flags was set when we 2631165220Srrs * did not find the TCB, now we found it 2632165220Srrs * which reduces the refcount.. we must 2633165220Srrs * raise it back out to balance it all :-) 2634165220Srrs */ 2635165220Srrs SCTP_INP_INCR_REF((*stcb)->sctp_ep); 2636165220Srrs if ((*stcb)->sctp_ep != l_inp) { 2637169420Srrs SCTP_PRINTF("Huh? ep:%p diff then l_inp:%p?\n", 2638240148Stuexen (void *)(*stcb)->sctp_ep, (void *)l_inp); 2639165220Srrs } 2640165220Srrs } 2641163953Srrs } 2642163953Srrs } 2643188067Srrs if (to == NULL) { 2644169420Srrs return (NULL); 2645188067Srrs } 2646163953Srrs cookie_len -= SCTP_SIGNATURE_SIZE; 2647163953Srrs if (*stcb == NULL) { 2648163953Srrs /* this is the "normal" case... get a new TCB */ 2649237715Stuexen *stcb = sctp_process_cookie_new(m, iphlen, offset, src, dst, sh, 2650237715Stuexen cookie, cookie_len, *inp_p, 2651237715Stuexen netp, to, ¬ification, 2652237049Stuexen auth_skipped, auth_offset, auth_len, 2653237049Stuexen use_mflowid, mflowid, 2654237049Stuexen vrf_id, port); 2655163953Srrs } else { 2656163953Srrs /* this is abnormal... cookie-echo on existing TCB */ 2657163953Srrs had_a_existing_tcb = 1; 2658237715Stuexen *stcb = sctp_process_cookie_existing(m, iphlen, offset, 2659237715Stuexen src, dst, sh, 2660185694Srrs cookie, cookie_len, *inp_p, *stcb, netp, to, 2661237049Stuexen ¬ification, auth_skipped, auth_offset, auth_len, 2662237049Stuexen use_mflowid, mflowid, 2663237049Stuexen vrf_id, port); 2664163953Srrs } 2665163953Srrs 2666163953Srrs if (*stcb == NULL) { 2667163953Srrs /* still no TCB... must be bad cookie-echo */ 2668163953Srrs return (NULL); 2669163953Srrs } 2670237049Stuexen if ((*netp != NULL) && (use_mflowid != 0)) { 2671237049Stuexen (*netp)->flowid = mflowid; 2672218400Stuexen#ifdef INVARIANTS 2673218392Srrs (*netp)->flowidset = 1; 2674218400Stuexen#endif 2675218335Stuexen } 2676163953Srrs /* 2677163953Srrs * Ok, we built an association so confirm the address we sent the 2678163953Srrs * INIT-ACK to. 2679163953Srrs */ 2680163953Srrs netl = sctp_findnet(*stcb, to); 2681163953Srrs /* 2682163953Srrs * This code should in theory NOT run but 2683163953Srrs */ 2684163953Srrs if (netl == NULL) { 2685163953Srrs /* TSNH! Huh, why do I need to add this address here? */ 2686228907Stuexen if (sctp_add_remote_addr(*stcb, to, NULL, SCTP_DONOT_SETSCOPE, SCTP_IN_COOKIE_PROC)) { 2687228907Stuexen return (NULL); 2688228907Stuexen } 2689163953Srrs netl = sctp_findnet(*stcb, to); 2690163953Srrs } 2691163953Srrs if (netl) { 2692163953Srrs if (netl->dest_state & SCTP_ADDR_UNCONFIRMED) { 2693163953Srrs netl->dest_state &= ~SCTP_ADDR_UNCONFIRMED; 2694169420Srrs (void)sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL, 2695163953Srrs netl); 2696216887Stuexen send_int_conf = 1; 2697163953Srrs } 2698163953Srrs } 2699224641Stuexen sctp_start_net_timers(*stcb); 2700163953Srrs if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) { 2701163953Srrs if (!had_a_existing_tcb || 2702163953Srrs (((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) { 2703163953Srrs /* 2704163953Srrs * If we have a NEW cookie or the connect never 2705163953Srrs * reached the connected state during collision we 2706163953Srrs * must do the TCP accept thing. 2707163953Srrs */ 2708163953Srrs struct socket *so, *oso; 2709163953Srrs struct sctp_inpcb *inp; 2710163953Srrs 2711163953Srrs if (notification == SCTP_NOTIFY_ASSOC_RESTART) { 2712163953Srrs /* 2713163953Srrs * For a restart we will keep the same 2714163953Srrs * socket, no need to do anything. I THINK!! 2715163953Srrs */ 2716228653Stuexen sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2717216887Stuexen if (send_int_conf) { 2718216887Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2719216887Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2720216887Stuexen } 2721163953Srrs return (m); 2722163953Srrs } 2723163953Srrs oso = (*inp_p)->sctp_socket; 2724171858Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2725163953Srrs SCTP_TCB_UNLOCK((*stcb)); 2726218757Sbz CURVNET_SET(oso->so_vnet); 2727166086Srrs so = sonewconn(oso, 0 2728163953Srrs ); 2729218757Sbz CURVNET_RESTORE(); 2730163953Srrs SCTP_TCB_LOCK((*stcb)); 2731171858Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2732171858Srrs 2733163953Srrs if (so == NULL) { 2734163953Srrs struct mbuf *op_err; 2735163953Srrs 2736237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2737172090Srrs struct socket *pcb_so; 2738172090Srrs 2739172090Srrs#endif 2740163953Srrs /* Too many sockets */ 2741169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n"); 2742267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 2743163953Srrs sctp_abort_association(*inp_p, NULL, m, iphlen, 2744237715Stuexen src, dst, sh, op_err, 2745237049Stuexen use_mflowid, mflowid, 2746237049Stuexen vrf_id, port); 2747237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2748172090Srrs pcb_so = SCTP_INP_SO(*inp_p); 2749172090Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2750172090Srrs SCTP_TCB_UNLOCK((*stcb)); 2751172090Srrs SCTP_SOCKET_LOCK(pcb_so, 1); 2752172090Srrs SCTP_TCB_LOCK((*stcb)); 2753172090Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2754172090Srrs#endif 2755171943Srrs (void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_20); 2756237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2757172090Srrs SCTP_SOCKET_UNLOCK(pcb_so, 1); 2758172090Srrs#endif 2759163953Srrs return (NULL); 2760163953Srrs } 2761163953Srrs inp = (struct sctp_inpcb *)so->so_pcb; 2762166086Srrs SCTP_INP_INCR_REF(inp); 2763166086Srrs /* 2764166086Srrs * We add the unbound flag here so that if we get an 2765166086Srrs * soabort() before we get the move_pcb done, we 2766166086Srrs * will properly cleanup. 2767166086Srrs */ 2768163953Srrs inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | 2769163953Srrs SCTP_PCB_FLAGS_CONNECTED | 2770163953Srrs SCTP_PCB_FLAGS_IN_TCPPOOL | 2771166086Srrs SCTP_PCB_FLAGS_UNBOUND | 2772163953Srrs (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) | 2773163953Srrs SCTP_PCB_FLAGS_DONT_WAKE); 2774163953Srrs inp->sctp_features = (*inp_p)->sctp_features; 2775172091Srrs inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features; 2776163953Srrs inp->sctp_socket = so; 2777163953Srrs inp->sctp_frag_point = (*inp_p)->sctp_frag_point; 2778211944Stuexen inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off; 2779270356Stuexen inp->ecn_supported = (*inp_p)->ecn_supported; 2780270357Stuexen inp->prsctp_supported = (*inp_p)->prsctp_supported; 2781270362Stuexen inp->auth_supported = (*inp_p)->auth_supported; 2782270362Stuexen inp->asconf_supported = (*inp_p)->asconf_supported; 2783270361Stuexen inp->reconfig_supported = (*inp_p)->reconfig_supported; 2784270359Stuexen inp->nrsack_supported = (*inp_p)->nrsack_supported; 2785270360Stuexen inp->pktdrop_supported = (*inp_p)->pktdrop_supported; 2786163953Srrs inp->partial_delivery_point = (*inp_p)->partial_delivery_point; 2787163953Srrs inp->sctp_context = (*inp_p)->sctp_context; 2788233660Srrs inp->local_strreset_support = (*inp_p)->local_strreset_support; 2789163953Srrs inp->inp_starting_point_for_iterator = NULL; 2790163953Srrs /* 2791163953Srrs * copy in the authentication parameters from the 2792163953Srrs * original endpoint 2793163953Srrs */ 2794163953Srrs if (inp->sctp_ep.local_hmacs) 2795163953Srrs sctp_free_hmaclist(inp->sctp_ep.local_hmacs); 2796163953Srrs inp->sctp_ep.local_hmacs = 2797163953Srrs sctp_copy_hmaclist((*inp_p)->sctp_ep.local_hmacs); 2798163953Srrs if (inp->sctp_ep.local_auth_chunks) 2799163953Srrs sctp_free_chunklist(inp->sctp_ep.local_auth_chunks); 2800163953Srrs inp->sctp_ep.local_auth_chunks = 2801163953Srrs sctp_copy_chunklist((*inp_p)->sctp_ep.local_auth_chunks); 2802163953Srrs 2803163953Srrs /* 2804163953Srrs * Now we must move it from one hash table to 2805163953Srrs * another and get the tcb in the right place. 2806163953Srrs */ 2807207924Srrs 2808207924Srrs /* 2809207924Srrs * This is where the one-2-one socket is put into 2810207924Srrs * the accept state waiting for the accept! 2811207924Srrs */ 2812207924Srrs if (*stcb) { 2813207924Srrs (*stcb)->asoc.state |= SCTP_STATE_IN_ACCEPT_QUEUE; 2814207924Srrs } 2815163953Srrs sctp_move_pcb_and_assoc(*inp_p, inp, *stcb); 2816170056Srrs 2817170056Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2818170056Srrs SCTP_TCB_UNLOCK((*stcb)); 2819170056Srrs 2820175845Srwatson sctp_pull_off_control_to_new_inp((*inp_p), inp, *stcb, 2821175845Srwatson 0); 2822170056Srrs SCTP_TCB_LOCK((*stcb)); 2823170056Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2824163953Srrs 2825170056Srrs 2826166086Srrs /* 2827166086Srrs * now we must check to see if we were aborted while 2828166086Srrs * the move was going on and the lock/unlock 2829166086Srrs * happened. 2830166086Srrs */ 2831166086Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 2832166086Srrs /* 2833166086Srrs * yep it was, we leave the assoc attached 2834166086Srrs * to the socket since the sctp_inpcb_free() 2835166086Srrs * call will send an abort for us. 2836166086Srrs */ 2837166086Srrs SCTP_INP_DECR_REF(inp); 2838166086Srrs return (NULL); 2839166086Srrs } 2840166086Srrs SCTP_INP_DECR_REF(inp); 2841163953Srrs /* Switch over to the new guy */ 2842163953Srrs *inp_p = inp; 2843172090Srrs sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2844216887Stuexen if (send_int_conf) { 2845216887Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2846216887Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2847216887Stuexen } 2848166086Srrs /* 2849166086Srrs * Pull it from the incomplete queue and wake the 2850166086Srrs * guy 2851166086Srrs */ 2852237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2853172090Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2854172090Srrs SCTP_TCB_UNLOCK((*stcb)); 2855172090Srrs SCTP_SOCKET_LOCK(so, 1); 2856172090Srrs#endif 2857166086Srrs soisconnected(so); 2858237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2859172118Srrs SCTP_TCB_LOCK((*stcb)); 2860172118Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2861172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2862172090Srrs#endif 2863163953Srrs return (m); 2864163953Srrs } 2865163953Srrs } 2866238454Stuexen if (notification) { 2867238454Stuexen sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2868163953Srrs } 2869238454Stuexen if (send_int_conf) { 2870238454Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2871238454Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2872238454Stuexen } 2873163953Srrs return (m); 2874163953Srrs} 2875163953Srrs 2876163953Srrsstatic void 2877228653Stuexensctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED, 2878163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 2879163953Srrs{ 2880163953Srrs /* cp must not be used, others call this without a c-ack :-) */ 2881163953Srrs struct sctp_association *asoc; 2882163953Srrs 2883169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2884169420Srrs "sctp_handle_cookie_ack: handling COOKIE-ACK\n"); 2885271746Stuexen if ((stcb == NULL) || (net == NULL)) { 2886163953Srrs return; 2887271746Stuexen } 2888163953Srrs asoc = &stcb->asoc; 2889163953Srrs 2890163953Srrs sctp_stop_all_cookie_timers(stcb); 2891163953Srrs /* process according to association state */ 2892163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 2893163953Srrs /* state change only needed when I am in right state */ 2894169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 2895171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 2896224641Stuexen sctp_start_net_timers(stcb); 2897163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 2898163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 2899163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 2900163953Srrs 2901163953Srrs } 2902163953Srrs /* update RTO */ 2903163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 2904163953Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 2905163953Srrs if (asoc->overall_error_count == 0) { 2906163953Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, 2907218186Srrs &asoc->time_entered, sctp_align_safe_nocopy, 2908219397Srrs SCTP_RTT_FROM_NON_DATA); 2909163953Srrs } 2910169378Srrs (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 2911172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2912163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2913163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 2914237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2915172090Srrs struct socket *so; 2916172090Srrs 2917172090Srrs#endif 2918163953Srrs stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 2919237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2920172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 2921172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2922172090Srrs SCTP_TCB_UNLOCK(stcb); 2923172090Srrs SCTP_SOCKET_LOCK(so, 1); 2924172090Srrs SCTP_TCB_LOCK(stcb); 2925172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2926218641Srrs#endif 2927218641Srrs if ((stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) == 0) { 2928218641Srrs soisconnected(stcb->sctp_socket); 2929172090Srrs } 2930237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2931172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2932172090Srrs#endif 2933163953Srrs } 2934163953Srrs /* 2935163953Srrs * since we did not send a HB make sure we don't double 2936163953Srrs * things 2937163953Srrs */ 2938163953Srrs net->hb_responded = 1; 2939163953Srrs 2940218641Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 2941218641Srrs /* 2942218641Srrs * We don't need to do the asconf thing, nor hb or 2943218641Srrs * autoclose if the socket is closed. 2944218641Srrs */ 2945218641Srrs goto closed_socket; 2946218641Srrs } 2947218641Srrs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, 2948218641Srrs stcb, net); 2949218641Srrs 2950218641Srrs 2951163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 2952163953Srrs sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTOCLOSE)) { 2953163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 2954163953Srrs stcb->sctp_ep, stcb, NULL); 2955163953Srrs } 2956163953Srrs /* 2957171572Srrs * send ASCONF if parameters are pending and ASCONFs are 2958171572Srrs * allowed (eg. addresses changed when init/cookie echo were 2959171572Srrs * in flight) 2960163953Srrs */ 2961163953Srrs if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) && 2962270362Stuexen (stcb->asoc.asconf_supported == 1) && 2963163953Srrs (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) { 2964171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 2965163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2966163953Srrs stcb->sctp_ep, stcb, 2967163953Srrs stcb->asoc.primary_destination); 2968171572Srrs#else 2969172190Srrs sctp_send_asconf(stcb, stcb->asoc.primary_destination, 2970172190Srrs SCTP_ADDR_NOT_LOCKED); 2971171572Srrs#endif 2972163953Srrs } 2973163953Srrs } 2974218641Srrsclosed_socket: 2975163953Srrs /* Toss the cookie if I can */ 2976163953Srrs sctp_toss_old_cookies(stcb, asoc); 2977163953Srrs if (!TAILQ_EMPTY(&asoc->sent_queue)) { 2978163953Srrs /* Restart the timer if we have pending data */ 2979163953Srrs struct sctp_tmit_chunk *chk; 2980163953Srrs 2981163953Srrs chk = TAILQ_FIRST(&asoc->sent_queue); 2982216822Stuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 2983163953Srrs } 2984163953Srrs} 2985163953Srrs 2986163953Srrsstatic void 2987163953Srrssctp_handle_ecn_echo(struct sctp_ecne_chunk *cp, 2988163953Srrs struct sctp_tcb *stcb) 2989163953Srrs{ 2990163953Srrs struct sctp_nets *net; 2991163953Srrs struct sctp_tmit_chunk *lchk; 2992218072Srrs struct sctp_ecne_chunk bkup; 2993228907Stuexen uint8_t override_bit; 2994218072Srrs uint32_t tsn, window_data_tsn; 2995218072Srrs int len; 2996218232Srrs unsigned int pkt_cnt; 2997163953Srrs 2998218072Srrs len = ntohs(cp->ch.chunk_length); 2999218072Srrs if ((len != sizeof(struct sctp_ecne_chunk)) && 3000218072Srrs (len != sizeof(struct old_sctp_ecne_chunk))) { 3001163953Srrs return; 3002163953Srrs } 3003218072Srrs if (len == sizeof(struct old_sctp_ecne_chunk)) { 3004218072Srrs /* Its the old format */ 3005218072Srrs memcpy(&bkup, cp, sizeof(struct old_sctp_ecne_chunk)); 3006218072Srrs bkup.num_pkts_since_cwr = htonl(1); 3007218072Srrs cp = &bkup; 3008218072Srrs } 3009163953Srrs SCTP_STAT_INCR(sctps_recvecne); 3010163953Srrs tsn = ntohl(cp->tsn); 3011218072Srrs pkt_cnt = ntohl(cp->num_pkts_since_cwr); 3012218072Srrs lchk = TAILQ_LAST(&stcb->asoc.send_queue, sctpchunk_listhead); 3013163953Srrs if (lchk == NULL) { 3014218129Srrs window_data_tsn = stcb->asoc.sending_seq - 1; 3015163953Srrs } else { 3016218129Srrs window_data_tsn = lchk->rec.data.TSN_seq; 3017163953Srrs } 3018163953Srrs 3019218072Srrs /* Find where it was sent to if possible. */ 3020163953Srrs net = NULL; 3021216822Stuexen TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) { 3022163953Srrs if (lchk->rec.data.TSN_seq == tsn) { 3023163953Srrs net = lchk->whoTo; 3024218186Srrs net->ecn_prev_cwnd = lchk->rec.data.cwnd_at_send; 3025163953Srrs break; 3026163953Srrs } 3027216825Stuexen if (SCTP_TSN_GT(lchk->rec.data.TSN_seq, tsn)) { 3028163953Srrs break; 3029216825Stuexen } 3030163953Srrs } 3031218072Srrs if (net == NULL) { 3032163953Srrs /* 3033218072Srrs * What to do. A previous send of a CWR was possibly lost. 3034218072Srrs * See how old it is, we may have it marked on the actual 3035218072Srrs * net. 3036218072Srrs */ 3037218072Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 3038218072Srrs if (tsn == net->last_cwr_tsn) { 3039218072Srrs /* Found him, send it off */ 3040228907Stuexen break; 3041218072Srrs } 3042218072Srrs } 3043228907Stuexen if (net == NULL) { 3044228907Stuexen /* 3045228907Stuexen * If we reach here, we need to send a special CWR 3046228907Stuexen * that says hey, we did this a long time ago and 3047228907Stuexen * you lost the response. 3048228907Stuexen */ 3049228907Stuexen net = TAILQ_FIRST(&stcb->asoc.nets); 3050228907Stuexen if (net == NULL) { 3051228907Stuexen /* TSNH */ 3052228907Stuexen return; 3053228907Stuexen } 3054228907Stuexen override_bit = SCTP_CWR_REDUCE_OVERRIDE; 3055228907Stuexen } else { 3056228907Stuexen override_bit = 0; 3057228907Stuexen } 3058228907Stuexen } else { 3059228907Stuexen override_bit = 0; 3060218072Srrs } 3061218129Srrs if (SCTP_TSN_GT(tsn, net->cwr_window_tsn) && 3062218129Srrs ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 3063218072Srrs /* 3064171440Srrs * JRS - Use the congestion control given in the pluggable 3065171440Srrs * CC module 3066171440Srrs */ 3067218129Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 0, pkt_cnt); 3068171440Srrs /* 3069218072Srrs * We reduce once every RTT. So we will only lower cwnd at 3070218072Srrs * the next sending seq i.e. the window_data_tsn 3071163953Srrs */ 3072218072Srrs net->cwr_window_tsn = window_data_tsn; 3073218072Srrs net->ecn_ce_pkt_cnt += pkt_cnt; 3074218072Srrs net->lost_cnt = pkt_cnt; 3075218072Srrs net->last_cwr_tsn = tsn; 3076218072Srrs } else { 3077218072Srrs override_bit |= SCTP_CWR_IN_SAME_WINDOW; 3078218129Srrs if (SCTP_TSN_GT(tsn, net->last_cwr_tsn) && 3079218129Srrs ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 3080218072Srrs /* 3081218129Srrs * Another loss in the same window update how many 3082218129Srrs * marks/packets lost we have had. 3083218072Srrs */ 3084218129Srrs int cnt = 1; 3085218072Srrs 3086218072Srrs if (pkt_cnt > net->lost_cnt) { 3087218072Srrs /* Should be the case */ 3088218129Srrs cnt = (pkt_cnt - net->lost_cnt); 3089218129Srrs net->ecn_ce_pkt_cnt += cnt; 3090218072Srrs } 3091218129Srrs net->lost_cnt = pkt_cnt; 3092218072Srrs net->last_cwr_tsn = tsn; 3093218129Srrs /* 3094218129Srrs * Most CC functions will ignore this call, since we 3095218129Srrs * are in-window yet of the initial CE the peer saw. 3096218129Srrs */ 3097218129Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 1, cnt); 3098218072Srrs } 3099163953Srrs } 3100163953Srrs /* 3101163953Srrs * We always send a CWR this way if our previous one was lost our 3102163953Srrs * peer will get an update, or if it is not time again to reduce we 3103218072Srrs * still get the cwr to the peer. Note we set the override when we 3104218072Srrs * could not find the TSN on the chunk or the destination network. 3105163953Srrs */ 3106218072Srrs sctp_send_cwr(stcb, net, net->last_cwr_tsn, override_bit); 3107163953Srrs} 3108163953Srrs 3109163953Srrsstatic void 3110218072Srrssctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sctp_nets *net) 3111163953Srrs{ 3112163953Srrs /* 3113163953Srrs * Here we get a CWR from the peer. We must look in the outqueue and 3114240520Seadler * make sure that we have a covered ECNE in the control chunk part. 3115163953Srrs * If so remove it. 3116163953Srrs */ 3117163953Srrs struct sctp_tmit_chunk *chk; 3118163953Srrs struct sctp_ecne_chunk *ecne; 3119218072Srrs int override; 3120218072Srrs uint32_t cwr_tsn; 3121163953Srrs 3122218072Srrs cwr_tsn = ntohl(cp->tsn); 3123218072Srrs 3124218072Srrs override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE; 3125163953Srrs TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 3126163953Srrs if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) { 3127163953Srrs continue; 3128163953Srrs } 3129218072Srrs if ((override == 0) && (chk->whoTo != net)) { 3130218072Srrs /* Must be from the right src unless override is set */ 3131218072Srrs continue; 3132218072Srrs } 3133163953Srrs ecne = mtod(chk->data, struct sctp_ecne_chunk *); 3134218072Srrs if (SCTP_TSN_GE(cwr_tsn, ntohl(ecne->tsn))) { 3135163953Srrs /* this covers this ECNE, we can remove it */ 3136163953Srrs stcb->asoc.ecn_echo_cnt_onq--; 3137163953Srrs TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk, 3138163953Srrs sctp_next); 3139163953Srrs if (chk->data) { 3140163953Srrs sctp_m_freem(chk->data); 3141163953Srrs chk->data = NULL; 3142163953Srrs } 3143163953Srrs stcb->asoc.ctrl_queue_cnt--; 3144221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 3145218072Srrs if (override == 0) { 3146218072Srrs break; 3147218072Srrs } 3148163953Srrs } 3149163953Srrs } 3150163953Srrs} 3151163953Srrs 3152163953Srrsstatic void 3153228653Stuexensctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSED, 3154163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 3155163953Srrs{ 3156163953Srrs struct sctp_association *asoc; 3157163953Srrs 3158237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3159172090Srrs struct socket *so; 3160172090Srrs 3161172090Srrs#endif 3162172090Srrs 3163169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3164169420Srrs "sctp_handle_shutdown_complete: handling SHUTDOWN-COMPLETE\n"); 3165163953Srrs if (stcb == NULL) 3166163953Srrs return; 3167163953Srrs 3168163953Srrs asoc = &stcb->asoc; 3169163953Srrs /* process according to association state */ 3170163953Srrs if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) { 3171163953Srrs /* unexpected SHUTDOWN-COMPLETE... so ignore... */ 3172171990Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3173171990Srrs "sctp_handle_shutdown_complete: not in SCTP_STATE_SHUTDOWN_ACK_SENT --- ignore\n"); 3174163953Srrs SCTP_TCB_UNLOCK(stcb); 3175163953Srrs return; 3176163953Srrs } 3177163953Srrs /* notify upper layer protocol */ 3178163953Srrs if (stcb->sctp_socket) { 3179172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 3180163953Srrs } 3181252585Stuexen#ifdef INVARIANTS 3182252585Stuexen if (!TAILQ_EMPTY(&asoc->send_queue) || 3183252585Stuexen !TAILQ_EMPTY(&asoc->sent_queue) || 3184252585Stuexen !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 3185252585Stuexen panic("Queues are not empty when handling SHUTDOWN-COMPLETE"); 3186252585Stuexen } 3187252585Stuexen#endif 3188163953Srrs /* stop the timer */ 3189178202Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_22); 3190163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 3191163953Srrs /* free the TCB */ 3192171990Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3193171990Srrs "sctp_handle_shutdown_complete: calls free-asoc\n"); 3194237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3195172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 3196172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 3197172090Srrs SCTP_TCB_UNLOCK(stcb); 3198172090Srrs SCTP_SOCKET_LOCK(so, 1); 3199172090Srrs SCTP_TCB_LOCK(stcb); 3200172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 3201172090Srrs#endif 3202171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_23); 3203237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3204172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 3205172090Srrs#endif 3206163953Srrs return; 3207163953Srrs} 3208163953Srrs 3209163953Srrsstatic int 3210163953Srrsprocess_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, 3211163953Srrs struct sctp_nets *net, uint8_t flg) 3212163953Srrs{ 3213163953Srrs switch (desc->chunk_type) { 3214211969Stuexen case SCTP_DATA: 3215163953Srrs /* find the tsn to resend (possibly */ 3216163953Srrs { 3217163953Srrs uint32_t tsn; 3218163953Srrs struct sctp_tmit_chunk *tp1; 3219163953Srrs 3220163953Srrs tsn = ntohl(desc->tsn_ifany); 3221216822Stuexen TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3222163953Srrs if (tp1->rec.data.TSN_seq == tsn) { 3223163953Srrs /* found it */ 3224163953Srrs break; 3225163953Srrs } 3226216825Stuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, tsn)) { 3227163953Srrs /* not found */ 3228163953Srrs tp1 = NULL; 3229163953Srrs break; 3230163953Srrs } 3231163953Srrs } 3232163953Srrs if (tp1 == NULL) { 3233163953Srrs /* 3234163953Srrs * Do it the other way , aka without paying 3235163953Srrs * attention to queue seq order. 3236163953Srrs */ 3237163953Srrs SCTP_STAT_INCR(sctps_pdrpdnfnd); 3238216822Stuexen TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3239163953Srrs if (tp1->rec.data.TSN_seq == tsn) { 3240163953Srrs /* found it */ 3241163953Srrs break; 3242163953Srrs } 3243163953Srrs } 3244163953Srrs } 3245163953Srrs if (tp1 == NULL) { 3246163953Srrs SCTP_STAT_INCR(sctps_pdrptsnnf); 3247163953Srrs } 3248163953Srrs if ((tp1) && (tp1->sent < SCTP_DATAGRAM_ACKED)) { 3249163953Srrs uint8_t *ddp; 3250163953Srrs 3251214877Stuexen if (((flg & SCTP_BADCRC) == 0) && 3252214877Stuexen ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 3253214877Stuexen return (0); 3254214877Stuexen } 3255163953Srrs if ((stcb->asoc.peers_rwnd == 0) && 3256163953Srrs ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 3257163953Srrs SCTP_STAT_INCR(sctps_pdrpdiwnp); 3258163953Srrs return (0); 3259163953Srrs } 3260163953Srrs if (stcb->asoc.peers_rwnd == 0 && 3261163953Srrs (flg & SCTP_FROM_MIDDLE_BOX)) { 3262163953Srrs SCTP_STAT_INCR(sctps_pdrpdizrw); 3263163953Srrs return (0); 3264163953Srrs } 3265163953Srrs ddp = (uint8_t *) (mtod(tp1->data, caddr_t)+ 3266163953Srrs sizeof(struct sctp_data_chunk)); 3267163953Srrs { 3268163953Srrs unsigned int iii; 3269163953Srrs 3270163953Srrs for (iii = 0; iii < sizeof(desc->data_bytes); 3271163953Srrs iii++) { 3272163953Srrs if (ddp[iii] != desc->data_bytes[iii]) { 3273163953Srrs SCTP_STAT_INCR(sctps_pdrpbadd); 3274163953Srrs return (-1); 3275163953Srrs } 3276163953Srrs } 3277163953Srrs } 3278163953Srrs 3279163953Srrs if (tp1->do_rtt) { 3280163953Srrs /* 3281163953Srrs * this guy had a RTO calculation 3282163953Srrs * pending on it, cancel it 3283163953Srrs */ 3284219397Srrs if (tp1->whoTo->rto_needed == 0) { 3285219397Srrs tp1->whoTo->rto_needed = 1; 3286219397Srrs } 3287163953Srrs tp1->do_rtt = 0; 3288163953Srrs } 3289163953Srrs SCTP_STAT_INCR(sctps_pdrpmark); 3290163953Srrs if (tp1->sent != SCTP_DATAGRAM_RESEND) 3291163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3292163953Srrs /* 3293163953Srrs * mark it as if we were doing a FR, since 3294163953Srrs * we will be getting gap ack reports behind 3295163953Srrs * the info from the router. 3296163953Srrs */ 3297163953Srrs tp1->rec.data.doing_fast_retransmit = 1; 3298163953Srrs /* 3299163953Srrs * mark the tsn with what sequences can 3300163953Srrs * cause a new FR. 3301163953Srrs */ 3302163953Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue)) { 3303163953Srrs tp1->rec.data.fast_retran_tsn = stcb->asoc.sending_seq; 3304163953Srrs } else { 3305163953Srrs tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq; 3306163953Srrs } 3307163953Srrs 3308163953Srrs /* restart the timer */ 3309163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 3310171440Srrs stcb, tp1->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_24); 3311163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 3312163953Srrs stcb, tp1->whoTo); 3313163953Srrs 3314163953Srrs /* fix counts and things */ 3315179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 3316170744Srrs sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP, 3317170744Srrs tp1->whoTo->flight_size, 3318170744Srrs tp1->book_size, 3319170744Srrs (uintptr_t) stcb, 3320170744Srrs tp1->rec.data.TSN_seq); 3321170744Srrs } 3322190689Srrs if (tp1->sent < SCTP_DATAGRAM_RESEND) { 3323190689Srrs sctp_flight_size_decrease(tp1); 3324190689Srrs sctp_total_flight_decrease(stcb, tp1); 3325190689Srrs } 3326216502Stuexen tp1->sent = SCTP_DATAGRAM_RESEND; 3327163953Srrs } { 3328163953Srrs /* audit code */ 3329163953Srrs unsigned int audit; 3330163953Srrs 3331163953Srrs audit = 0; 3332163953Srrs TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3333163953Srrs if (tp1->sent == SCTP_DATAGRAM_RESEND) 3334163953Srrs audit++; 3335163953Srrs } 3336163953Srrs TAILQ_FOREACH(tp1, &stcb->asoc.control_send_queue, 3337163953Srrs sctp_next) { 3338163953Srrs if (tp1->sent == SCTP_DATAGRAM_RESEND) 3339163953Srrs audit++; 3340163953Srrs } 3341163953Srrs if (audit != stcb->asoc.sent_queue_retran_cnt) { 3342169420Srrs SCTP_PRINTF("**Local Audit finds cnt:%d asoc cnt:%d\n", 3343163953Srrs audit, stcb->asoc.sent_queue_retran_cnt); 3344163953Srrs#ifndef SCTP_AUDITING_ENABLED 3345163953Srrs stcb->asoc.sent_queue_retran_cnt = audit; 3346163953Srrs#endif 3347163953Srrs } 3348163953Srrs } 3349163953Srrs } 3350163953Srrs break; 3351163953Srrs case SCTP_ASCONF: 3352163953Srrs { 3353163953Srrs struct sctp_tmit_chunk *asconf; 3354163953Srrs 3355163953Srrs TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue, 3356163953Srrs sctp_next) { 3357163953Srrs if (asconf->rec.chunk_id.id == SCTP_ASCONF) { 3358163953Srrs break; 3359163953Srrs } 3360163953Srrs } 3361163953Srrs if (asconf) { 3362163953Srrs if (asconf->sent != SCTP_DATAGRAM_RESEND) 3363163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3364163953Srrs asconf->sent = SCTP_DATAGRAM_RESEND; 3365163953Srrs asconf->snd_count--; 3366163953Srrs } 3367163953Srrs } 3368163953Srrs break; 3369163953Srrs case SCTP_INITIATION: 3370163953Srrs /* resend the INIT */ 3371163953Srrs stcb->asoc.dropped_special_cnt++; 3372163953Srrs if (stcb->asoc.dropped_special_cnt < SCTP_RETRY_DROPPED_THRESH) { 3373163953Srrs /* 3374163953Srrs * If we can get it in, in a few attempts we do 3375163953Srrs * this, otherwise we let the timer fire. 3376163953Srrs */ 3377163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, 3378171440Srrs stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_25); 3379172090Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 3380163953Srrs } 3381163953Srrs break; 3382163953Srrs case SCTP_SELECTIVE_ACK: 3383206137Stuexen case SCTP_NR_SELECTIVE_ACK: 3384163953Srrs /* resend the sack */ 3385221627Stuexen sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 3386163953Srrs break; 3387163953Srrs case SCTP_HEARTBEAT_REQUEST: 3388163953Srrs /* resend a demand HB */ 3389171440Srrs if ((stcb->asoc.overall_error_count + 3) < stcb->asoc.max_send_times) { 3390171440Srrs /* 3391171440Srrs * Only retransmit if we KNOW we wont destroy the 3392171440Srrs * tcb 3393171440Srrs */ 3394224641Stuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 3395171440Srrs } 3396163953Srrs break; 3397163953Srrs case SCTP_SHUTDOWN: 3398163953Srrs sctp_send_shutdown(stcb, net); 3399163953Srrs break; 3400163953Srrs case SCTP_SHUTDOWN_ACK: 3401163953Srrs sctp_send_shutdown_ack(stcb, net); 3402163953Srrs break; 3403163953Srrs case SCTP_COOKIE_ECHO: 3404163953Srrs { 3405163953Srrs struct sctp_tmit_chunk *cookie; 3406163953Srrs 3407163953Srrs cookie = NULL; 3408163953Srrs TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, 3409163953Srrs sctp_next) { 3410163953Srrs if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) { 3411163953Srrs break; 3412163953Srrs } 3413163953Srrs } 3414163953Srrs if (cookie) { 3415163953Srrs if (cookie->sent != SCTP_DATAGRAM_RESEND) 3416163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3417163953Srrs cookie->sent = SCTP_DATAGRAM_RESEND; 3418163953Srrs sctp_stop_all_cookie_timers(stcb); 3419163953Srrs } 3420163953Srrs } 3421163953Srrs break; 3422163953Srrs case SCTP_COOKIE_ACK: 3423163953Srrs sctp_send_cookie_ack(stcb); 3424163953Srrs break; 3425163953Srrs case SCTP_ASCONF_ACK: 3426163953Srrs /* resend last asconf ack */ 3427171990Srrs sctp_send_asconf_ack(stcb); 3428163953Srrs break; 3429163953Srrs case SCTP_FORWARD_CUM_TSN: 3430163953Srrs send_forward_tsn(stcb, &stcb->asoc); 3431163953Srrs break; 3432163953Srrs /* can't do anything with these */ 3433163953Srrs case SCTP_PACKET_DROPPED: 3434163953Srrs case SCTP_INITIATION_ACK: /* this should not happen */ 3435163953Srrs case SCTP_HEARTBEAT_ACK: 3436163953Srrs case SCTP_ABORT_ASSOCIATION: 3437163953Srrs case SCTP_OPERATION_ERROR: 3438163953Srrs case SCTP_SHUTDOWN_COMPLETE: 3439163953Srrs case SCTP_ECN_ECHO: 3440163953Srrs case SCTP_ECN_CWR: 3441163953Srrs default: 3442163953Srrs break; 3443163953Srrs } 3444163953Srrs return (0); 3445163953Srrs} 3446163953Srrs 3447163953Srrsvoid 3448240198Stuexensctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list) 3449163953Srrs{ 3450240198Stuexen uint32_t i; 3451163953Srrs uint16_t temp; 3452163953Srrs 3453163953Srrs /* 3454163953Srrs * We set things to 0xffff since this is the last delivered sequence 3455163953Srrs * and we will be sending in 0 after the reset. 3456163953Srrs */ 3457163953Srrs 3458163953Srrs if (number_entries) { 3459163953Srrs for (i = 0; i < number_entries; i++) { 3460163953Srrs temp = ntohs(list[i]); 3461163953Srrs if (temp >= stcb->asoc.streamincnt) { 3462163953Srrs continue; 3463163953Srrs } 3464163953Srrs stcb->asoc.strmin[temp].last_sequence_delivered = 0xffff; 3465163953Srrs } 3466163953Srrs } else { 3467163953Srrs list = NULL; 3468163953Srrs for (i = 0; i < stcb->asoc.streamincnt; i++) { 3469163953Srrs stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 3470163953Srrs } 3471163953Srrs } 3472172090Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 3473163953Srrs} 3474163953Srrs 3475163953Srrsstatic void 3476252585Stuexensctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list) 3477163953Srrs{ 3478252585Stuexen uint32_t i; 3479252585Stuexen uint16_t temp; 3480163953Srrs 3481252585Stuexen if (number_entries > 0) { 3482163953Srrs for (i = 0; i < number_entries; i++) { 3483163953Srrs temp = ntohs(list[i]); 3484163953Srrs if (temp >= stcb->asoc.streamoutcnt) { 3485163953Srrs /* no such stream */ 3486163953Srrs continue; 3487163953Srrs } 3488242627Stuexen stcb->asoc.strmout[temp].next_sequence_send = 0; 3489163953Srrs } 3490252585Stuexen } else { 3491252585Stuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 3492252585Stuexen stcb->asoc.strmout[i].next_sequence_send = 0; 3493252585Stuexen } 3494163953Srrs } 3495172090Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 3496163953Srrs} 3497163953Srrs 3498163953Srrs 3499273303Stuexenstruct sctp_stream_reset_request * 3500163953Srrssctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk) 3501163953Srrs{ 3502163953Srrs struct sctp_association *asoc; 3503240198Stuexen struct sctp_chunkhdr *ch; 3504273303Stuexen struct sctp_stream_reset_request *r; 3505163953Srrs struct sctp_tmit_chunk *chk; 3506163953Srrs int len, clen; 3507163953Srrs 3508163953Srrs asoc = &stcb->asoc; 3509163953Srrs if (TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 3510169208Srrs asoc->stream_reset_outstanding = 0; 3511163953Srrs return (NULL); 3512163953Srrs } 3513163953Srrs if (stcb->asoc.str_reset == NULL) { 3514169208Srrs asoc->stream_reset_outstanding = 0; 3515163953Srrs return (NULL); 3516163953Srrs } 3517163953Srrs chk = stcb->asoc.str_reset; 3518163953Srrs if (chk->data == NULL) { 3519163953Srrs return (NULL); 3520163953Srrs } 3521163953Srrs if (bchk) { 3522163953Srrs /* he wants a copy of the chk pointer */ 3523163953Srrs *bchk = chk; 3524163953Srrs } 3525163953Srrs clen = chk->send_size; 3526240198Stuexen ch = mtod(chk->data, struct sctp_chunkhdr *); 3527273303Stuexen r = (struct sctp_stream_reset_request *)(ch + 1); 3528163953Srrs if (ntohl(r->request_seq) == seq) { 3529163953Srrs /* found it */ 3530163953Srrs return (r); 3531163953Srrs } 3532163953Srrs len = SCTP_SIZE32(ntohs(r->ph.param_length)); 3533163953Srrs if (clen > (len + (int)sizeof(struct sctp_chunkhdr))) { 3534163953Srrs /* move to the next one, there can only be a max of two */ 3535273303Stuexen r = (struct sctp_stream_reset_request *)((caddr_t)r + len); 3536163953Srrs if (ntohl(r->request_seq) == seq) { 3537163953Srrs return (r); 3538163953Srrs } 3539163953Srrs } 3540163953Srrs /* that seq is not here */ 3541163953Srrs return (NULL); 3542163953Srrs} 3543163953Srrs 3544163953Srrsstatic void 3545163953Srrssctp_clean_up_stream_reset(struct sctp_tcb *stcb) 3546163953Srrs{ 3547163953Srrs struct sctp_association *asoc; 3548163953Srrs struct sctp_tmit_chunk *chk = stcb->asoc.str_reset; 3549163953Srrs 3550163953Srrs if (stcb->asoc.str_reset == NULL) { 3551163953Srrs return; 3552163953Srrs } 3553166675Srrs asoc = &stcb->asoc; 3554166675Srrs 3555171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_26); 3556163953Srrs TAILQ_REMOVE(&asoc->control_send_queue, 3557163953Srrs chk, 3558163953Srrs sctp_next); 3559163953Srrs if (chk->data) { 3560163953Srrs sctp_m_freem(chk->data); 3561163953Srrs chk->data = NULL; 3562163953Srrs } 3563163953Srrs asoc->ctrl_queue_cnt--; 3564221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 3565172156Srrs /* sa_ignore NO_NULL_CHK */ 3566163953Srrs stcb->asoc.str_reset = NULL; 3567163953Srrs} 3568163953Srrs 3569163953Srrs 3570163953Srrsstatic int 3571163953Srrssctp_handle_stream_reset_response(struct sctp_tcb *stcb, 3572163953Srrs uint32_t seq, uint32_t action, 3573164139Srrs struct sctp_stream_reset_response *respin) 3574163953Srrs{ 3575163953Srrs uint16_t type; 3576163953Srrs int lparm_len; 3577163953Srrs struct sctp_association *asoc = &stcb->asoc; 3578163953Srrs struct sctp_tmit_chunk *chk; 3579273303Stuexen struct sctp_stream_reset_request *req_param; 3580273303Stuexen struct sctp_stream_reset_out_request *req_out_param; 3581273303Stuexen struct sctp_stream_reset_in_request *req_in_param; 3582252585Stuexen uint32_t number_entries; 3583163953Srrs 3584163953Srrs if (asoc->stream_reset_outstanding == 0) { 3585163953Srrs /* duplicate */ 3586163953Srrs return (0); 3587163953Srrs } 3588163953Srrs if (seq == stcb->asoc.str_reset_seq_out) { 3589273303Stuexen req_param = sctp_find_stream_reset(stcb, seq, &chk); 3590273303Stuexen if (req_param != NULL) { 3591163953Srrs stcb->asoc.str_reset_seq_out++; 3592273303Stuexen type = ntohs(req_param->ph.param_type); 3593273303Stuexen lparm_len = ntohs(req_param->ph.param_length); 3594163953Srrs if (type == SCTP_STR_RESET_OUT_REQUEST) { 3595273303Stuexen req_out_param = (struct sctp_stream_reset_out_request *)req_param; 3596164139Srrs number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t); 3597163953Srrs asoc->stream_reset_out_is_outstanding = 0; 3598163953Srrs if (asoc->stream_reset_outstanding) 3599163953Srrs asoc->stream_reset_outstanding--; 3600235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3601163953Srrs /* do it */ 3602273303Stuexen sctp_reset_out_streams(stcb, number_entries, req_out_param->list_of_streams); 3603235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3604273303Stuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED); 3605163953Srrs } else { 3606273303Stuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED); 3607163953Srrs } 3608163953Srrs } else if (type == SCTP_STR_RESET_IN_REQUEST) { 3609273303Stuexen req_in_param = (struct sctp_stream_reset_in_request *)req_param; 3610164139Srrs number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t); 3611163953Srrs if (asoc->stream_reset_outstanding) 3612163953Srrs asoc->stream_reset_outstanding--; 3613235066Stuexen if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3614235066Stuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_IN, stcb, 3615273303Stuexen number_entries, req_in_param->list_of_streams, SCTP_SO_NOT_LOCKED); 3616235066Stuexen } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 3617233660Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb, 3618273303Stuexen number_entries, req_in_param->list_of_streams, SCTP_SO_NOT_LOCKED); 3619163953Srrs } 3620233660Srrs } else if (type == SCTP_STR_RESET_ADD_OUT_STREAMS) { 3621188854Srrs /* Ok we now may have more streams */ 3622233660Srrs int num_stream; 3623233660Srrs 3624233660Srrs num_stream = stcb->asoc.strm_pending_add_size; 3625233660Srrs if (num_stream > (stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt)) { 3626233660Srrs /* TSNH */ 3627233660Srrs num_stream = stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt; 3628233660Srrs } 3629233660Srrs stcb->asoc.strm_pending_add_size = 0; 3630189121Srrs if (asoc->stream_reset_outstanding) 3631189121Srrs asoc->stream_reset_outstanding--; 3632235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3633188854Srrs /* Put the new streams into effect */ 3634233660Srrs stcb->asoc.streamoutcnt += num_stream; 3635233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 3636235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3637235066Stuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3638235066Stuexen SCTP_STREAM_CHANGE_DENIED); 3639188854Srrs } else { 3640233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3641235066Stuexen SCTP_STREAM_CHANGE_FAILED); 3642188854Srrs } 3643233660Srrs } else if (type == SCTP_STR_RESET_ADD_IN_STREAMS) { 3644233660Srrs if (asoc->stream_reset_outstanding) 3645233660Srrs asoc->stream_reset_outstanding--; 3646235066Stuexen if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3647233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3648235066Stuexen SCTP_STREAM_CHANGE_DENIED); 3649235066Stuexen } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 3650235066Stuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3651235066Stuexen SCTP_STREAM_CHANGE_FAILED); 3652233660Srrs } 3653163953Srrs } else if (type == SCTP_STR_RESET_TSN_REQUEST) { 3654163953Srrs /** 3655163953Srrs * a) Adopt the new in tsn. 3656163953Srrs * b) reset the map 3657163953Srrs * c) Adopt the new out-tsn 3658163953Srrs */ 3659163953Srrs struct sctp_stream_reset_response_tsn *resp; 3660163953Srrs struct sctp_forward_tsn_chunk fwdtsn; 3661163953Srrs int abort_flag = 0; 3662163953Srrs 3663163953Srrs if (respin == NULL) { 3664163953Srrs /* huh ? */ 3665163953Srrs return (0); 3666163953Srrs } 3667277808Sdelphij if (ntohs(respin->ph.param_length) < sizeof(struct sctp_stream_reset_response_tsn)) { 3668277808Sdelphij return (0); 3669277808Sdelphij } 3670235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3671163953Srrs resp = (struct sctp_stream_reset_response_tsn *)respin; 3672163953Srrs asoc->stream_reset_outstanding--; 3673163953Srrs fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 3674163953Srrs fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 3675163953Srrs fwdtsn.new_cumulative_tsn = htonl(ntohl(resp->senders_next_tsn) - 1); 3676170992Srrs sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 3677163953Srrs if (abort_flag) { 3678163953Srrs return (1); 3679163953Srrs } 3680163953Srrs stcb->asoc.highest_tsn_inside_map = (ntohl(resp->senders_next_tsn) - 1); 3681179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 3682179783Srrs sctp_log_map(0, 7, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 3683179783Srrs } 3684180955Srrs stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map; 3685163953Srrs stcb->asoc.mapping_array_base_tsn = ntohl(resp->senders_next_tsn); 3686163953Srrs memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); 3687185694Srrs 3688205627Srrs stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; 3689206137Stuexen memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size); 3690205627Srrs 3691163953Srrs stcb->asoc.sending_seq = ntohl(resp->receivers_next_tsn); 3692163953Srrs stcb->asoc.last_acked_seq = stcb->asoc.cumulative_tsn; 3693163953Srrs 3694163953Srrs sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 3695163953Srrs sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 3696233660Srrs sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 0); 3697235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3698235066Stuexen sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 3699235066Stuexen SCTP_ASSOC_RESET_DENIED); 3700233660Srrs } else { 3701233660Srrs sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 3702235066Stuexen SCTP_ASSOC_RESET_FAILED); 3703163953Srrs } 3704163953Srrs } 3705163953Srrs /* get rid of the request and get the request flags */ 3706163953Srrs if (asoc->stream_reset_outstanding == 0) { 3707163953Srrs sctp_clean_up_stream_reset(stcb); 3708163953Srrs } 3709163953Srrs } 3710163953Srrs } 3711163953Srrs return (0); 3712163953Srrs} 3713163953Srrs 3714163953Srrsstatic void 3715163953Srrssctp_handle_str_reset_request_in(struct sctp_tcb *stcb, 3716163953Srrs struct sctp_tmit_chunk *chk, 3717170992Srrs struct sctp_stream_reset_in_request *req, int trunc) 3718163953Srrs{ 3719163953Srrs uint32_t seq; 3720163953Srrs int len, i; 3721163953Srrs int number_entries; 3722163953Srrs uint16_t temp; 3723163953Srrs 3724163953Srrs /* 3725163953Srrs * peer wants me to send a str-reset to him for my outgoing seq's if 3726163953Srrs * seq_in is right. 3727163953Srrs */ 3728163953Srrs struct sctp_association *asoc = &stcb->asoc; 3729163953Srrs 3730163953Srrs seq = ntohl(req->request_seq); 3731163953Srrs if (asoc->str_reset_seq_in == seq) { 3732235064Stuexen asoc->last_reset_action[1] = asoc->last_reset_action[0]; 3733235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 3734235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3735235064Stuexen } else if (trunc) { 3736170992Srrs /* Can't do it, since they exceeded our buffer size */ 3737235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3738170992Srrs } else if (stcb->asoc.stream_reset_out_is_outstanding == 0) { 3739163953Srrs len = ntohs(req->ph.param_length); 3740163953Srrs number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t)); 3741163953Srrs for (i = 0; i < number_entries; i++) { 3742163953Srrs temp = ntohs(req->list_of_streams[i]); 3743163953Srrs req->list_of_streams[i] = temp; 3744163953Srrs } 3745235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3746163953Srrs sctp_add_stream_reset_out(chk, number_entries, req->list_of_streams, 3747163953Srrs asoc->str_reset_seq_out, 3748163953Srrs seq, (asoc->sending_seq - 1)); 3749163953Srrs asoc->stream_reset_out_is_outstanding = 1; 3750163953Srrs asoc->str_reset = chk; 3751163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); 3752163953Srrs stcb->asoc.stream_reset_outstanding++; 3753163953Srrs } else { 3754163953Srrs /* Can't do it, since we have sent one out */ 3755235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 3756163953Srrs } 3757233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3758163953Srrs asoc->str_reset_seq_in++; 3759163953Srrs } else if (asoc->str_reset_seq_in - 1 == seq) { 3760163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3761163953Srrs } else if (asoc->str_reset_seq_in - 2 == seq) { 3762163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 3763163953Srrs } else { 3764235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3765163953Srrs } 3766163953Srrs} 3767163953Srrs 3768163953Srrsstatic int 3769163953Srrssctp_handle_str_reset_request_tsn(struct sctp_tcb *stcb, 3770163953Srrs struct sctp_tmit_chunk *chk, 3771163953Srrs struct sctp_stream_reset_tsn_request *req) 3772163953Srrs{ 3773163953Srrs /* reset all in and out and update the tsn */ 3774163953Srrs /* 3775163953Srrs * A) reset my str-seq's on in and out. B) Select a receive next, 3776163953Srrs * and set cum-ack to it. Also process this selected number as a 3777163953Srrs * fwd-tsn as well. C) set in the response my next sending seq. 3778163953Srrs */ 3779163953Srrs struct sctp_forward_tsn_chunk fwdtsn; 3780163953Srrs struct sctp_association *asoc = &stcb->asoc; 3781163953Srrs int abort_flag = 0; 3782163953Srrs uint32_t seq; 3783163953Srrs 3784163953Srrs seq = ntohl(req->request_seq); 3785163953Srrs if (asoc->str_reset_seq_in == seq) { 3786235283Stuexen asoc->last_reset_action[1] = stcb->asoc.last_reset_action[0]; 3787235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 3788235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3789235283Stuexen } else { 3790235064Stuexen fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 3791235283Stuexen fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 3792235283Stuexen fwdtsn.ch.chunk_flags = 0; 3793235283Stuexen fwdtsn.new_cumulative_tsn = htonl(stcb->asoc.highest_tsn_inside_map + 1); 3794235283Stuexen sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 3795235283Stuexen if (abort_flag) { 3796235283Stuexen return (1); 3797235283Stuexen } 3798235283Stuexen asoc->highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA; 3799235283Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 3800235283Stuexen sctp_log_map(0, 10, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 3801235283Stuexen } 3802235283Stuexen asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->highest_tsn_inside_map; 3803235283Stuexen asoc->mapping_array_base_tsn = asoc->highest_tsn_inside_map + 1; 3804235283Stuexen memset(asoc->mapping_array, 0, asoc->mapping_array_size); 3805235283Stuexen asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 3806235283Stuexen memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size); 3807235283Stuexen atomic_add_int(&asoc->sending_seq, 1); 3808235283Stuexen /* save off historical data for retrans */ 3809235283Stuexen asoc->last_sending_seq[1] = asoc->last_sending_seq[0]; 3810235283Stuexen asoc->last_sending_seq[0] = asoc->sending_seq; 3811235283Stuexen asoc->last_base_tsnsent[1] = asoc->last_base_tsnsent[0]; 3812235283Stuexen asoc->last_base_tsnsent[0] = asoc->mapping_array_base_tsn; 3813235283Stuexen sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 3814235283Stuexen sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 3815235283Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3816235283Stuexen sctp_notify_stream_reset_tsn(stcb, asoc->sending_seq, (asoc->mapping_array_base_tsn + 1), 0); 3817163953Srrs } 3818235283Stuexen sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 3819235283Stuexen asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 3820163953Srrs asoc->str_reset_seq_in++; 3821163953Srrs } else if (asoc->str_reset_seq_in - 1 == seq) { 3822163953Srrs sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 3823235064Stuexen asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 3824163953Srrs } else if (asoc->str_reset_seq_in - 2 == seq) { 3825163953Srrs sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[1], 3826235064Stuexen asoc->last_sending_seq[1], asoc->last_base_tsnsent[1]); 3827163953Srrs } else { 3828235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3829163953Srrs } 3830163953Srrs return (0); 3831163953Srrs} 3832163953Srrs 3833163953Srrsstatic void 3834163953Srrssctp_handle_str_reset_request_out(struct sctp_tcb *stcb, 3835163953Srrs struct sctp_tmit_chunk *chk, 3836170992Srrs struct sctp_stream_reset_out_request *req, int trunc) 3837163953Srrs{ 3838163953Srrs uint32_t seq, tsn; 3839163953Srrs int number_entries, len; 3840163953Srrs struct sctp_association *asoc = &stcb->asoc; 3841163953Srrs 3842163953Srrs seq = ntohl(req->request_seq); 3843163953Srrs 3844163953Srrs /* now if its not a duplicate we process it */ 3845163953Srrs if (asoc->str_reset_seq_in == seq) { 3846163953Srrs len = ntohs(req->ph.param_length); 3847163953Srrs number_entries = ((len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t)); 3848163953Srrs /* 3849163953Srrs * the sender is resetting, handle the list issue.. we must 3850163953Srrs * a) verify if we can do the reset, if so no problem b) If 3851163953Srrs * we can't do the reset we must copy the request. c) queue 3852163953Srrs * it, and setup the data in processor to trigger it off 3853163953Srrs * when needed and dequeue all the queued data. 3854163953Srrs */ 3855163953Srrs tsn = ntohl(req->send_reset_at_tsn); 3856163953Srrs 3857163953Srrs /* move the reset action back one */ 3858163953Srrs asoc->last_reset_action[1] = asoc->last_reset_action[0]; 3859235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 3860235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3861235064Stuexen } else if (trunc) { 3862235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3863216825Stuexen } else if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) { 3864163953Srrs /* we can do it now */ 3865163953Srrs sctp_reset_in_stream(stcb, number_entries, req->list_of_streams); 3866235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3867163953Srrs } else { 3868163953Srrs /* 3869163953Srrs * we must queue it up and thus wait for the TSN's 3870163953Srrs * to arrive that are at or before tsn 3871163953Srrs */ 3872163953Srrs struct sctp_stream_reset_list *liste; 3873163953Srrs int siz; 3874163953Srrs 3875163953Srrs siz = sizeof(struct sctp_stream_reset_list) + (number_entries * sizeof(uint16_t)); 3876163953Srrs SCTP_MALLOC(liste, struct sctp_stream_reset_list *, 3877170091Srrs siz, SCTP_M_STRESET); 3878163953Srrs if (liste == NULL) { 3879163953Srrs /* gak out of memory */ 3880235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3881235064Stuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3882163953Srrs return; 3883163953Srrs } 3884163953Srrs liste->tsn = tsn; 3885163953Srrs liste->number_entries = number_entries; 3886240198Stuexen memcpy(&liste->list_of_streams, req->list_of_streams, number_entries * sizeof(uint16_t)); 3887163953Srrs TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp); 3888235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3889163953Srrs } 3890233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3891163953Srrs asoc->str_reset_seq_in++; 3892163953Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 3893163953Srrs /* 3894163953Srrs * one seq back, just echo back last action since my 3895163953Srrs * response was lost. 3896163953Srrs */ 3897163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3898163953Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 3899163953Srrs /* 3900163953Srrs * two seq back, just echo back last action since my 3901163953Srrs * response was lost. 3902163953Srrs */ 3903163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 3904163953Srrs } else { 3905235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3906163953Srrs } 3907163953Srrs} 3908163953Srrs 3909188854Srrsstatic void 3910188854Srrssctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 3911188854Srrs struct sctp_stream_reset_add_strm *str_add) 3912188854Srrs{ 3913188854Srrs /* 3914188854Srrs * Peer is requesting to add more streams. If its within our 3915188854Srrs * max-streams we will allow it. 3916188854Srrs */ 3917233660Srrs uint32_t num_stream, i; 3918188854Srrs uint32_t seq; 3919189121Srrs struct sctp_association *asoc = &stcb->asoc; 3920216822Stuexen struct sctp_queued_to_read *ctl, *nctl; 3921188854Srrs 3922188854Srrs /* Get the number. */ 3923188854Srrs seq = ntohl(str_add->request_seq); 3924188854Srrs num_stream = ntohs(str_add->number_of_streams); 3925188854Srrs /* Now what would be the new total? */ 3926189121Srrs if (asoc->str_reset_seq_in == seq) { 3927189121Srrs num_stream += stcb->asoc.streamincnt; 3928235064Stuexen stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 3929235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 3930235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3931235064Stuexen } else if ((num_stream > stcb->asoc.max_inbound_streams) || 3932233660Srrs (num_stream > 0xffff)) { 3933189121Srrs /* We must reject it they ask for to many */ 3934189121Srrs denied: 3935235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3936189121Srrs } else { 3937189121Srrs /* Ok, we can do that :-) */ 3938189121Srrs struct sctp_stream_in *oldstrm; 3939189121Srrs 3940189121Srrs /* save off the old */ 3941189121Srrs oldstrm = stcb->asoc.strmin; 3942189121Srrs SCTP_MALLOC(stcb->asoc.strmin, struct sctp_stream_in *, 3943189121Srrs (num_stream * sizeof(struct sctp_stream_in)), 3944189121Srrs SCTP_M_STRMI); 3945189121Srrs if (stcb->asoc.strmin == NULL) { 3946189121Srrs stcb->asoc.strmin = oldstrm; 3947189121Srrs goto denied; 3948189121Srrs } 3949189121Srrs /* copy off the old data */ 3950189121Srrs for (i = 0; i < stcb->asoc.streamincnt; i++) { 3951189121Srrs TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 3952189121Srrs stcb->asoc.strmin[i].stream_no = i; 3953189121Srrs stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered; 3954189121Srrs stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started; 3955189121Srrs /* now anything on those queues? */ 3956216822Stuexen TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next, nctl) { 3957189121Srrs TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next); 3958189121Srrs TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next); 3959189121Srrs } 3960189121Srrs } 3961189121Srrs /* Init the new streams */ 3962189121Srrs for (i = stcb->asoc.streamincnt; i < num_stream; i++) { 3963189121Srrs TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 3964189121Srrs stcb->asoc.strmin[i].stream_no = i; 3965189121Srrs stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 3966189121Srrs stcb->asoc.strmin[i].delivery_started = 0; 3967189121Srrs } 3968189121Srrs SCTP_FREE(oldstrm, SCTP_M_STRMI); 3969189121Srrs /* update the size */ 3970189121Srrs stcb->asoc.streamincnt = num_stream; 3971235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3972233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 3973189121Srrs } 3974233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3975233660Srrs asoc->str_reset_seq_in++; 3976189121Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 3977189121Srrs /* 3978189121Srrs * one seq back, just echo back last action since my 3979189121Srrs * response was lost. 3980189121Srrs */ 3981189121Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3982189121Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 3983189121Srrs /* 3984189121Srrs * two seq back, just echo back last action since my 3985189121Srrs * response was lost. 3986189121Srrs */ 3987189121Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 3988188854Srrs } else { 3989235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3990188854Srrs 3991188854Srrs } 3992188854Srrs} 3993188854Srrs 3994233660Srrsstatic void 3995233660Srrssctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 3996233660Srrs struct sctp_stream_reset_add_strm *str_add) 3997233660Srrs{ 3998233660Srrs /* 3999233660Srrs * Peer is requesting to add more streams. If its within our 4000233660Srrs * max-streams we will allow it. 4001233660Srrs */ 4002233660Srrs uint16_t num_stream; 4003233660Srrs uint32_t seq; 4004233660Srrs struct sctp_association *asoc = &stcb->asoc; 4005233660Srrs 4006233660Srrs /* Get the number. */ 4007233660Srrs seq = ntohl(str_add->request_seq); 4008233660Srrs num_stream = ntohs(str_add->number_of_streams); 4009233660Srrs /* Now what would be the new total? */ 4010233660Srrs if (asoc->str_reset_seq_in == seq) { 4011235064Stuexen stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 4012235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 4013235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4014235064Stuexen } else if (stcb->asoc.stream_reset_outstanding) { 4015233660Srrs /* We must reject it we have something pending */ 4016235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 4017233660Srrs } else { 4018233660Srrs /* Ok, we can do that :-) */ 4019233660Srrs int mychk; 4020233660Srrs 4021233660Srrs mychk = stcb->asoc.streamoutcnt; 4022233660Srrs mychk += num_stream; 4023233660Srrs if (mychk < 0x10000) { 4024235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 4025233660Srrs if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, 1, num_stream, 0, 1)) { 4026235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4027233660Srrs } 4028233660Srrs } else { 4029235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4030233660Srrs } 4031233660Srrs } 4032233660Srrs sctp_add_stream_reset_result(chk, seq, stcb->asoc.last_reset_action[0]); 4033233660Srrs asoc->str_reset_seq_in++; 4034233660Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 4035233660Srrs /* 4036233660Srrs * one seq back, just echo back last action since my 4037233660Srrs * response was lost. 4038233660Srrs */ 4039233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 4040233660Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 4041233660Srrs /* 4042233660Srrs * two seq back, just echo back last action since my 4043233660Srrs * response was lost. 4044233660Srrs */ 4045233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 4046233660Srrs } else { 4047235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 4048233660Srrs } 4049233660Srrs} 4050233660Srrs 4051170992Srrs#ifdef __GNUC__ 4052170992Srrs__attribute__((noinline)) 4053170992Srrs#endif 4054170992Srrs static int 4055170992Srrs sctp_handle_stream_reset(struct sctp_tcb *stcb, struct mbuf *m, int offset, 4056240198Stuexen struct sctp_chunkhdr *ch_req) 4057163953Srrs{ 4058277808Sdelphij uint16_t remaining_length, param_len, ptype; 4059170992Srrs struct sctp_paramhdr pstore; 4060170992Srrs uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE]; 4061233660Srrs uint32_t seq = 0; 4062163953Srrs int num_req = 0; 4063170992Srrs int trunc = 0; 4064163953Srrs struct sctp_tmit_chunk *chk; 4065163953Srrs struct sctp_chunkhdr *ch; 4066163953Srrs struct sctp_paramhdr *ph; 4067166675Srrs int ret_code = 0; 4068166675Srrs int num_param = 0; 4069163953Srrs 4070163953Srrs /* now it may be a reset or a reset-response */ 4071277808Sdelphij remaining_length = ntohs(ch_req->chunk_length) - sizeof(struct sctp_chunkhdr); 4072163953Srrs 4073163953Srrs /* setup for adding the response */ 4074163953Srrs sctp_alloc_a_chunk(stcb, chk); 4075163953Srrs if (chk == NULL) { 4076163953Srrs return (ret_code); 4077163953Srrs } 4078273106Stuexen chk->copy_by_ref = 0; 4079163953Srrs chk->rec.chunk_id.id = SCTP_STREAM_RESET; 4080169208Srrs chk->rec.chunk_id.can_take_data = 0; 4081273106Stuexen chk->flags = 0; 4082163953Srrs chk->asoc = &stcb->asoc; 4083163953Srrs chk->no_fr_allowed = 0; 4084163953Srrs chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr); 4085166023Srrs chk->book_size_scale = 0; 4086243882Sglebius chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); 4087163953Srrs if (chk->data == NULL) { 4088163953Srrsstrres_nochunk: 4089163953Srrs if (chk->data) { 4090163953Srrs sctp_m_freem(chk->data); 4091163953Srrs chk->data = NULL; 4092163953Srrs } 4093221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 4094163953Srrs return (ret_code); 4095163953Srrs } 4096165647Srrs SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); 4097163953Srrs 4098163953Srrs /* setup chunk parameters */ 4099163953Srrs chk->sent = SCTP_DATAGRAM_UNSENT; 4100163953Srrs chk->snd_count = 0; 4101224641Stuexen chk->whoTo = NULL; 4102163953Srrs 4103163953Srrs ch = mtod(chk->data, struct sctp_chunkhdr *); 4104163953Srrs ch->chunk_type = SCTP_STREAM_RESET; 4105163953Srrs ch->chunk_flags = 0; 4106163953Srrs ch->chunk_length = htons(chk->send_size); 4107165647Srrs SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size); 4108170992Srrs offset += sizeof(struct sctp_chunkhdr); 4109277808Sdelphij while (remaining_length >= sizeof(struct sctp_paramhdr)) { 4110170992Srrs ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(pstore), (uint8_t *) & pstore); 4111277808Sdelphij if (ph == NULL) { 4112277808Sdelphij /* TSNH */ 4113170992Srrs break; 4114277808Sdelphij } 4115163953Srrs param_len = ntohs(ph->param_length); 4116277808Sdelphij if ((param_len > remaining_length) || 4117277808Sdelphij (param_len < (sizeof(struct sctp_paramhdr) + sizeof(uint32_t)))) { 4118277808Sdelphij /* bad parameter length */ 4119163953Srrs break; 4120163953Srrs } 4121277808Sdelphij ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, sizeof(cstore)), 4122170992Srrs (uint8_t *) & cstore); 4123277808Sdelphij if (ph == NULL) { 4124277808Sdelphij /* TSNH */ 4125277808Sdelphij break; 4126277808Sdelphij } 4127163953Srrs ptype = ntohs(ph->param_type); 4128163953Srrs num_param++; 4129277808Sdelphij if (param_len > sizeof(cstore)) { 4130170992Srrs trunc = 1; 4131170992Srrs } else { 4132170992Srrs trunc = 0; 4133170992Srrs } 4134163953Srrs if (num_param > SCTP_MAX_RESET_PARAMS) { 4135163953Srrs /* hit the max of parameters already sorry.. */ 4136163953Srrs break; 4137163953Srrs } 4138163953Srrs if (ptype == SCTP_STR_RESET_OUT_REQUEST) { 4139163953Srrs struct sctp_stream_reset_out_request *req_out; 4140163953Srrs 4141277808Sdelphij if (param_len < sizeof(struct sctp_stream_reset_out_request)) { 4142277808Sdelphij break; 4143277808Sdelphij } 4144163953Srrs req_out = (struct sctp_stream_reset_out_request *)ph; 4145163953Srrs num_req++; 4146163953Srrs if (stcb->asoc.stream_reset_outstanding) { 4147163953Srrs seq = ntohl(req_out->response_seq); 4148163953Srrs if (seq == stcb->asoc.str_reset_seq_out) { 4149163953Srrs /* implicit ack */ 4150235064Stuexen (void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_RESULT_PERFORMED, NULL); 4151163953Srrs } 4152163953Srrs } 4153170992Srrs sctp_handle_str_reset_request_out(stcb, chk, req_out, trunc); 4154233660Srrs } else if (ptype == SCTP_STR_RESET_ADD_OUT_STREAMS) { 4155188854Srrs struct sctp_stream_reset_add_strm *str_add; 4156188854Srrs 4157277808Sdelphij if (param_len < sizeof(struct sctp_stream_reset_add_strm)) { 4158277808Sdelphij break; 4159277808Sdelphij } 4160188854Srrs str_add = (struct sctp_stream_reset_add_strm *)ph; 4161188854Srrs num_req++; 4162188854Srrs sctp_handle_str_reset_add_strm(stcb, chk, str_add); 4163233660Srrs } else if (ptype == SCTP_STR_RESET_ADD_IN_STREAMS) { 4164233660Srrs struct sctp_stream_reset_add_strm *str_add; 4165233660Srrs 4166277808Sdelphij if (param_len < sizeof(struct sctp_stream_reset_add_strm)) { 4167277808Sdelphij break; 4168277808Sdelphij } 4169233660Srrs str_add = (struct sctp_stream_reset_add_strm *)ph; 4170233660Srrs num_req++; 4171233660Srrs sctp_handle_str_reset_add_out_strm(stcb, chk, str_add); 4172163953Srrs } else if (ptype == SCTP_STR_RESET_IN_REQUEST) { 4173163953Srrs struct sctp_stream_reset_in_request *req_in; 4174163953Srrs 4175163953Srrs num_req++; 4176163953Srrs req_in = (struct sctp_stream_reset_in_request *)ph; 4177170992Srrs sctp_handle_str_reset_request_in(stcb, chk, req_in, trunc); 4178163953Srrs } else if (ptype == SCTP_STR_RESET_TSN_REQUEST) { 4179163953Srrs struct sctp_stream_reset_tsn_request *req_tsn; 4180163953Srrs 4181163953Srrs num_req++; 4182163953Srrs req_tsn = (struct sctp_stream_reset_tsn_request *)ph; 4183163953Srrs if (sctp_handle_str_reset_request_tsn(stcb, chk, req_tsn)) { 4184163953Srrs ret_code = 1; 4185163953Srrs goto strres_nochunk; 4186163953Srrs } 4187163953Srrs /* no more */ 4188163953Srrs break; 4189163953Srrs } else if (ptype == SCTP_STR_RESET_RESPONSE) { 4190163953Srrs struct sctp_stream_reset_response *resp; 4191163953Srrs uint32_t result; 4192163953Srrs 4193277808Sdelphij if (param_len < sizeof(struct sctp_stream_reset_response)) { 4194277808Sdelphij break; 4195277808Sdelphij } 4196163953Srrs resp = (struct sctp_stream_reset_response *)ph; 4197163953Srrs seq = ntohl(resp->response_seq); 4198163953Srrs result = ntohl(resp->result); 4199163953Srrs if (sctp_handle_stream_reset_response(stcb, seq, result, resp)) { 4200163953Srrs ret_code = 1; 4201163953Srrs goto strres_nochunk; 4202163953Srrs } 4203163953Srrs } else { 4204163953Srrs break; 4205163953Srrs } 4206170992Srrs offset += SCTP_SIZE32(param_len); 4207277808Sdelphij if (remaining_length >= SCTP_SIZE32(param_len)) { 4208277808Sdelphij remaining_length -= SCTP_SIZE32(param_len); 4209277808Sdelphij } else { 4210277808Sdelphij remaining_length = 0; 4211277808Sdelphij } 4212163953Srrs } 4213163953Srrs if (num_req == 0) { 4214163953Srrs /* we have no response free the stuff */ 4215163953Srrs goto strres_nochunk; 4216163953Srrs } 4217163953Srrs /* ok we have a chunk to link in */ 4218163953Srrs TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue, 4219163953Srrs chk, 4220163953Srrs sctp_next); 4221163953Srrs stcb->asoc.ctrl_queue_cnt++; 4222163953Srrs return (ret_code); 4223163953Srrs} 4224163953Srrs 4225163953Srrs/* 4226163953Srrs * Handle a router or endpoints report of a packet loss, there are two ways 4227163953Srrs * to handle this, either we get the whole packet and must disect it 4228163953Srrs * ourselves (possibly with truncation and or corruption) or it is a summary 4229163953Srrs * from a middle box that did the disectting for us. 4230163953Srrs */ 4231163953Srrsstatic void 4232163953Srrssctp_handle_packet_dropped(struct sctp_pktdrop_chunk *cp, 4233170781Srrs struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t limit) 4234163953Srrs{ 4235163953Srrs uint32_t bottle_bw, on_queue; 4236163953Srrs uint16_t trunc_len; 4237163953Srrs unsigned int chlen; 4238163953Srrs unsigned int at; 4239163953Srrs struct sctp_chunk_desc desc; 4240163953Srrs struct sctp_chunkhdr *ch; 4241163953Srrs 4242163953Srrs chlen = ntohs(cp->ch.chunk_length); 4243163953Srrs chlen -= sizeof(struct sctp_pktdrop_chunk); 4244163953Srrs /* XXX possible chlen underflow */ 4245163953Srrs if (chlen == 0) { 4246163953Srrs ch = NULL; 4247163953Srrs if (cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) 4248163953Srrs SCTP_STAT_INCR(sctps_pdrpbwrpt); 4249163953Srrs } else { 4250163953Srrs ch = (struct sctp_chunkhdr *)(cp->data + sizeof(struct sctphdr)); 4251163953Srrs chlen -= sizeof(struct sctphdr); 4252163953Srrs /* XXX possible chlen underflow */ 4253163953Srrs memset(&desc, 0, sizeof(desc)); 4254163953Srrs } 4255163953Srrs trunc_len = (uint16_t) ntohs(cp->trunc_len); 4256170781Srrs if (trunc_len > limit) { 4257170781Srrs trunc_len = limit; 4258170781Srrs } 4259163953Srrs /* now the chunks themselves */ 4260163953Srrs while ((ch != NULL) && (chlen >= sizeof(struct sctp_chunkhdr))) { 4261163953Srrs desc.chunk_type = ch->chunk_type; 4262163953Srrs /* get amount we need to move */ 4263163953Srrs at = ntohs(ch->chunk_length); 4264163953Srrs if (at < sizeof(struct sctp_chunkhdr)) { 4265163953Srrs /* corrupt chunk, maybe at the end? */ 4266163953Srrs SCTP_STAT_INCR(sctps_pdrpcrupt); 4267163953Srrs break; 4268163953Srrs } 4269163953Srrs if (trunc_len == 0) { 4270163953Srrs /* we are supposed to have all of it */ 4271163953Srrs if (at > chlen) { 4272163953Srrs /* corrupt skip it */ 4273163953Srrs SCTP_STAT_INCR(sctps_pdrpcrupt); 4274163953Srrs break; 4275163953Srrs } 4276163953Srrs } else { 4277163953Srrs /* is there enough of it left ? */ 4278163953Srrs if (desc.chunk_type == SCTP_DATA) { 4279163953Srrs if (chlen < (sizeof(struct sctp_data_chunk) + 4280163953Srrs sizeof(desc.data_bytes))) { 4281163953Srrs break; 4282163953Srrs } 4283163953Srrs } else { 4284163953Srrs if (chlen < sizeof(struct sctp_chunkhdr)) { 4285163953Srrs break; 4286163953Srrs } 4287163953Srrs } 4288163953Srrs } 4289163953Srrs if (desc.chunk_type == SCTP_DATA) { 4290163953Srrs /* can we get out the tsn? */ 4291163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 4292163953Srrs SCTP_STAT_INCR(sctps_pdrpmbda); 4293163953Srrs 4294163953Srrs if (chlen >= (sizeof(struct sctp_data_chunk) + sizeof(uint32_t))) { 4295163953Srrs /* yep */ 4296163953Srrs struct sctp_data_chunk *dcp; 4297163953Srrs uint8_t *ddp; 4298163953Srrs unsigned int iii; 4299163953Srrs 4300163953Srrs dcp = (struct sctp_data_chunk *)ch; 4301163953Srrs ddp = (uint8_t *) (dcp + 1); 4302163953Srrs for (iii = 0; iii < sizeof(desc.data_bytes); iii++) { 4303163953Srrs desc.data_bytes[iii] = ddp[iii]; 4304163953Srrs } 4305163953Srrs desc.tsn_ifany = dcp->dp.tsn; 4306163953Srrs } else { 4307163953Srrs /* nope we are done. */ 4308163953Srrs SCTP_STAT_INCR(sctps_pdrpnedat); 4309163953Srrs break; 4310163953Srrs } 4311163953Srrs } else { 4312163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 4313163953Srrs SCTP_STAT_INCR(sctps_pdrpmbct); 4314163953Srrs } 4315163953Srrs 4316163953Srrs if (process_chunk_drop(stcb, &desc, net, cp->ch.chunk_flags)) { 4317163953Srrs SCTP_STAT_INCR(sctps_pdrppdbrk); 4318163953Srrs break; 4319163953Srrs } 4320163953Srrs if (SCTP_SIZE32(at) > chlen) { 4321163953Srrs break; 4322163953Srrs } 4323163953Srrs chlen -= SCTP_SIZE32(at); 4324163953Srrs if (chlen < sizeof(struct sctp_chunkhdr)) { 4325163953Srrs /* done, none left */ 4326163953Srrs break; 4327163953Srrs } 4328163953Srrs ch = (struct sctp_chunkhdr *)((caddr_t)ch + SCTP_SIZE32(at)); 4329163953Srrs } 4330163953Srrs /* Now update any rwnd --- possibly */ 4331163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) == 0) { 4332163953Srrs /* From a peer, we get a rwnd report */ 4333163953Srrs uint32_t a_rwnd; 4334163953Srrs 4335163953Srrs SCTP_STAT_INCR(sctps_pdrpfehos); 4336163953Srrs 4337163953Srrs bottle_bw = ntohl(cp->bottle_bw); 4338163953Srrs on_queue = ntohl(cp->current_onq); 4339163953Srrs if (bottle_bw && on_queue) { 4340163953Srrs /* a rwnd report is in here */ 4341163953Srrs if (bottle_bw > on_queue) 4342163953Srrs a_rwnd = bottle_bw - on_queue; 4343163953Srrs else 4344163953Srrs a_rwnd = 0; 4345163953Srrs 4346163953Srrs if (a_rwnd == 0) 4347163953Srrs stcb->asoc.peers_rwnd = 0; 4348163953Srrs else { 4349163953Srrs if (a_rwnd > stcb->asoc.total_flight) { 4350163953Srrs stcb->asoc.peers_rwnd = 4351163953Srrs a_rwnd - stcb->asoc.total_flight; 4352163953Srrs } else { 4353163953Srrs stcb->asoc.peers_rwnd = 0; 4354163953Srrs } 4355163953Srrs if (stcb->asoc.peers_rwnd < 4356163953Srrs stcb->sctp_ep->sctp_ep.sctp_sws_sender) { 4357163953Srrs /* SWS sender side engages */ 4358163953Srrs stcb->asoc.peers_rwnd = 0; 4359163953Srrs } 4360163953Srrs } 4361163953Srrs } 4362163953Srrs } else { 4363163953Srrs SCTP_STAT_INCR(sctps_pdrpfmbox); 4364163953Srrs } 4365163953Srrs 4366163953Srrs /* now middle boxes in sat networks get a cwnd bump */ 4367163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) && 4368163953Srrs (stcb->asoc.sat_t3_loss_recovery == 0) && 4369163953Srrs (stcb->asoc.sat_network)) { 4370163953Srrs /* 4371163953Srrs * This is debateable but for sat networks it makes sense 4372163953Srrs * Note if a T3 timer has went off, we will prohibit any 4373163953Srrs * changes to cwnd until we exit the t3 loss recovery. 4374163953Srrs */ 4375171440Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped(stcb, 4376171440Srrs net, cp, &bottle_bw, &on_queue); 4377163953Srrs } 4378163953Srrs} 4379163953Srrs 4380163953Srrs/* 4381163953Srrs * handles all control chunks in a packet inputs: - m: mbuf chain, assumed to 4382163953Srrs * still contain IP/SCTP header - stcb: is the tcb found for this packet - 4383163953Srrs * offset: offset into the mbuf chain to first chunkhdr - length: is the 4384163953Srrs * length of the complete packet outputs: - length: modified to remaining 4385163953Srrs * length after control processing - netp: modified to new sctp_nets after 4386163953Srrs * cookie-echo processing - return NULL to discard the packet (ie. no asoc, 4387163953Srrs * bad packet,...) otherwise return the tcb for this packet 4388163953Srrs */ 4389170099Srrs#ifdef __GNUC__ 4390170099Srrs__attribute__((noinline)) 4391170099Srrs#endif 4392170099Srrs static struct sctp_tcb * 4393170099Srrs sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, 4394237715Stuexen struct sockaddr *src, struct sockaddr *dst, 4395170099Srrs struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp, 4396170099Srrs struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen, 4397237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 4398179157Srrs uint32_t vrf_id, uint16_t port) 4399163953Srrs{ 4400163953Srrs struct sctp_association *asoc; 4401267723Stuexen struct mbuf *op_err; 4402267723Stuexen char msg[SCTP_DIAG_INFO_LEN]; 4403163953Srrs uint32_t vtag_in; 4404163953Srrs int num_chunks = 0; /* number of control chunks processed */ 4405170140Srrs uint32_t chk_length; 4406163953Srrs int ret; 4407168299Srrs int abort_no_unlock = 0; 4408218186Srrs int ecne_seen = 0; 4409163953Srrs 4410163953Srrs /* 4411163953Srrs * How big should this be, and should it be alloc'd? Lets try the 4412163953Srrs * d-mtu-ceiling for now (2k) and that should hopefully work ... 4413163953Srrs * until we get into jumbo grams and such.. 4414163953Srrs */ 4415166675Srrs uint8_t chunk_buf[SCTP_CHUNK_BUFFER_SIZE]; 4416163953Srrs struct sctp_tcb *locked_tcb = stcb; 4417163953Srrs int got_auth = 0; 4418163953Srrs uint32_t auth_offset = 0, auth_len = 0; 4419163953Srrs int auth_skipped = 0; 4420171990Srrs int asconf_cnt = 0; 4421163953Srrs 4422237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4423172090Srrs struct socket *so; 4424172090Srrs 4425172090Srrs#endif 4426172090Srrs 4427169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n", 4428240148Stuexen iphlen, *offset, length, (void *)stcb); 4429163953Srrs 4430163953Srrs /* validate chunk header length... */ 4431163953Srrs if (ntohs(ch->chunk_length) < sizeof(*ch)) { 4432170056Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Invalid header length %d\n", 4433170056Srrs ntohs(ch->chunk_length)); 4434170091Srrs if (locked_tcb) { 4435170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4436170091Srrs } 4437163953Srrs return (NULL); 4438163953Srrs } 4439163953Srrs /* 4440163953Srrs * validate the verification tag 4441163953Srrs */ 4442163953Srrs vtag_in = ntohl(sh->v_tag); 4443163953Srrs 4444165220Srrs if (locked_tcb) { 4445165220Srrs SCTP_TCB_LOCK_ASSERT(locked_tcb); 4446165220Srrs } 4447163953Srrs if (ch->chunk_type == SCTP_INITIATION) { 4448170056Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Its an INIT of len:%d vtag:%x\n", 4449170056Srrs ntohs(ch->chunk_length), vtag_in); 4450163953Srrs if (vtag_in != 0) { 4451163953Srrs /* protocol error- silently discard... */ 4452163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4453169378Srrs if (locked_tcb) { 4454163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4455169378Srrs } 4456163953Srrs return (NULL); 4457163953Srrs } 4458163953Srrs } else if (ch->chunk_type != SCTP_COOKIE_ECHO) { 4459163953Srrs /* 4460163953Srrs * If there is no stcb, skip the AUTH chunk and process 4461163953Srrs * later after a stcb is found (to validate the lookup was 4462163953Srrs * valid. 4463163953Srrs */ 4464163953Srrs if ((ch->chunk_type == SCTP_AUTHENTICATION) && 4465179783Srrs (stcb == NULL) && 4466270362Stuexen (inp->auth_supported == 1)) { 4467163953Srrs /* save this chunk for later processing */ 4468163953Srrs auth_skipped = 1; 4469163953Srrs auth_offset = *offset; 4470163953Srrs auth_len = ntohs(ch->chunk_length); 4471163953Srrs 4472163953Srrs /* (temporarily) move past this chunk */ 4473163953Srrs *offset += SCTP_SIZE32(auth_len); 4474163953Srrs if (*offset >= length) { 4475163953Srrs /* no more data left in the mbuf chain */ 4476163953Srrs *offset = length; 4477170091Srrs if (locked_tcb) { 4478170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4479170091Srrs } 4480163953Srrs return (NULL); 4481163953Srrs } 4482163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4483163953Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 4484163953Srrs } 4485169420Srrs if (ch == NULL) { 4486169420Srrs /* Help */ 4487169420Srrs *offset = length; 4488170091Srrs if (locked_tcb) { 4489170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4490170091Srrs } 4491169420Srrs return (NULL); 4492169420Srrs } 4493163953Srrs if (ch->chunk_type == SCTP_COOKIE_ECHO) { 4494163953Srrs goto process_control_chunks; 4495163953Srrs } 4496163953Srrs /* 4497163953Srrs * first check if it's an ASCONF with an unknown src addr we 4498163953Srrs * need to look inside to find the association 4499163953Srrs */ 4500163953Srrs if (ch->chunk_type == SCTP_ASCONF && stcb == NULL) { 4501171990Srrs struct sctp_chunkhdr *asconf_ch = ch; 4502171990Srrs uint32_t asconf_offset = 0, asconf_len = 0; 4503171990Srrs 4504163953Srrs /* inp's refcount may be reduced */ 4505163953Srrs SCTP_INP_INCR_REF(inp); 4506163953Srrs 4507171990Srrs asconf_offset = *offset; 4508171990Srrs do { 4509171990Srrs asconf_len = ntohs(asconf_ch->chunk_length); 4510171990Srrs if (asconf_len < sizeof(struct sctp_asconf_paramhdr)) 4511171990Srrs break; 4512228653Stuexen stcb = sctp_findassociation_ep_asconf(m, 4513237715Stuexen *offset, 4514237715Stuexen dst, 4515237715Stuexen sh, &inp, netp, vrf_id); 4516171990Srrs if (stcb != NULL) 4517171990Srrs break; 4518171990Srrs asconf_offset += SCTP_SIZE32(asconf_len); 4519171990Srrs asconf_ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, asconf_offset, 4520171990Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 4521171990Srrs } while (asconf_ch != NULL && asconf_ch->chunk_type == SCTP_ASCONF); 4522163953Srrs if (stcb == NULL) { 4523163953Srrs /* 4524163953Srrs * reduce inp's refcount if not reduced in 4525163953Srrs * sctp_findassociation_ep_asconf(). 4526163953Srrs */ 4527163953Srrs SCTP_INP_DECR_REF(inp); 4528171990Srrs } else { 4529171990Srrs locked_tcb = stcb; 4530163953Srrs } 4531171990Srrs 4532163953Srrs /* now go back and verify any auth chunk to be sure */ 4533163953Srrs if (auth_skipped && (stcb != NULL)) { 4534163953Srrs struct sctp_auth_chunk *auth; 4535163953Srrs 4536163953Srrs auth = (struct sctp_auth_chunk *) 4537163953Srrs sctp_m_getptr(m, auth_offset, 4538163953Srrs auth_len, chunk_buf); 4539163953Srrs got_auth = 1; 4540163953Srrs auth_skipped = 0; 4541169420Srrs if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, 4542163953Srrs auth_offset)) { 4543163953Srrs /* auth HMAC failed so dump it */ 4544163953Srrs *offset = length; 4545170091Srrs if (locked_tcb) { 4546170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4547170091Srrs } 4548163953Srrs return (NULL); 4549163953Srrs } else { 4550163953Srrs /* remaining chunks are HMAC checked */ 4551163953Srrs stcb->asoc.authenticated = 1; 4552163953Srrs } 4553163953Srrs } 4554163953Srrs } 4555163953Srrs if (stcb == NULL) { 4556267723Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 4557267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 4558267723Stuexen msg); 4559163953Srrs /* no association, so it's out of the blue... */ 4560267723Stuexen sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err, 4561237049Stuexen use_mflowid, mflowid, 4562179157Srrs vrf_id, port); 4563163953Srrs *offset = length; 4564169378Srrs if (locked_tcb) { 4565163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4566169378Srrs } 4567163953Srrs return (NULL); 4568163953Srrs } 4569163953Srrs asoc = &stcb->asoc; 4570163953Srrs /* ABORT and SHUTDOWN can use either v_tag... */ 4571163953Srrs if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) || 4572163953Srrs (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) || 4573163953Srrs (ch->chunk_type == SCTP_PACKET_DROPPED)) { 4574252718Stuexen /* Take the T-bit always into account. */ 4575252718Stuexen if ((((ch->chunk_flags & SCTP_HAD_NO_TCB) == 0) && 4576252718Stuexen (vtag_in == asoc->my_vtag)) || 4577252718Stuexen (((ch->chunk_flags & SCTP_HAD_NO_TCB) == SCTP_HAD_NO_TCB) && 4578163953Srrs (vtag_in == asoc->peer_vtag))) { 4579163953Srrs /* this is valid */ 4580163953Srrs } else { 4581163953Srrs /* drop this packet... */ 4582163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4583169378Srrs if (locked_tcb) { 4584163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4585169378Srrs } 4586163953Srrs return (NULL); 4587163953Srrs } 4588163953Srrs } else if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 4589163953Srrs if (vtag_in != asoc->my_vtag) { 4590163953Srrs /* 4591163953Srrs * this could be a stale SHUTDOWN-ACK or the 4592163953Srrs * peer never got the SHUTDOWN-COMPLETE and 4593163953Srrs * is still hung; we have started a new asoc 4594163953Srrs * but it won't complete until the shutdown 4595163953Srrs * is completed 4596163953Srrs */ 4597169378Srrs if (locked_tcb) { 4598163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4599169378Srrs } 4600267723Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 4601267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 4602267723Stuexen msg); 4603237715Stuexen sctp_handle_ootb(m, iphlen, *offset, src, dst, 4604267723Stuexen sh, inp, op_err, 4605237049Stuexen use_mflowid, mflowid, 4606236450Stuexen vrf_id, port); 4607163953Srrs return (NULL); 4608163953Srrs } 4609163953Srrs } else { 4610163953Srrs /* for all other chunks, vtag must match */ 4611163953Srrs if (vtag_in != asoc->my_vtag) { 4612163953Srrs /* invalid vtag... */ 4613169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 4614169420Srrs "invalid vtag: %xh, expect %xh\n", 4615169420Srrs vtag_in, asoc->my_vtag); 4616163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4617169378Srrs if (locked_tcb) { 4618163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4619169378Srrs } 4620163953Srrs *offset = length; 4621163953Srrs return (NULL); 4622163953Srrs } 4623163953Srrs } 4624163953Srrs } /* end if !SCTP_COOKIE_ECHO */ 4625163953Srrs /* 4626163953Srrs * process all control chunks... 4627163953Srrs */ 4628163953Srrs if (((ch->chunk_type == SCTP_SELECTIVE_ACK) || 4629185694Srrs (ch->chunk_type == SCTP_NR_SELECTIVE_ACK) || 4630163953Srrs (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) && 4631163953Srrs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { 4632163953Srrs /* implied cookie-ack.. we must have lost the ack */ 4633179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 4634171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 4635171943Srrs stcb->asoc.overall_error_count, 4636171943Srrs 0, 4637171943Srrs SCTP_FROM_SCTP_INPUT, 4638171943Srrs __LINE__); 4639171943Srrs } 4640163953Srrs stcb->asoc.overall_error_count = 0; 4641163953Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, 4642163953Srrs *netp); 4643163953Srrs } 4644163953Srrsprocess_control_chunks: 4645163953Srrs while (IS_SCTP_CONTROL(ch)) { 4646163953Srrs /* validate chunk length */ 4647163953Srrs chk_length = ntohs(ch->chunk_length); 4648169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_process_control: processing a chunk type=%u, len=%u\n", 4649169420Srrs ch->chunk_type, chk_length); 4650170744Srrs SCTP_LTRACE_CHK(inp, stcb, ch->chunk_type, chk_length); 4651170140Srrs if (chk_length < sizeof(*ch) || 4652170140Srrs (*offset + (int)chk_length) > length) { 4653163953Srrs *offset = length; 4654169378Srrs if (locked_tcb) { 4655163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4656169378Srrs } 4657163953Srrs return (NULL); 4658163953Srrs } 4659163953Srrs SCTP_STAT_INCR_COUNTER64(sctps_incontrolchunks); 4660163953Srrs /* 4661163953Srrs * INIT-ACK only gets the init ack "header" portion only 4662163953Srrs * because we don't have to process the peer's COOKIE. All 4663163953Srrs * others get a complete chunk. 4664163953Srrs */ 4665169208Srrs if ((ch->chunk_type == SCTP_INITIATION_ACK) || 4666169208Srrs (ch->chunk_type == SCTP_INITIATION)) { 4667163953Srrs /* get an init-ack chunk */ 4668163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4669163953Srrs sizeof(struct sctp_init_ack_chunk), chunk_buf); 4670163953Srrs if (ch == NULL) { 4671163953Srrs *offset = length; 4672169378Srrs if (locked_tcb) { 4673163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4674169378Srrs } 4675163953Srrs return (NULL); 4676163953Srrs } 4677170642Srrs } else { 4678170786Srrs /* For cookies and all other chunks. */ 4679169208Srrs if (chk_length > sizeof(chunk_buf)) { 4680169208Srrs /* 4681169208Srrs * use just the size of the chunk buffer so 4682170642Srrs * the front part of our chunks fit in 4683170642Srrs * contiguous space up to the chunk buffer 4684170642Srrs * size (508 bytes). For chunks that need to 4685170786Srrs * get more than that they must use the 4686170642Srrs * sctp_m_getptr() function or other means 4687170786Srrs * (e.g. know how to parse mbuf chains). 4688170786Srrs * Cookies do this already. 4689169208Srrs */ 4690169208Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4691169208Srrs (sizeof(chunk_buf) - 4), 4692169208Srrs chunk_buf); 4693169208Srrs if (ch == NULL) { 4694169208Srrs *offset = length; 4695169378Srrs if (locked_tcb) { 4696169208Srrs SCTP_TCB_UNLOCK(locked_tcb); 4697169378Srrs } 4698169208Srrs return (NULL); 4699169208Srrs } 4700169208Srrs } else { 4701169208Srrs /* We can fit it all */ 4702170642Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4703170642Srrs chk_length, chunk_buf); 4704170642Srrs if (ch == NULL) { 4705170642Srrs SCTP_PRINTF("sctp_process_control: Can't get the all data....\n"); 4706170642Srrs *offset = length; 4707170642Srrs if (locked_tcb) { 4708170642Srrs SCTP_TCB_UNLOCK(locked_tcb); 4709169208Srrs } 4710170642Srrs return (NULL); 4711163953Srrs } 4712163953Srrs } 4713163953Srrs } 4714163953Srrs num_chunks++; 4715163953Srrs /* Save off the last place we got a control from */ 4716163953Srrs if (stcb != NULL) { 4717169420Srrs if (((netp != NULL) && (*netp != NULL)) || (ch->chunk_type == SCTP_ASCONF)) { 4718163953Srrs /* 4719163953Srrs * allow last_control to be NULL if 4720163953Srrs * ASCONF... ASCONF processing will find the 4721163953Srrs * right net later 4722163953Srrs */ 4723169420Srrs if ((netp != NULL) && (*netp != NULL)) 4724169420Srrs stcb->asoc.last_control_chunk_from = *netp; 4725163953Srrs } 4726163953Srrs } 4727163953Srrs#ifdef SCTP_AUDITING_ENABLED 4728163953Srrs sctp_audit_log(0xB0, ch->chunk_type); 4729163953Srrs#endif 4730163953Srrs 4731163953Srrs /* check to see if this chunk required auth, but isn't */ 4732179783Srrs if ((stcb != NULL) && 4733270362Stuexen (stcb->asoc.auth_supported == 1) && 4734179783Srrs sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) && 4735163953Srrs !stcb->asoc.authenticated) { 4736163953Srrs /* "silently" ignore */ 4737163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 4738163953Srrs goto next_chunk; 4739163953Srrs } 4740163953Srrs switch (ch->chunk_type) { 4741163953Srrs case SCTP_INITIATION: 4742169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT\n"); 4743229774Stuexen /* The INIT chunk must be the only chunk. */ 4744229774Stuexen if ((num_chunks > 1) || 4745229775Stuexen (length - *offset > (int)SCTP_SIZE32(chk_length))) { 4746267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 4747267723Stuexen "INIT not the only chunk"); 4748237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, 4749267723Stuexen src, dst, sh, op_err, 4750237049Stuexen use_mflowid, mflowid, 4751237049Stuexen vrf_id, port); 4752163953Srrs *offset = length; 4753163953Srrs return (NULL); 4754163953Srrs } 4755229774Stuexen /* Honor our resource limit. */ 4756229774Stuexen if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) { 4757267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 4758237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, 4759237715Stuexen src, dst, sh, op_err, 4760237049Stuexen use_mflowid, mflowid, 4761237049Stuexen vrf_id, port); 4762163953Srrs *offset = length; 4763163953Srrs return (NULL); 4764163953Srrs } 4765237715Stuexen sctp_handle_init(m, iphlen, *offset, src, dst, sh, 4766229774Stuexen (struct sctp_init_chunk *)ch, inp, 4767237049Stuexen stcb, &abort_no_unlock, 4768237049Stuexen use_mflowid, mflowid, 4769237049Stuexen vrf_id, port); 4770163953Srrs *offset = length; 4771229774Stuexen if ((!abort_no_unlock) && (locked_tcb)) { 4772163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4773169378Srrs } 4774163953Srrs return (NULL); 4775163953Srrs break; 4776170642Srrs case SCTP_PAD_CHUNK: 4777170642Srrs break; 4778163953Srrs case SCTP_INITIATION_ACK: 4779169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n"); 4780163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 4781163953Srrs /* We are not interested anymore */ 4782163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 4783163953Srrs ; 4784163953Srrs } else { 4785208876Srrs if (locked_tcb != stcb) { 4786208876Srrs /* Very unlikely */ 4787163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4788169378Srrs } 4789163953Srrs *offset = length; 4790163953Srrs if (stcb) { 4791237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4792172090Srrs so = SCTP_INP_SO(inp); 4793172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 4794172090Srrs SCTP_TCB_UNLOCK(stcb); 4795172090Srrs SCTP_SOCKET_LOCK(so, 1); 4796172090Srrs SCTP_TCB_LOCK(stcb); 4797172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 4798172090Srrs#endif 4799171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27); 4800237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4801172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4802172090Srrs#endif 4803163953Srrs } 4804163953Srrs return (NULL); 4805163953Srrs } 4806163953Srrs } 4807229775Stuexen /* The INIT-ACK chunk must be the only chunk. */ 4808163953Srrs if ((num_chunks > 1) || 4809229775Stuexen (length - *offset > (int)SCTP_SIZE32(chk_length))) { 4810163953Srrs *offset = length; 4811169378Srrs if (locked_tcb) { 4812163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4813169378Srrs } 4814163953Srrs return (NULL); 4815163953Srrs } 4816169420Srrs if ((netp) && (*netp)) { 4817237715Stuexen ret = sctp_handle_init_ack(m, iphlen, *offset, 4818237715Stuexen src, dst, sh, 4819237049Stuexen (struct sctp_init_ack_chunk *)ch, 4820237049Stuexen stcb, *netp, 4821237049Stuexen &abort_no_unlock, 4822237049Stuexen use_mflowid, mflowid, 4823237049Stuexen vrf_id); 4824169420Srrs } else { 4825169420Srrs ret = -1; 4826169420Srrs } 4827229774Stuexen *offset = length; 4828229774Stuexen if (abort_no_unlock) { 4829229774Stuexen return (NULL); 4830229774Stuexen } 4831163953Srrs /* 4832163953Srrs * Special case, I must call the output routine to 4833163953Srrs * get the cookie echoed 4834163953Srrs */ 4835229774Stuexen if ((stcb != NULL) && (ret == 0)) { 4836172090Srrs sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 4837229774Stuexen } 4838169378Srrs if (locked_tcb) { 4839163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4840169378Srrs } 4841163953Srrs return (NULL); 4842163953Srrs break; 4843163953Srrs case SCTP_SELECTIVE_ACK: 4844163953Srrs { 4845163953Srrs struct sctp_sack_chunk *sack; 4846163953Srrs int abort_now = 0; 4847163953Srrs uint32_t a_rwnd, cum_ack; 4848202526Stuexen uint16_t num_seg, num_dup; 4849202526Stuexen uint8_t flags; 4850202526Stuexen int offset_seg, offset_dup; 4851163953Srrs 4852211944Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n"); 4853211944Stuexen SCTP_STAT_INCR(sctps_recvsacks); 4854202526Stuexen if (stcb == NULL) { 4855202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing SACK chunk\n"); 4856202526Stuexen break; 4857169208Srrs } 4858202526Stuexen if (chk_length < sizeof(struct sctp_sack_chunk)) { 4859202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on SACK chunk, too small\n"); 4860202526Stuexen break; 4861202526Stuexen } 4862171990Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 4863171990Srrs /*- 4864171990Srrs * If we have sent a shutdown-ack, we will pay no 4865171990Srrs * attention to a sack sent in to us since 4866171990Srrs * we don't care anymore. 4867171990Srrs */ 4868184883Srrs break; 4869171990Srrs } 4870163953Srrs sack = (struct sctp_sack_chunk *)ch; 4871202526Stuexen flags = ch->chunk_flags; 4872163953Srrs cum_ack = ntohl(sack->sack.cum_tsn_ack); 4873163953Srrs num_seg = ntohs(sack->sack.num_gap_ack_blks); 4874202526Stuexen num_dup = ntohs(sack->sack.num_dup_tsns); 4875163953Srrs a_rwnd = (uint32_t) ntohl(sack->sack.a_rwnd); 4876202526Stuexen if (sizeof(struct sctp_sack_chunk) + 4877202526Stuexen num_seg * sizeof(struct sctp_gap_ack_block) + 4878202526Stuexen num_dup * sizeof(uint32_t) != chk_length) { 4879202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of SACK chunk\n"); 4880202526Stuexen break; 4881202526Stuexen } 4882202526Stuexen offset_seg = *offset + sizeof(struct sctp_sack_chunk); 4883202526Stuexen offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 4884170606Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 4885202526Stuexen cum_ack, num_seg, a_rwnd); 4886163953Srrs stcb->asoc.seen_a_sack_this_pkt = 1; 4887163953Srrs if ((stcb->asoc.pr_sctp_cnt == 0) && 4888163953Srrs (num_seg == 0) && 4889216825Stuexen SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 4890163953Srrs (stcb->asoc.saw_sack_with_frags == 0) && 4891216188Stuexen (stcb->asoc.saw_sack_with_nr_frags == 0) && 4892163953Srrs (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) 4893163953Srrs ) { 4894163953Srrs /* 4895163953Srrs * We have a SIMPLE sack having no 4896163953Srrs * prior segments and data on sent 4897163953Srrs * queue to be acked.. Use the 4898163953Srrs * faster path sack processing. We 4899163953Srrs * also allow window update sacks 4900163953Srrs * with no missing segments to go 4901163953Srrs * this way too. 4902163953Srrs */ 4903218186Srrs sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now, ecne_seen); 4904163953Srrs } else { 4905169420Srrs if (netp && *netp) 4906228653Stuexen sctp_handle_sack(m, offset_seg, offset_dup, stcb, 4907202526Stuexen num_seg, 0, num_dup, &abort_now, flags, 4908218186Srrs cum_ack, a_rwnd, ecne_seen); 4909163953Srrs } 4910202526Stuexen if (abort_now) { 4911202526Stuexen /* ABORT signal from sack processing */ 4912202526Stuexen *offset = length; 4913202526Stuexen return (NULL); 4914202526Stuexen } 4915185694Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 4916185694Srrs TAILQ_EMPTY(&stcb->asoc.sent_queue) && 4917185694Srrs (stcb->asoc.stream_queue_cnt == 0)) { 4918185694Srrs sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 4919185694Srrs } 4920163953Srrs } 4921163953Srrs break; 4922185694Srrs /* 4923185694Srrs * EY - nr_sack: If the received chunk is an 4924185694Srrs * nr_sack chunk 4925185694Srrs */ 4926185694Srrs case SCTP_NR_SELECTIVE_ACK: 4927185694Srrs { 4928185694Srrs struct sctp_nr_sack_chunk *nr_sack; 4929185694Srrs int abort_now = 0; 4930185694Srrs uint32_t a_rwnd, cum_ack; 4931202526Stuexen uint16_t num_seg, num_nr_seg, num_dup; 4932202526Stuexen uint8_t flags; 4933202526Stuexen int offset_seg, offset_dup; 4934185694Srrs 4935211944Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n"); 4936211944Stuexen SCTP_STAT_INCR(sctps_recvsacks); 4937212225Srrs if (stcb == NULL) { 4938212225Srrs SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing NR-SACK chunk\n"); 4939212225Srrs break; 4940212225Srrs } 4941270359Stuexen if (stcb->asoc.nrsack_supported == 0) { 4942185694Srrs goto unknown_chunk; 4943185694Srrs } 4944202526Stuexen if (chk_length < sizeof(struct sctp_nr_sack_chunk)) { 4945202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on NR-SACK chunk, too small\n"); 4946202526Stuexen break; 4947202526Stuexen } 4948185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 4949185694Srrs /*- 4950185694Srrs * If we have sent a shutdown-ack, we will pay no 4951185694Srrs * attention to a sack sent in to us since 4952185694Srrs * we don't care anymore. 4953185694Srrs */ 4954202526Stuexen break; 4955185694Srrs } 4956185694Srrs nr_sack = (struct sctp_nr_sack_chunk *)ch; 4957202526Stuexen flags = ch->chunk_flags; 4958185694Srrs cum_ack = ntohl(nr_sack->nr_sack.cum_tsn_ack); 4959185694Srrs num_seg = ntohs(nr_sack->nr_sack.num_gap_ack_blks); 4960185694Srrs num_nr_seg = ntohs(nr_sack->nr_sack.num_nr_gap_ack_blks); 4961202526Stuexen num_dup = ntohs(nr_sack->nr_sack.num_dup_tsns); 4962185694Srrs a_rwnd = (uint32_t) ntohl(nr_sack->nr_sack.a_rwnd); 4963202526Stuexen if (sizeof(struct sctp_nr_sack_chunk) + 4964202526Stuexen (num_seg + num_nr_seg) * sizeof(struct sctp_gap_ack_block) + 4965202526Stuexen num_dup * sizeof(uint32_t) != chk_length) { 4966202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of NR_SACK chunk\n"); 4967202526Stuexen break; 4968202526Stuexen } 4969202526Stuexen offset_seg = *offset + sizeof(struct sctp_nr_sack_chunk); 4970202526Stuexen offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 4971185694Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 4972202526Stuexen cum_ack, num_seg, a_rwnd); 4973185694Srrs stcb->asoc.seen_a_sack_this_pkt = 1; 4974185694Srrs if ((stcb->asoc.pr_sctp_cnt == 0) && 4975202526Stuexen (num_seg == 0) && (num_nr_seg == 0) && 4976216825Stuexen SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 4977185694Srrs (stcb->asoc.saw_sack_with_frags == 0) && 4978216188Stuexen (stcb->asoc.saw_sack_with_nr_frags == 0) && 4979202526Stuexen (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 4980185694Srrs /* 4981185694Srrs * We have a SIMPLE sack having no 4982185694Srrs * prior segments and data on sent 4983202526Stuexen * queue to be acked. Use the faster 4984202526Stuexen * path sack processing. We also 4985202526Stuexen * allow window update sacks with no 4986202526Stuexen * missing segments to go this way 4987202526Stuexen * too. 4988185694Srrs */ 4989218129Srrs sctp_express_handle_sack(stcb, cum_ack, a_rwnd, 4990218186Srrs &abort_now, ecne_seen); 4991185694Srrs } else { 4992185694Srrs if (netp && *netp) 4993228653Stuexen sctp_handle_sack(m, offset_seg, offset_dup, stcb, 4994202526Stuexen num_seg, num_nr_seg, num_dup, &abort_now, flags, 4995218186Srrs cum_ack, a_rwnd, ecne_seen); 4996185694Srrs } 4997202526Stuexen if (abort_now) { 4998202526Stuexen /* ABORT signal from sack processing */ 4999202526Stuexen *offset = length; 5000202526Stuexen return (NULL); 5001202526Stuexen } 5002185694Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 5003185694Srrs TAILQ_EMPTY(&stcb->asoc.sent_queue) && 5004185694Srrs (stcb->asoc.stream_queue_cnt == 0)) { 5005185694Srrs sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 5006185694Srrs } 5007185694Srrs } 5008185694Srrs break; 5009185694Srrs 5010163953Srrs case SCTP_HEARTBEAT_REQUEST: 5011169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT\n"); 5012169420Srrs if ((stcb) && netp && *netp) { 5013169420Srrs SCTP_STAT_INCR(sctps_recvheartbeat); 5014169420Srrs sctp_send_heartbeat_ack(stcb, m, *offset, 5015169420Srrs chk_length, *netp); 5016169420Srrs 5017169420Srrs /* He's alive so give him credit */ 5018179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5019171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5020171943Srrs stcb->asoc.overall_error_count, 5021171943Srrs 0, 5022171943Srrs SCTP_FROM_SCTP_INPUT, 5023171943Srrs __LINE__); 5024171943Srrs } 5025169420Srrs stcb->asoc.overall_error_count = 0; 5026163953Srrs } 5027163953Srrs break; 5028163953Srrs case SCTP_HEARTBEAT_ACK: 5029169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT-ACK\n"); 5030169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_heartbeat_chunk))) { 5031169208Srrs /* Its not ours */ 5032169352Srrs *offset = length; 5033169378Srrs if (locked_tcb) { 5034169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5035169378Srrs } 5036169208Srrs return (NULL); 5037169208Srrs } 5038163953Srrs /* He's alive so give him credit */ 5039179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5040171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5041171943Srrs stcb->asoc.overall_error_count, 5042171943Srrs 0, 5043171943Srrs SCTP_FROM_SCTP_INPUT, 5044171943Srrs __LINE__); 5045171943Srrs } 5046163953Srrs stcb->asoc.overall_error_count = 0; 5047163953Srrs SCTP_STAT_INCR(sctps_recvheartbeatack); 5048169420Srrs if (netp && *netp) 5049169420Srrs sctp_handle_heartbeat_ack((struct sctp_heartbeat_chunk *)ch, 5050169420Srrs stcb, *netp); 5051163953Srrs break; 5052163953Srrs case SCTP_ABORT_ASSOCIATION: 5053170091Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT, stcb %p\n", 5054240148Stuexen (void *)stcb); 5055169420Srrs if ((stcb) && netp && *netp) 5056169420Srrs sctp_handle_abort((struct sctp_abort_chunk *)ch, 5057169420Srrs stcb, *netp); 5058163953Srrs *offset = length; 5059163953Srrs return (NULL); 5060163953Srrs break; 5061163953Srrs case SCTP_SHUTDOWN: 5062170091Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN, stcb %p\n", 5063240148Stuexen (void *)stcb); 5064169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_shutdown_chunk))) { 5065169208Srrs *offset = length; 5066169378Srrs if (locked_tcb) { 5067169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5068169378Srrs } 5069169208Srrs return (NULL); 5070169420Srrs } 5071169420Srrs if (netp && *netp) { 5072163953Srrs int abort_flag = 0; 5073163953Srrs 5074163953Srrs sctp_handle_shutdown((struct sctp_shutdown_chunk *)ch, 5075163953Srrs stcb, *netp, &abort_flag); 5076163953Srrs if (abort_flag) { 5077163953Srrs *offset = length; 5078163953Srrs return (NULL); 5079163953Srrs } 5080163953Srrs } 5081163953Srrs break; 5082163953Srrs case SCTP_SHUTDOWN_ACK: 5083240148Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", (void *)stcb); 5084169420Srrs if ((stcb) && (netp) && (*netp)) 5085169420Srrs sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp); 5086163953Srrs *offset = length; 5087163953Srrs return (NULL); 5088163953Srrs break; 5089169420Srrs 5090163953Srrs case SCTP_OPERATION_ERROR: 5091169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_OP-ERR\n"); 5092169420Srrs if ((stcb) && netp && *netp && sctp_handle_error(ch, stcb, *netp) < 0) { 5093163953Srrs *offset = length; 5094163953Srrs return (NULL); 5095163953Srrs } 5096163953Srrs break; 5097163953Srrs case SCTP_COOKIE_ECHO: 5098169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 5099240148Stuexen "SCTP_COOKIE-ECHO, stcb %p\n", (void *)stcb); 5100163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 5101163953Srrs ; 5102163953Srrs } else { 5103169420Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5104163953Srrs /* We are not interested anymore */ 5105208878Srrs abend: 5106208853Srrs if (stcb) { 5107208853Srrs SCTP_TCB_UNLOCK(stcb); 5108208853Srrs } 5109163953Srrs *offset = length; 5110163953Srrs return (NULL); 5111163953Srrs } 5112163953Srrs } 5113163953Srrs /* 5114163953Srrs * First are we accepting? We do this again here 5115207924Srrs * since it is possible that a previous endpoint WAS 5116207924Srrs * listening responded to a INIT-ACK and then 5117163953Srrs * closed. We opened and bound.. and are now no 5118163953Srrs * longer listening. 5119163953Srrs */ 5120172703Srrs 5121172703Srrs if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) { 5122172703Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 5123179783Srrs (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) { 5124267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 5125237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, 5126237715Stuexen src, dst, sh, op_err, 5127237049Stuexen use_mflowid, mflowid, 5128237049Stuexen vrf_id, port); 5129163953Srrs } 5130172703Srrs *offset = length; 5131172703Srrs return (NULL); 5132172703Srrs } else { 5133163953Srrs struct mbuf *ret_buf; 5134165220Srrs struct sctp_inpcb *linp; 5135163953Srrs 5136169420Srrs if (stcb) { 5137165220Srrs linp = NULL; 5138169420Srrs } else { 5139165220Srrs linp = inp; 5140169420Srrs } 5141165220Srrs 5142169420Srrs if (linp) { 5143165220Srrs SCTP_ASOC_CREATE_LOCK(linp); 5144208878Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 5145208878Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 5146208878Srrs SCTP_ASOC_CREATE_UNLOCK(linp); 5147208878Srrs goto abend; 5148208878Srrs } 5149169420Srrs } 5150169420Srrs if (netp) { 5151169420Srrs ret_buf = 5152169420Srrs sctp_handle_cookie_echo(m, iphlen, 5153237715Stuexen *offset, 5154237715Stuexen src, dst, 5155237715Stuexen sh, 5156169420Srrs (struct sctp_cookie_echo_chunk *)ch, 5157169420Srrs &inp, &stcb, netp, 5158169420Srrs auth_skipped, 5159169420Srrs auth_offset, 5160169420Srrs auth_len, 5161169420Srrs &locked_tcb, 5162237049Stuexen use_mflowid, 5163237049Stuexen mflowid, 5164179157Srrs vrf_id, 5165179157Srrs port); 5166169420Srrs } else { 5167169420Srrs ret_buf = NULL; 5168169420Srrs } 5169169420Srrs if (linp) { 5170165220Srrs SCTP_ASOC_CREATE_UNLOCK(linp); 5171169420Srrs } 5172163953Srrs if (ret_buf == NULL) { 5173163953Srrs if (locked_tcb) { 5174163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5175163953Srrs } 5176169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 5177169420Srrs "GAK, null buffer\n"); 5178163953Srrs *offset = length; 5179163953Srrs return (NULL); 5180163953Srrs } 5181163953Srrs /* if AUTH skipped, see if it verified... */ 5182163953Srrs if (auth_skipped) { 5183163953Srrs got_auth = 1; 5184163953Srrs auth_skipped = 0; 5185163953Srrs } 5186163953Srrs if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) { 5187163953Srrs /* 5188163953Srrs * Restart the timer if we have 5189163953Srrs * pending data 5190163953Srrs */ 5191163953Srrs struct sctp_tmit_chunk *chk; 5192163953Srrs 5193163953Srrs chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 5194216822Stuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 5195163953Srrs } 5196163953Srrs } 5197163953Srrs break; 5198163953Srrs case SCTP_COOKIE_ACK: 5199240148Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", (void *)stcb); 5200169420Srrs if ((stcb == NULL) || chk_length != sizeof(struct sctp_cookie_ack_chunk)) { 5201169378Srrs if (locked_tcb) { 5202169352Srrs SCTP_TCB_UNLOCK(locked_tcb); 5203169378Srrs } 5204169352Srrs return (NULL); 5205169352Srrs } 5206163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5207163953Srrs /* We are not interested anymore */ 5208163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 5209163953Srrs ; 5210169420Srrs } else if (stcb) { 5211237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5212172090Srrs so = SCTP_INP_SO(inp); 5213172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5214172090Srrs SCTP_TCB_UNLOCK(stcb); 5215172090Srrs SCTP_SOCKET_LOCK(so, 1); 5216172090Srrs SCTP_TCB_LOCK(stcb); 5217172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 5218172090Srrs#endif 5219171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27); 5220237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5221172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 5222172090Srrs#endif 5223163953Srrs *offset = length; 5224163953Srrs return (NULL); 5225163953Srrs } 5226163953Srrs } 5227163953Srrs /* He's alive so give him credit */ 5228169420Srrs if ((stcb) && netp && *netp) { 5229179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5230171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5231171943Srrs stcb->asoc.overall_error_count, 5232171943Srrs 0, 5233171943Srrs SCTP_FROM_SCTP_INPUT, 5234171943Srrs __LINE__); 5235171943Srrs } 5236169378Srrs stcb->asoc.overall_error_count = 0; 5237169378Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, *netp); 5238169378Srrs } 5239163953Srrs break; 5240163953Srrs case SCTP_ECN_ECHO: 5241169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-ECHO\n"); 5242163953Srrs /* He's alive so give him credit */ 5243169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_ecne_chunk))) { 5244169208Srrs /* Its not ours */ 5245169378Srrs if (locked_tcb) { 5246169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5247169378Srrs } 5248169208Srrs *offset = length; 5249169208Srrs return (NULL); 5250169208Srrs } 5251169378Srrs if (stcb) { 5252270362Stuexen if (stcb->asoc.ecn_supported == 0) { 5253270362Stuexen goto unknown_chunk; 5254270362Stuexen } 5255179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5256171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5257171943Srrs stcb->asoc.overall_error_count, 5258171943Srrs 0, 5259171943Srrs SCTP_FROM_SCTP_INPUT, 5260171943Srrs __LINE__); 5261171943Srrs } 5262169378Srrs stcb->asoc.overall_error_count = 0; 5263169378Srrs sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch, 5264169378Srrs stcb); 5265218186Srrs ecne_seen = 1; 5266169378Srrs } 5267163953Srrs break; 5268163953Srrs case SCTP_ECN_CWR: 5269169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-CWR\n"); 5270163953Srrs /* He's alive so give him credit */ 5271169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_cwr_chunk))) { 5272169208Srrs /* Its not ours */ 5273169378Srrs if (locked_tcb) { 5274169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5275169378Srrs } 5276169208Srrs *offset = length; 5277169208Srrs return (NULL); 5278169208Srrs } 5279169378Srrs if (stcb) { 5280270362Stuexen if (stcb->asoc.ecn_supported == 0) { 5281270362Stuexen goto unknown_chunk; 5282270362Stuexen } 5283179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5284171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5285171943Srrs stcb->asoc.overall_error_count, 5286171943Srrs 0, 5287171943Srrs SCTP_FROM_SCTP_INPUT, 5288171943Srrs __LINE__); 5289171943Srrs } 5290169378Srrs stcb->asoc.overall_error_count = 0; 5291218072Srrs sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb, *netp); 5292169378Srrs } 5293163953Srrs break; 5294163953Srrs case SCTP_SHUTDOWN_COMPLETE: 5295240148Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", (void *)stcb); 5296163953Srrs /* must be first and only chunk */ 5297163953Srrs if ((num_chunks > 1) || 5298170140Srrs (length - *offset > (int)SCTP_SIZE32(chk_length))) { 5299163953Srrs *offset = length; 5300169378Srrs if (locked_tcb) { 5301163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5302169378Srrs } 5303163953Srrs return (NULL); 5304163953Srrs } 5305169420Srrs if ((stcb) && netp && *netp) { 5306169378Srrs sctp_handle_shutdown_complete((struct sctp_shutdown_complete_chunk *)ch, 5307169378Srrs stcb, *netp); 5308169378Srrs } 5309163953Srrs *offset = length; 5310163953Srrs return (NULL); 5311163953Srrs break; 5312163953Srrs case SCTP_ASCONF: 5313169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n"); 5314163953Srrs /* He's alive so give him credit */ 5315169378Srrs if (stcb) { 5316270362Stuexen if (stcb->asoc.asconf_supported == 0) { 5317270362Stuexen goto unknown_chunk; 5318270362Stuexen } 5319179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5320171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5321171943Srrs stcb->asoc.overall_error_count, 5322171943Srrs 0, 5323171943Srrs SCTP_FROM_SCTP_INPUT, 5324171943Srrs __LINE__); 5325171943Srrs } 5326169378Srrs stcb->asoc.overall_error_count = 0; 5327237715Stuexen sctp_handle_asconf(m, *offset, src, 5328171990Srrs (struct sctp_asconf_chunk *)ch, stcb, asconf_cnt == 0); 5329171990Srrs asconf_cnt++; 5330169378Srrs } 5331163953Srrs break; 5332163953Srrs case SCTP_ASCONF_ACK: 5333169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF-ACK\n"); 5334169208Srrs if (chk_length < sizeof(struct sctp_asconf_ack_chunk)) { 5335169208Srrs /* Its not ours */ 5336169378Srrs if (locked_tcb) { 5337169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5338169378Srrs } 5339169208Srrs *offset = length; 5340169208Srrs return (NULL); 5341169208Srrs } 5342169420Srrs if ((stcb) && netp && *netp) { 5343270362Stuexen if (stcb->asoc.asconf_supported == 0) { 5344270362Stuexen goto unknown_chunk; 5345270362Stuexen } 5346169378Srrs /* He's alive so give him credit */ 5347179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5348171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5349171943Srrs stcb->asoc.overall_error_count, 5350171943Srrs 0, 5351171943Srrs SCTP_FROM_SCTP_INPUT, 5352171943Srrs __LINE__); 5353171943Srrs } 5354169378Srrs stcb->asoc.overall_error_count = 0; 5355169378Srrs sctp_handle_asconf_ack(m, *offset, 5356172190Srrs (struct sctp_asconf_ack_chunk *)ch, stcb, *netp, &abort_no_unlock); 5357172190Srrs if (abort_no_unlock) 5358172190Srrs return (NULL); 5359169378Srrs } 5360163953Srrs break; 5361163953Srrs case SCTP_FORWARD_CUM_TSN: 5362169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_FWD-TSN\n"); 5363169208Srrs if (chk_length < sizeof(struct sctp_forward_tsn_chunk)) { 5364169208Srrs /* Its not ours */ 5365169378Srrs if (locked_tcb) { 5366169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5367169378Srrs } 5368169208Srrs *offset = length; 5369169208Srrs return (NULL); 5370169208Srrs } 5371163953Srrs /* He's alive so give him credit */ 5372169378Srrs if (stcb) { 5373163953Srrs int abort_flag = 0; 5374163953Srrs 5375270362Stuexen if (stcb->asoc.prsctp_supported == 0) { 5376270362Stuexen goto unknown_chunk; 5377270362Stuexen } 5378163953Srrs stcb->asoc.overall_error_count = 0; 5379179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5380171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5381171943Srrs stcb->asoc.overall_error_count, 5382171943Srrs 0, 5383171943Srrs SCTP_FROM_SCTP_INPUT, 5384171943Srrs __LINE__); 5385171943Srrs } 5386163953Srrs *fwd_tsn_seen = 1; 5387163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5388163953Srrs /* We are not interested anymore */ 5389237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5390172090Srrs so = SCTP_INP_SO(inp); 5391172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5392172090Srrs SCTP_TCB_UNLOCK(stcb); 5393172090Srrs SCTP_SOCKET_LOCK(so, 1); 5394172090Srrs SCTP_TCB_LOCK(stcb); 5395172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 5396172090Srrs#endif 5397171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_29); 5398237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5399172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 5400172090Srrs#endif 5401163953Srrs *offset = length; 5402163953Srrs return (NULL); 5403163953Srrs } 5404163953Srrs sctp_handle_forward_tsn(stcb, 5405170992Srrs (struct sctp_forward_tsn_chunk *)ch, &abort_flag, m, *offset); 5406163953Srrs if (abort_flag) { 5407163953Srrs *offset = length; 5408163953Srrs return (NULL); 5409163953Srrs } else { 5410179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5411171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5412171943Srrs stcb->asoc.overall_error_count, 5413171943Srrs 0, 5414171943Srrs SCTP_FROM_SCTP_INPUT, 5415171943Srrs __LINE__); 5416171943Srrs } 5417163953Srrs stcb->asoc.overall_error_count = 0; 5418163953Srrs } 5419163953Srrs 5420163953Srrs } 5421163953Srrs break; 5422163953Srrs case SCTP_STREAM_RESET: 5423169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_STREAM_RESET\n"); 5424169420Srrs if (((stcb == NULL) || (ch == NULL) || (chk_length < sizeof(struct sctp_stream_reset_tsn_req)))) { 5425169208Srrs /* Its not ours */ 5426169378Srrs if (locked_tcb) { 5427169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5428169378Srrs } 5429169208Srrs *offset = length; 5430169208Srrs return (NULL); 5431169208Srrs } 5432270361Stuexen if (stcb->asoc.reconfig_supported == 0) { 5433270362Stuexen goto unknown_chunk; 5434163953Srrs } 5435240198Stuexen if (sctp_handle_stream_reset(stcb, m, *offset, ch)) { 5436169420Srrs /* stop processing */ 5437169420Srrs *offset = length; 5438169420Srrs return (NULL); 5439169420Srrs } 5440163953Srrs break; 5441163953Srrs case SCTP_PACKET_DROPPED: 5442169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_PACKET_DROPPED\n"); 5443163953Srrs /* re-get it all please */ 5444169208Srrs if (chk_length < sizeof(struct sctp_pktdrop_chunk)) { 5445169208Srrs /* Its not ours */ 5446169378Srrs if (locked_tcb) { 5447169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5448169378Srrs } 5449169208Srrs *offset = length; 5450169208Srrs return (NULL); 5451169208Srrs } 5452169420Srrs if (ch && (stcb) && netp && (*netp)) { 5453270362Stuexen if (stcb->asoc.pktdrop_supported == 0) { 5454270362Stuexen goto unknown_chunk; 5455270362Stuexen } 5456169378Srrs sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch, 5457170781Srrs stcb, *netp, 5458170781Srrs min(chk_length, (sizeof(chunk_buf) - 4))); 5459170781Srrs 5460169378Srrs } 5461163953Srrs break; 5462163953Srrs case SCTP_AUTHENTICATION: 5463169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n"); 5464163953Srrs if (stcb == NULL) { 5465163953Srrs /* save the first AUTH for later processing */ 5466163953Srrs if (auth_skipped == 0) { 5467163953Srrs auth_offset = *offset; 5468163953Srrs auth_len = chk_length; 5469163953Srrs auth_skipped = 1; 5470163953Srrs } 5471163953Srrs /* skip this chunk (temporarily) */ 5472163953Srrs goto next_chunk; 5473163953Srrs } 5474270362Stuexen if (stcb->asoc.auth_supported == 0) { 5475270362Stuexen goto unknown_chunk; 5476270362Stuexen } 5477169208Srrs if ((chk_length < (sizeof(struct sctp_auth_chunk))) || 5478169420Srrs (chk_length > (sizeof(struct sctp_auth_chunk) + 5479169420Srrs SCTP_AUTH_DIGEST_LEN_MAX))) { 5480169208Srrs /* Its not ours */ 5481169378Srrs if (locked_tcb) { 5482169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5483169378Srrs } 5484169208Srrs *offset = length; 5485169208Srrs return (NULL); 5486169208Srrs } 5487163953Srrs if (got_auth == 1) { 5488163953Srrs /* skip this chunk... it's already auth'd */ 5489163953Srrs goto next_chunk; 5490163953Srrs } 5491163953Srrs got_auth = 1; 5492169420Srrs if ((ch == NULL) || sctp_handle_auth(stcb, (struct sctp_auth_chunk *)ch, 5493163953Srrs m, *offset)) { 5494163953Srrs /* auth HMAC failed so dump the packet */ 5495163953Srrs *offset = length; 5496163953Srrs return (stcb); 5497163953Srrs } else { 5498163953Srrs /* remaining chunks are HMAC checked */ 5499163953Srrs stcb->asoc.authenticated = 1; 5500163953Srrs } 5501163953Srrs break; 5502163953Srrs 5503163953Srrs default: 5504163953Srrs unknown_chunk: 5505163953Srrs /* it's an unknown chunk! */ 5506163953Srrs if ((ch->chunk_type & 0x40) && (stcb != NULL)) { 5507163953Srrs struct mbuf *mm; 5508163953Srrs struct sctp_paramhdr *phd; 5509163953Srrs 5510163953Srrs mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 5511243882Sglebius 0, M_NOWAIT, 1, MT_DATA); 5512163953Srrs if (mm) { 5513163953Srrs phd = mtod(mm, struct sctp_paramhdr *); 5514163953Srrs /* 5515163953Srrs * We cheat and use param type since 5516163953Srrs * we did not bother to define a 5517163953Srrs * error cause struct. They are the 5518163953Srrs * same basic format with different 5519163953Srrs * names. 5520163953Srrs */ 5521163953Srrs phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK); 5522163953Srrs phd->param_length = htons(chk_length + sizeof(*phd)); 5523165647Srrs SCTP_BUF_LEN(mm) = sizeof(*phd); 5524243882Sglebius SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); 5525165647Srrs if (SCTP_BUF_NEXT(mm)) { 5526270354Stuexen if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) { 5527234459Stuexen sctp_m_freem(mm); 5528234459Stuexen } else { 5529178202Srrs#ifdef SCTP_MBUF_LOGGING 5530234459Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 5531234459Stuexen struct mbuf *mat; 5532178202Srrs 5533234461Stuexen for (mat = SCTP_BUF_NEXT(mm); mat; mat = SCTP_BUF_NEXT(mat)) { 5534234459Stuexen if (SCTP_BUF_IS_EXTENDED(mat)) { 5535234459Stuexen sctp_log_mb(mat, SCTP_MBUF_ICOPY); 5536234459Stuexen } 5537178202Srrs } 5538178202Srrs } 5539234459Stuexen#endif 5540234459Stuexen sctp_queue_op_err(stcb, mm); 5541178202Srrs } 5542163953Srrs } else { 5543163953Srrs sctp_m_freem(mm); 5544163953Srrs } 5545163953Srrs } 5546163953Srrs } 5547163953Srrs if ((ch->chunk_type & 0x80) == 0) { 5548163953Srrs /* discard this packet */ 5549163953Srrs *offset = length; 5550163953Srrs return (stcb); 5551163953Srrs } /* else skip this bad chunk and continue... */ 5552163953Srrs break; 5553163953Srrs } /* switch (ch->chunk_type) */ 5554163953Srrs 5555163953Srrs 5556163953Srrsnext_chunk: 5557163953Srrs /* get the next chunk */ 5558163953Srrs *offset += SCTP_SIZE32(chk_length); 5559163953Srrs if (*offset >= length) { 5560163953Srrs /* no more data left in the mbuf chain */ 5561163953Srrs break; 5562163953Srrs } 5563163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 5564163953Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 5565163953Srrs if (ch == NULL) { 5566169378Srrs if (locked_tcb) { 5567163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5568169378Srrs } 5569163953Srrs *offset = length; 5570163953Srrs return (NULL); 5571163953Srrs } 5572163953Srrs } /* while */ 5573171990Srrs 5574171990Srrs if (asconf_cnt > 0 && stcb != NULL) { 5575171990Srrs sctp_send_asconf_ack(stcb); 5576171990Srrs } 5577163953Srrs return (stcb); 5578163953Srrs} 5579163953Srrs 5580163953Srrs 5581171440Srrs#ifdef INVARIANTS 5582208853Srrs#ifdef __GNUC__ 5583208853Srrs__attribute__((noinline)) 5584208853Srrs#endif 5585208853Srrs void 5586208853Srrs sctp_validate_no_locks(struct sctp_inpcb *inp) 5587171440Srrs{ 5588208853Srrs struct sctp_tcb *lstcb; 5589171440Srrs 5590208853Srrs LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) { 5591208853Srrs if (mtx_owned(&lstcb->tcb_mtx)) { 5592171440Srrs panic("Own lock on stcb at return from input"); 5593171440Srrs } 5594171440Srrs } 5595208876Srrs if (mtx_owned(&inp->inp_create_mtx)) { 5596208876Srrs panic("Own create lock on inp"); 5597208876Srrs } 5598208876Srrs if (mtx_owned(&inp->inp_mtx)) { 5599208876Srrs panic("Own inp lock on inp"); 5600208876Srrs } 5601171440Srrs} 5602171440Srrs 5603171440Srrs#endif 5604171440Srrs 5605163953Srrs/* 5606163953Srrs * common input chunk processing (v4 and v6) 5607163953Srrs */ 5608169378Srrsvoid 5609237715Stuexensctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int length, 5610237715Stuexen struct sockaddr *src, struct sockaddr *dst, 5611237715Stuexen struct sctphdr *sh, struct sctp_chunkhdr *ch, 5612238003Stuexen#if !defined(SCTP_WITH_NO_CSUM) 5613238003Stuexen uint8_t compute_crc, 5614238003Stuexen#endif 5615238003Stuexen uint8_t ecn_bits, 5616237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 5617237049Stuexen uint32_t vrf_id, uint16_t port) 5618163953Srrs{ 5619163953Srrs uint32_t high_tsn; 5620163953Srrs int fwd_tsn_seen = 0, data_processed = 0; 5621267723Stuexen struct mbuf *m = *mm, *op_err; 5622267723Stuexen char msg[SCTP_DIAG_INFO_LEN]; 5623163953Srrs int un_sent; 5624218129Srrs int cnt_ctrl_ready = 0; 5625239091Stuexen struct sctp_inpcb *inp = NULL, *inp_decr = NULL; 5626238003Stuexen struct sctp_tcb *stcb = NULL; 5627238087Stuexen struct sctp_nets *net = NULL; 5628163953Srrs 5629163953Srrs SCTP_STAT_INCR(sctps_recvdatagrams); 5630163953Srrs#ifdef SCTP_AUDITING_ENABLED 5631163953Srrs sctp_audit_log(0xE0, 1); 5632163953Srrs sctp_auditing(0, inp, stcb, net); 5633163953Srrs#endif 5634238003Stuexen#if !defined(SCTP_WITH_NO_CSUM) 5635238003Stuexen if (compute_crc != 0) { 5636238003Stuexen uint32_t check, calc_check; 5637163953Srrs 5638238003Stuexen check = sh->checksum; 5639238003Stuexen sh->checksum = 0; 5640238003Stuexen calc_check = sctp_calculate_cksum(m, iphlen); 5641238003Stuexen sh->checksum = check; 5642238003Stuexen if (calc_check != check) { 5643238003Stuexen SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n", 5644240148Stuexen calc_check, check, (void *)m, length, iphlen); 5645238003Stuexen stcb = sctp_findassociation_addr(m, offset, src, dst, 5646238003Stuexen sh, ch, &inp, &net, vrf_id); 5647270350Stuexen#if defined(INET) || defined(INET6) 5648238003Stuexen if ((net != NULL) && (port != 0)) { 5649238003Stuexen if (net->port == 0) { 5650238003Stuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 5651238003Stuexen } 5652238003Stuexen net->port = port; 5653238003Stuexen } 5654270350Stuexen#endif 5655238003Stuexen if ((net != NULL) && (use_mflowid != 0)) { 5656238003Stuexen net->flowid = mflowid; 5657238003Stuexen#ifdef INVARIANTS 5658238003Stuexen net->flowidset = 1; 5659238003Stuexen#endif 5660238003Stuexen } 5661238003Stuexen if ((inp != NULL) && (stcb != NULL)) { 5662238003Stuexen sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1); 5663238003Stuexen sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED); 5664238003Stuexen } else if ((inp != NULL) && (stcb == NULL)) { 5665238003Stuexen inp_decr = inp; 5666238003Stuexen } 5667238003Stuexen SCTP_STAT_INCR(sctps_badsum); 5668238003Stuexen SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors); 5669238003Stuexen goto out; 5670238003Stuexen } 5671238003Stuexen } 5672238003Stuexen#endif 5673238003Stuexen /* Destination port of 0 is illegal, based on RFC4960. */ 5674238003Stuexen if (sh->dest_port == 0) { 5675238003Stuexen SCTP_STAT_INCR(sctps_hdrops); 5676238003Stuexen goto out; 5677238003Stuexen } 5678238003Stuexen stcb = sctp_findassociation_addr(m, offset, src, dst, 5679238003Stuexen sh, ch, &inp, &net, vrf_id); 5680270350Stuexen#if defined(INET) || defined(INET6) 5681238003Stuexen if ((net != NULL) && (port != 0)) { 5682238003Stuexen if (net->port == 0) { 5683238003Stuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 5684238003Stuexen } 5685238003Stuexen net->port = port; 5686238003Stuexen } 5687270350Stuexen#endif 5688238003Stuexen if ((net != NULL) && (use_mflowid != 0)) { 5689238003Stuexen net->flowid = mflowid; 5690238003Stuexen#ifdef INVARIANTS 5691238003Stuexen net->flowidset = 1; 5692238003Stuexen#endif 5693238003Stuexen } 5694238003Stuexen if (inp == NULL) { 5695238003Stuexen SCTP_STAT_INCR(sctps_noport); 5696238003Stuexen if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) { 5697238003Stuexen goto out; 5698238003Stuexen } 5699238003Stuexen if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 5700238003Stuexen sctp_send_shutdown_complete2(src, dst, sh, 5701238003Stuexen use_mflowid, mflowid, 5702238003Stuexen vrf_id, port); 5703238003Stuexen goto out; 5704238003Stuexen } 5705238003Stuexen if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) { 5706238003Stuexen goto out; 5707238003Stuexen } 5708238003Stuexen if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) { 5709238003Stuexen if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || 5710238003Stuexen ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && 5711238003Stuexen (ch->chunk_type != SCTP_INIT))) { 5712267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5713267723Stuexen "Out of the blue"); 5714238003Stuexen sctp_send_abort(m, iphlen, src, dst, 5715267723Stuexen sh, 0, op_err, 5716238003Stuexen use_mflowid, mflowid, 5717238003Stuexen vrf_id, port); 5718238003Stuexen } 5719238003Stuexen } 5720238003Stuexen goto out; 5721238003Stuexen } else if (stcb == NULL) { 5722238003Stuexen inp_decr = inp; 5723238003Stuexen } 5724238003Stuexen#ifdef IPSEC 5725238003Stuexen /*- 5726238003Stuexen * I very much doubt any of the IPSEC stuff will work but I have no 5727238003Stuexen * idea, so I will leave it in place. 5728238003Stuexen */ 5729238003Stuexen if (inp != NULL) { 5730238003Stuexen switch (dst->sa_family) { 5731238003Stuexen#ifdef INET 5732238003Stuexen case AF_INET: 5733238003Stuexen if (ipsec4_in_reject(m, &inp->ip_inp.inp)) { 5734253571Sae IPSECSTAT_INC(ips_in_polvio); 5735238003Stuexen SCTP_STAT_INCR(sctps_hdrops); 5736238003Stuexen goto out; 5737238003Stuexen } 5738238003Stuexen break; 5739238003Stuexen#endif 5740238003Stuexen#ifdef INET6 5741238003Stuexen case AF_INET6: 5742238003Stuexen if (ipsec6_in_reject(m, &inp->ip_inp.inp)) { 5743253571Sae IPSEC6STAT_INC(ips_in_polvio); 5744238003Stuexen SCTP_STAT_INCR(sctps_hdrops); 5745238003Stuexen goto out; 5746238003Stuexen } 5747238003Stuexen break; 5748238003Stuexen#endif 5749238003Stuexen default: 5750238003Stuexen break; 5751238003Stuexen } 5752238003Stuexen } 5753238003Stuexen#endif 5754179783Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n", 5755240148Stuexen (void *)m, iphlen, offset, length, (void *)stcb); 5756163953Srrs if (stcb) { 5757163953Srrs /* always clear this before beginning a packet */ 5758163953Srrs stcb->asoc.authenticated = 0; 5759163953Srrs stcb->asoc.seen_a_sack_this_pkt = 0; 5760171990Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "stcb:%p state:%x\n", 5761240148Stuexen (void *)stcb, stcb->asoc.state); 5762171990Srrs 5763171943Srrs if ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) || 5764171943Srrs (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) { 5765171745Srrs /*- 5766171745Srrs * If we hit here, we had a ref count 5767171745Srrs * up when the assoc was aborted and the 5768171745Srrs * timer is clearing out the assoc, we should 5769171745Srrs * NOT respond to any packet.. its OOTB. 5770171745Srrs */ 5771171745Srrs SCTP_TCB_UNLOCK(stcb); 5772238003Stuexen stcb = NULL; 5773267723Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 5774267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5775267723Stuexen msg); 5776267723Stuexen sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 5777237049Stuexen use_mflowid, mflowid, 5778179157Srrs vrf_id, port); 5779238003Stuexen goto out; 5780171745Srrs } 5781163953Srrs } 5782163953Srrs if (IS_SCTP_CONTROL(ch)) { 5783163953Srrs /* process the control portion of the SCTP packet */ 5784169655Srrs /* sa_ignore NO_NULL_CHK */ 5785237715Stuexen stcb = sctp_process_control(m, iphlen, &offset, length, 5786237715Stuexen src, dst, sh, ch, 5787237049Stuexen inp, stcb, &net, &fwd_tsn_seen, 5788237049Stuexen use_mflowid, mflowid, 5789237049Stuexen vrf_id, port); 5790163953Srrs if (stcb) { 5791163953Srrs /* 5792163953Srrs * This covers us if the cookie-echo was there and 5793163953Srrs * it changes our INP. 5794163953Srrs */ 5795163953Srrs inp = stcb->sctp_ep; 5796270350Stuexen#if defined(INET) || defined(INET6) 5797179783Srrs if ((net) && (port)) { 5798179783Srrs if (net->port == 0) { 5799228653Stuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 5800179783Srrs } 5801179783Srrs net->port = port; 5802179783Srrs } 5803270350Stuexen#endif 5804163953Srrs } 5805163953Srrs } else { 5806163953Srrs /* 5807163953Srrs * no control chunks, so pre-process DATA chunks (these 5808163953Srrs * checks are taken care of by control processing) 5809163953Srrs */ 5810163953Srrs 5811163953Srrs /* 5812163953Srrs * if DATA only packet, and auth is required, then punt... 5813163953Srrs * can't have authenticated without any AUTH (control) 5814163953Srrs * chunks 5815163953Srrs */ 5816179783Srrs if ((stcb != NULL) && 5817270362Stuexen (stcb->asoc.auth_supported == 1) && 5818179783Srrs sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) { 5819163953Srrs /* "silently" ignore */ 5820163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 5821238003Stuexen goto out; 5822163953Srrs } 5823163953Srrs if (stcb == NULL) { 5824163953Srrs /* out of the blue DATA chunk */ 5825267723Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 5826267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5827267723Stuexen msg); 5828267723Stuexen sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 5829237049Stuexen use_mflowid, mflowid, 5830179157Srrs vrf_id, port); 5831238003Stuexen goto out; 5832163953Srrs } 5833163953Srrs if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) { 5834163953Srrs /* v_tag mismatch! */ 5835163953Srrs SCTP_STAT_INCR(sctps_badvtag); 5836238003Stuexen goto out; 5837163953Srrs } 5838163953Srrs } 5839163953Srrs 5840163953Srrs if (stcb == NULL) { 5841163953Srrs /* 5842163953Srrs * no valid TCB for this packet, or we found it's a bad 5843163953Srrs * packet while processing control, or we're done with this 5844163953Srrs * packet (done or skip rest of data), so we drop it... 5845163953Srrs */ 5846238003Stuexen goto out; 5847163953Srrs } 5848163953Srrs /* 5849163953Srrs * DATA chunk processing 5850163953Srrs */ 5851163953Srrs /* plow through the data chunks while length > offset */ 5852163953Srrs 5853163953Srrs /* 5854163953Srrs * Rest should be DATA only. Check authentication state if AUTH for 5855163953Srrs * DATA is required. 5856163953Srrs */ 5857179783Srrs if ((length > offset) && 5858179783Srrs (stcb != NULL) && 5859270362Stuexen (stcb->asoc.auth_supported == 1) && 5860179783Srrs sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) && 5861163953Srrs !stcb->asoc.authenticated) { 5862163953Srrs /* "silently" ignore */ 5863163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 5864169420Srrs SCTPDBG(SCTP_DEBUG_AUTH1, 5865169420Srrs "Data chunk requires AUTH, skipped\n"); 5866165220Srrs goto trigger_send; 5867163953Srrs } 5868163953Srrs if (length > offset) { 5869163953Srrs int retval; 5870163953Srrs 5871163953Srrs /* 5872163953Srrs * First check to make sure our state is correct. We would 5873163953Srrs * not get here unless we really did have a tag, so we don't 5874163953Srrs * abort if this happens, just dump the chunk silently. 5875163953Srrs */ 5876163953Srrs switch (SCTP_GET_STATE(&stcb->asoc)) { 5877163953Srrs case SCTP_STATE_COOKIE_ECHOED: 5878163953Srrs /* 5879163953Srrs * we consider data with valid tags in this state 5880163953Srrs * shows us the cookie-ack was lost. Imply it was 5881163953Srrs * there. 5882163953Srrs */ 5883179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5884171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5885171943Srrs stcb->asoc.overall_error_count, 5886171943Srrs 0, 5887171943Srrs SCTP_FROM_SCTP_INPUT, 5888171943Srrs __LINE__); 5889171943Srrs } 5890163953Srrs stcb->asoc.overall_error_count = 0; 5891163953Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, net); 5892163953Srrs break; 5893163953Srrs case SCTP_STATE_COOKIE_WAIT: 5894163953Srrs /* 5895163953Srrs * We consider OOTB any data sent during asoc setup. 5896163953Srrs */ 5897267723Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 5898267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5899267723Stuexen msg); 5900267723Stuexen sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 5901237049Stuexen use_mflowid, mflowid, 5902179157Srrs vrf_id, port); 5903238003Stuexen goto out; 5904171531Srrs /* sa_ignore NOTREACHED */ 5905163953Srrs break; 5906163953Srrs case SCTP_STATE_EMPTY: /* should not happen */ 5907163953Srrs case SCTP_STATE_INUSE: /* should not happen */ 5908163953Srrs case SCTP_STATE_SHUTDOWN_RECEIVED: /* This is a peer error */ 5909163953Srrs case SCTP_STATE_SHUTDOWN_ACK_SENT: 5910163953Srrs default: 5911238003Stuexen goto out; 5912171531Srrs /* sa_ignore NOTREACHED */ 5913163953Srrs break; 5914163953Srrs case SCTP_STATE_OPEN: 5915163953Srrs case SCTP_STATE_SHUTDOWN_SENT: 5916163953Srrs break; 5917163953Srrs } 5918163953Srrs /* plow through the data chunks while length > offset */ 5919237715Stuexen retval = sctp_process_data(mm, iphlen, &offset, length, 5920237715Stuexen src, dst, sh, 5921237049Stuexen inp, stcb, net, &high_tsn, 5922237049Stuexen use_mflowid, mflowid, 5923237049Stuexen vrf_id, port); 5924163953Srrs if (retval == 2) { 5925163953Srrs /* 5926163953Srrs * The association aborted, NO UNLOCK needed since 5927163953Srrs * the association is destroyed. 5928163953Srrs */ 5929238003Stuexen stcb = NULL; 5930238003Stuexen goto out; 5931163953Srrs } 5932163953Srrs data_processed = 1; 5933163953Srrs /* 5934163953Srrs * Anything important needs to have been m_copy'ed in 5935163953Srrs * process_data 5936163953Srrs */ 5937163953Srrs } 5938218129Srrs /* take care of ecn */ 5939228907Stuexen if ((data_processed == 1) && 5940270356Stuexen (stcb->asoc.ecn_supported == 1) && 5941218235Stuexen ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) { 5942218129Srrs /* Yep, we need to add a ECNE */ 5943218129Srrs sctp_send_ecn_echo(stcb, net, high_tsn); 5944218129Srrs } 5945163953Srrs if ((data_processed == 0) && (fwd_tsn_seen)) { 5946216495Stuexen int was_a_gap; 5947216495Stuexen uint32_t highest_tsn; 5948163953Srrs 5949216825Stuexen if (SCTP_TSN_GT(stcb->asoc.highest_tsn_inside_nr_map, stcb->asoc.highest_tsn_inside_map)) { 5950216495Stuexen highest_tsn = stcb->asoc.highest_tsn_inside_nr_map; 5951216495Stuexen } else { 5952216495Stuexen highest_tsn = stcb->asoc.highest_tsn_inside_map; 5953163953Srrs } 5954216825Stuexen was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn); 5955190689Srrs stcb->asoc.send_sack = 1; 5956228653Stuexen sctp_sack_check(stcb, was_a_gap); 5957190689Srrs } else if (fwd_tsn_seen) { 5958190689Srrs stcb->asoc.send_sack = 1; 5959163953Srrs } 5960163953Srrs /* trigger send of any chunks in queue... */ 5961165220Srrstrigger_send: 5962163953Srrs#ifdef SCTP_AUDITING_ENABLED 5963163953Srrs sctp_audit_log(0xE0, 2); 5964163953Srrs sctp_auditing(1, inp, stcb, net); 5965163953Srrs#endif 5966169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 5967169420Srrs "Check for chunk output prw:%d tqe:%d tf=%d\n", 5968169420Srrs stcb->asoc.peers_rwnd, 5969169420Srrs TAILQ_EMPTY(&stcb->asoc.control_send_queue), 5970169420Srrs stcb->asoc.total_flight); 5971163953Srrs un_sent = (stcb->asoc.total_output_queue_size - stcb->asoc.total_flight); 5972218129Srrs if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 5973218129Srrs cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq; 5974218129Srrs } 5975218129Srrs if (cnt_ctrl_ready || 5976163953Srrs ((un_sent) && 5977163953Srrs (stcb->asoc.peers_rwnd > 0 || 5978163953Srrs (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) { 5979169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "Calling chunk OUTPUT\n"); 5980172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 5981169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "chunk OUTPUT returns\n"); 5982163953Srrs } 5983163953Srrs#ifdef SCTP_AUDITING_ENABLED 5984163953Srrs sctp_audit_log(0xE0, 3); 5985163953Srrs sctp_auditing(2, inp, stcb, net); 5986163953Srrs#endif 5987238003Stuexenout: 5988238003Stuexen if (stcb != NULL) { 5989238003Stuexen SCTP_TCB_UNLOCK(stcb); 5990238003Stuexen } 5991238003Stuexen if (inp_decr != NULL) { 5992238003Stuexen /* reduce ref-count */ 5993238003Stuexen SCTP_INP_WLOCK(inp_decr); 5994238003Stuexen SCTP_INP_DECR_REF(inp_decr); 5995238003Stuexen SCTP_INP_WUNLOCK(inp_decr); 5996238003Stuexen } 5997171440Srrs#ifdef INVARIANTS 5998238003Stuexen if (inp != NULL) { 5999238003Stuexen sctp_validate_no_locks(inp); 6000238003Stuexen } 6001171440Srrs#endif 6002169378Srrs return; 6003163953Srrs} 6004163953Srrs 6005185694Srrs#if 0 6006185694Srrsstatic void 6007185694Srrssctp_print_mbuf_chain(struct mbuf *m) 6008185694Srrs{ 6009185694Srrs for (; m; m = SCTP_BUF_NEXT(m)) { 6010240148Stuexen SCTP_PRINTF("%p: m_len = %ld\n", (void *)m, SCTP_BUF_LEN(m)); 6011185694Srrs if (SCTP_BUF_IS_EXTENDED(m)) 6012240148Stuexen SCTP_PRINTF("%p: extend_size = %d\n", (void *)m, SCTP_BUF_EXTEND_SIZE(m)); 6013185694Srrs } 6014185694Srrs} 6015163953Srrs 6016185694Srrs#endif 6017185694Srrs 6018221249Stuexen#ifdef INET 6019163953Srrsvoid 6020189004Srdivackysctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) 6021163953Srrs{ 6022165647Srrs struct mbuf *m; 6023163953Srrs int iphlen; 6024170181Srrs uint32_t vrf_id = 0; 6025163953Srrs uint8_t ecn_bits; 6026237715Stuexen struct sockaddr_in src, dst; 6027163953Srrs struct ip *ip; 6028163953Srrs struct sctphdr *sh; 6029237569Stuexen struct sctp_chunkhdr *ch; 6030237569Stuexen int length, offset; 6031163953Srrs 6032211969Stuexen#if !defined(SCTP_WITH_NO_CSUM) 6033238003Stuexen uint8_t compute_crc; 6034211969Stuexen 6035211969Stuexen#endif 6036238003Stuexen uint32_t mflowid; 6037238003Stuexen uint8_t use_mflowid; 6038211969Stuexen 6039237569Stuexen iphlen = off; 6040169352Srrs if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) { 6041169352Srrs SCTP_RELEASE_PKT(i_pak); 6042169352Srrs return; 6043169352Srrs } 6044165647Srrs m = SCTP_HEADER_TO_CHAIN(i_pak); 6045163953Srrs#ifdef SCTP_MBUF_LOGGING 6046163953Srrs /* Log in any input mbufs */ 6047179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 6048234461Stuexen struct mbuf *mat; 6049234461Stuexen 6050228907Stuexen for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) { 6051170744Srrs if (SCTP_BUF_IS_EXTENDED(mat)) { 6052170744Srrs sctp_log_mb(mat, SCTP_MBUF_INPUT); 6053170744Srrs } 6054163953Srrs } 6055163953Srrs } 6056163953Srrs#endif 6057237540Stuexen#ifdef SCTP_PACKET_LOGGING 6058237569Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { 6059237540Stuexen sctp_packet_log(m); 6060237569Stuexen } 6061170091Srrs#endif 6062238003Stuexen SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 6063254854Stuexen "sctp_input(): Packet of length %d received on %s with csum_flags 0x%b.\n", 6064238003Stuexen m->m_pkthdr.len, 6065238003Stuexen if_name(m->m_pkthdr.rcvif), 6066254854Stuexen (int)m->m_pkthdr.csum_flags, CSUM_BITS); 6067237049Stuexen if (m->m_flags & M_FLOWID) { 6068237049Stuexen mflowid = m->m_pkthdr.flowid; 6069237049Stuexen use_mflowid = 1; 6070237049Stuexen } else { 6071237049Stuexen mflowid = 0; 6072237049Stuexen use_mflowid = 0; 6073237049Stuexen } 6074237569Stuexen SCTP_STAT_INCR(sctps_recvpackets); 6075237569Stuexen SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 6076237569Stuexen /* Get IP, SCTP, and first chunk header together in the first mbuf. */ 6077237569Stuexen offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); 6078165647Srrs if (SCTP_BUF_LEN(m) < offset) { 6079237715Stuexen if ((m = m_pullup(m, offset)) == NULL) { 6080163953Srrs SCTP_STAT_INCR(sctps_hdrops); 6081163953Srrs return; 6082163953Srrs } 6083163953Srrs } 6084237715Stuexen ip = mtod(m, struct ip *); 6085237569Stuexen sh = (struct sctphdr *)((caddr_t)ip + iphlen); 6086237569Stuexen ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 6087237569Stuexen offset -= sizeof(struct sctp_chunkhdr); 6088237715Stuexen memset(&src, 0, sizeof(struct sockaddr_in)); 6089237715Stuexen src.sin_family = AF_INET; 6090237715Stuexen src.sin_len = sizeof(struct sockaddr_in); 6091237715Stuexen src.sin_port = sh->src_port; 6092237715Stuexen src.sin_addr = ip->ip_src; 6093237715Stuexen memset(&dst, 0, sizeof(struct sockaddr_in)); 6094237715Stuexen dst.sin_family = AF_INET; 6095237715Stuexen dst.sin_len = sizeof(struct sockaddr_in); 6096237715Stuexen dst.sin_port = sh->dest_port; 6097237715Stuexen dst.sin_addr = ip->ip_dst; 6098241923Sglebius length = ntohs(ip->ip_len); 6099237569Stuexen /* Validate mbuf chain length with IP payload length. */ 6100238003Stuexen if (SCTP_HEADER_LEN(m) != length) { 6101237569Stuexen SCTPDBG(SCTP_DEBUG_INPUT1, 6102238003Stuexen "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m)); 6103188067Srrs SCTP_STAT_INCR(sctps_hdrops); 6104238003Stuexen goto out; 6105188067Srrs } 6106163953Srrs /* SCTP does not allow broadcasts or multicasts */ 6107237715Stuexen if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { 6108238003Stuexen goto out; 6109163953Srrs } 6110237715Stuexen if (SCTP_IS_IT_BROADCAST(dst.sin_addr, m)) { 6111238003Stuexen goto out; 6112163953Srrs } 6113238003Stuexen ecn_bits = ip->ip_tos; 6114211969Stuexen#if defined(SCTP_WITH_NO_CSUM) 6115211969Stuexen SCTP_STAT_INCR(sctps_recvnocrc); 6116211969Stuexen#else 6117188067Srrs if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { 6118188067Srrs SCTP_STAT_INCR(sctps_recvhwcrc); 6119238003Stuexen compute_crc = 0; 6120238003Stuexen } else { 6121238003Stuexen SCTP_STAT_INCR(sctps_recvswcrc); 6122238003Stuexen compute_crc = 1; 6123188067Srrs } 6124218400Stuexen#endif 6125238003Stuexen sctp_common_input_processing(&m, iphlen, offset, length, 6126237715Stuexen (struct sockaddr *)&src, 6127237715Stuexen (struct sockaddr *)&dst, 6128238003Stuexen sh, ch, 6129238003Stuexen#if !defined(SCTP_WITH_NO_CSUM) 6130238003Stuexen compute_crc, 6131218400Stuexen#endif 6132238003Stuexen ecn_bits, 6133237049Stuexen use_mflowid, mflowid, 6134237049Stuexen vrf_id, port); 6135238003Stuexenout: 6136163953Srrs if (m) { 6137163953Srrs sctp_m_freem(m); 6138163953Srrs } 6139163953Srrs return; 6140163953Srrs} 6141218211Srrs 6142218269Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 6143218269Srrsextern int *sctp_cpuarry; 6144218211Srrs 6145218269Srrs#endif 6146218269Srrs 6147179157Srrsvoid 6148218211Srrssctp_input(struct mbuf *m, int off) 6149179157Srrs{ 6150218211Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 6151218211Srrs struct ip *ip; 6152218211Srrs struct sctphdr *sh; 6153218211Srrs int offset; 6154218211Srrs int cpu_to_use; 6155218371Srrs uint32_t flowid, tag; 6156218211Srrs 6157218269Srrs if (mp_ncpus > 1) { 6158218371Srrs if (m->m_flags & M_FLOWID) { 6159218371Srrs flowid = m->m_pkthdr.flowid; 6160218269Srrs } else { 6161218269Srrs /* 6162218371Srrs * No flow id built by lower layers fix it so we 6163218371Srrs * create one. 6164218269Srrs */ 6165237715Stuexen offset = off + sizeof(struct sctphdr); 6166218371Srrs if (SCTP_BUF_LEN(m) < offset) { 6167237715Stuexen if ((m = m_pullup(m, offset)) == NULL) { 6168218371Srrs SCTP_STAT_INCR(sctps_hdrops); 6169218371Srrs return; 6170218371Srrs } 6171218371Srrs } 6172237715Stuexen ip = mtod(m, struct ip *); 6173218371Srrs sh = (struct sctphdr *)((caddr_t)ip + off); 6174218371Srrs tag = htonl(sh->v_tag); 6175218371Srrs flowid = tag ^ ntohs(sh->dest_port) ^ ntohs(sh->src_port); 6176218371Srrs m->m_pkthdr.flowid = flowid; 6177218371Srrs m->m_flags |= M_FLOWID; 6178218269Srrs } 6179218371Srrs cpu_to_use = sctp_cpuarry[flowid % mp_ncpus]; 6180218211Srrs sctp_queue_to_mcore(m, off, cpu_to_use); 6181218211Srrs return; 6182218211Srrs } 6183218211Srrs#endif 6184218211Srrs sctp_input_with_port(m, off, 0); 6185179157Srrs} 6186221249Stuexen 6187221249Stuexen#endif 6188