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: releng/10.3/sys/netinet/sctp_input.c 296052 2016-02-25 18:46:06Z tuexen $"); 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, 88295208Stuexen struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_no_unlock, 89281955Shiren uint8_t mflowtype, 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, 104281955Shiren mflowtype, 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, 116281955Shiren mflowtype, 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, 126281955Shiren mflowtype, 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, 136281955Shiren mflowtype, 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, 146281955Shiren mflowtype, 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, 158281955Shiren mflowtype, 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, 189284633Stuexen mflowtype, mflowid, inp->fibnum, 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"); 201295208Stuexen sctp_send_initiate_ack(inp, stcb, net, m, iphlen, offset, 202295208Stuexen src, dst, sh, cp, 203281955Shiren mflowtype, 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 } 360294140Stuexen outs->state = SCTP_STREAM_CLOSED; 361163953Srrs } 362163953Srrs } 363196260Stuexen /* cut back the count */ 364163953Srrs asoc->pre_open_streams = newcnt; 365163953Srrs } 366164181Srrs SCTP_TCB_SEND_UNLOCK(stcb); 367294140Stuexen asoc->streamoutcnt = asoc->pre_open_streams; 368296052Stuexen if (asoc->strmout) { 369296052Stuexen for (i = 0; i < asoc->streamoutcnt; i++) { 370296052Stuexen asoc->strmout[i].state = SCTP_STREAM_OPEN; 371296052Stuexen } 372294140Stuexen } 373185694Srrs /* EY - nr_sack: initialize highest tsn in nr_mapping_array */ 374185694Srrs asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 375179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 376170744Srrs sctp_log_map(0, 5, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 377170744Srrs } 378163953Srrs /* This is the next one we expect */ 379163953Srrs asoc->str_reset_seq_in = asoc->asconf_seq_in + 1; 380163953Srrs 381163953Srrs asoc->mapping_array_base_tsn = ntohl(init->initial_tsn); 382180955Srrs asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->asconf_seq_in; 383218129Srrs 384163953Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 385163953Srrs /* open the requested streams */ 386170091Srrs 387163953Srrs if (asoc->strmin != NULL) { 388163953Srrs /* Free the old ones */ 389216822Stuexen struct sctp_queued_to_read *ctl, *nctl; 390164181Srrs 391164181Srrs for (i = 0; i < asoc->streamincnt; i++) { 392216822Stuexen TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) { 393164181Srrs TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next); 394164181Srrs sctp_free_remote_addr(ctl->whoFrom); 395171158Srrs ctl->whoFrom = NULL; 396164181Srrs sctp_m_freem(ctl->data); 397164181Srrs ctl->data = NULL; 398164181Srrs sctp_free_a_readq(stcb, ctl); 399164181Srrs } 400164181Srrs } 401170091Srrs SCTP_FREE(asoc->strmin, SCTP_M_STRMI); 402163953Srrs } 403252779Stuexen if (asoc->max_inbound_streams > ntohs(init->num_outbound_streams)) { 404252779Stuexen asoc->streamincnt = ntohs(init->num_outbound_streams); 405252779Stuexen } else { 406252779Stuexen asoc->streamincnt = asoc->max_inbound_streams; 407164181Srrs } 408163953Srrs SCTP_MALLOC(asoc->strmin, struct sctp_stream_in *, asoc->streamincnt * 409170091Srrs sizeof(struct sctp_stream_in), SCTP_M_STRMI); 410163953Srrs if (asoc->strmin == NULL) { 411163953Srrs /* we didn't get memory for the streams! */ 412169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "process_init: couldn't get memory for the streams!\n"); 413163953Srrs return (-1); 414163953Srrs } 415163953Srrs for (i = 0; i < asoc->streamincnt; i++) { 416163953Srrs asoc->strmin[i].stream_no = i; 417163953Srrs asoc->strmin[i].last_sequence_delivered = 0xffff; 418163953Srrs TAILQ_INIT(&asoc->strmin[i].inqueue); 419168943Srrs asoc->strmin[i].delivery_started = 0; 420163953Srrs } 421163953Srrs /* 422163953Srrs * load_address_from_init will put the addresses into the 423163953Srrs * association when the COOKIE is processed or the INIT-ACK is 424163953Srrs * processed. Both types of COOKIE's existing and new call this 425163953Srrs * routine. It will remove addresses that are no longer in the 426163953Srrs * association (for the restarting case where addresses are 427163953Srrs * removed). Up front when the INIT arrives we will discard it if it 428163953Srrs * is a restart and new addresses have been added. 429163953Srrs */ 430169655Srrs /* sa_ignore MEMLEAK */ 431163953Srrs return (0); 432163953Srrs} 433163953Srrs 434163953Srrs/* 435163953Srrs * INIT-ACK message processing/consumption returns value < 0 on error 436163953Srrs */ 437163953Srrsstatic int 438237715Stuexensctp_process_init_ack(struct mbuf *m, int iphlen, int offset, 439237715Stuexen struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 440237049Stuexen struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 441237049Stuexen struct sctp_nets *net, int *abort_no_unlock, 442281955Shiren uint8_t mflowtype, uint32_t mflowid, 443237049Stuexen uint32_t vrf_id) 444163953Srrs{ 445163953Srrs struct sctp_association *asoc; 446163953Srrs struct mbuf *op_err; 447163953Srrs int retval, abort_flag; 448163953Srrs uint32_t initack_limit; 449185694Srrs int nat_friendly = 0; 450163953Srrs 451163953Srrs /* First verify that we have no illegal param's */ 452163953Srrs abort_flag = 0; 453163953Srrs 454163953Srrs op_err = sctp_arethere_unrecognized_parameters(m, 455163953Srrs (offset + sizeof(struct sctp_init_chunk)), 456185694Srrs &abort_flag, (struct sctp_chunkhdr *)cp, &nat_friendly); 457163953Srrs if (abort_flag) { 458163953Srrs /* Send an abort and notify peer */ 459235360Stuexen sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 460170056Srrs *abort_no_unlock = 1; 461163953Srrs return (-1); 462163953Srrs } 463163953Srrs asoc = &stcb->asoc; 464185694Srrs asoc->peer_supports_nat = (uint8_t) nat_friendly; 465163953Srrs /* process the peer's parameters in the INIT-ACK */ 466228653Stuexen retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb); 467163953Srrs if (retval < 0) { 468163953Srrs return (retval); 469163953Srrs } 470163953Srrs initack_limit = offset + ntohs(cp->ch.chunk_length); 471163953Srrs /* load all addresses */ 472228653Stuexen if ((retval = sctp_load_addresses_from_init(stcb, m, 473237715Stuexen (offset + sizeof(struct sctp_init_chunk)), initack_limit, 474237715Stuexen src, dst, NULL))) { 475267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 476267723Stuexen "Problem with address parameters"); 477169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 478169420Srrs "Load addresses from INIT causes an abort %d\n", 479169420Srrs retval); 480237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 481267723Stuexen src, dst, sh, op_err, 482281955Shiren mflowtype, mflowid, 483237049Stuexen vrf_id, net->port); 484168299Srrs *abort_no_unlock = 1; 485163953Srrs return (-1); 486163953Srrs } 487171477Srrs /* if the peer doesn't support asconf, flush the asconf queue */ 488270362Stuexen if (asoc->asconf_supported == 0) { 489216822Stuexen struct sctp_asconf_addr *param, *nparam; 490171477Srrs 491216822Stuexen TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) { 492216822Stuexen TAILQ_REMOVE(&asoc->asconf_queue, param, next); 493216822Stuexen SCTP_FREE(param, SCTP_M_ASC_ADDR); 494171477Srrs } 495171477Srrs } 496163953Srrs stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs, 497163953Srrs stcb->asoc.local_hmacs); 498163953Srrs if (op_err) { 499163953Srrs sctp_queue_op_err(stcb, op_err); 500163953Srrs /* queuing will steal away the mbuf chain to the out queue */ 501163953Srrs op_err = NULL; 502163953Srrs } 503163953Srrs /* extract the cookie and queue it to "echo" it back... */ 504179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 505171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 506171943Srrs stcb->asoc.overall_error_count, 507171943Srrs 0, 508171943Srrs SCTP_FROM_SCTP_INPUT, 509171943Srrs __LINE__); 510171943Srrs } 511163953Srrs stcb->asoc.overall_error_count = 0; 512163953Srrs net->error_count = 0; 513163953Srrs 514163953Srrs /* 515163953Srrs * Cancel the INIT timer, We do this first before queueing the 516163953Srrs * cookie. We always cancel at the primary to assue that we are 517163953Srrs * canceling the timer started by the INIT which always goes to the 518163953Srrs * primary. 519163953Srrs */ 520163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb, 521283822Stuexen asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 522163953Srrs 523165220Srrs /* calculate the RTO */ 524218186Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy, 525219397Srrs SCTP_RTT_FROM_NON_DATA); 526163953Srrs retval = sctp_send_cookie_echo(m, offset, stcb, net); 527163953Srrs if (retval < 0) { 528163953Srrs /* 529163953Srrs * No cookie, we probably should send a op error. But in any 530163953Srrs * case if there is no cookie in the INIT-ACK, we can 531163953Srrs * abandon the peer, its broke. 532163953Srrs */ 533163953Srrs if (retval == -3) { 534294159Stuexen uint16_t len; 535294158Stuexen 536294159Stuexen len = (uint16_t) (sizeof(struct sctp_error_missing_param) + sizeof(uint16_t)); 537163953Srrs /* We abort with an error of missing mandatory param */ 538294158Stuexen op_err = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA); 539294158Stuexen if (op_err != NULL) { 540294158Stuexen struct sctp_error_missing_param *cause; 541163953Srrs 542294158Stuexen SCTP_BUF_LEN(op_err) = len; 543294158Stuexen cause = mtod(op_err, struct sctp_error_missing_param *); 544163953Srrs /* Subtract the reserved param */ 545294158Stuexen cause->cause.code = htons(SCTP_CAUSE_MISSING_PARAM); 546294158Stuexen cause->cause.length = htons(len); 547294158Stuexen cause->num_missing_params = htonl(1); 548294158Stuexen cause->type[0] = htons(SCTP_STATE_COOKIE); 549163953Srrs } 550163953Srrs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 551237715Stuexen src, dst, sh, op_err, 552281955Shiren mflowtype, 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); 636283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, 637283822Stuexen r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4); 638224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 639163953Srrs } 640224641Stuexen old_error_counter = r_net->error_count; 641163953Srrs r_net->error_count = 0; 642163953Srrs r_net->hb_responded = 1; 643163953Srrs tv.tv_sec = cp->heartbeat.hb_info.time_value_1; 644163953Srrs tv.tv_usec = cp->heartbeat.hb_info.time_value_2; 645224641Stuexen /* Now lets do a RTO with this */ 646224641Stuexen r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy, 647224641Stuexen SCTP_RTT_FROM_NON_DATA); 648224641Stuexen if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) { 649163953Srrs r_net->dest_state |= SCTP_ADDR_REACHABLE; 650163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 651235414Stuexen 0, (void *)r_net, SCTP_SO_NOT_LOCKED); 652163953Srrs } 653224641Stuexen if (r_net->dest_state & SCTP_ADDR_PF) { 654224641Stuexen r_net->dest_state &= ~SCTP_ADDR_PF; 655224641Stuexen stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net); 656224641Stuexen } 657224641Stuexen if (old_error_counter > 0) { 658283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, 659283822Stuexen stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_5); 660224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 661224641Stuexen } 662224641Stuexen if (r_net == stcb->asoc.primary_destination) { 663224641Stuexen if (stcb->asoc.alternate) { 664224641Stuexen /* release the alternate, primary is good */ 665224641Stuexen sctp_free_remote_addr(stcb->asoc.alternate); 666224641Stuexen stcb->asoc.alternate = NULL; 667171440Srrs } 668171440Srrs } 669172396Srrs /* Mobility adaptation */ 670172396Srrs if (req_prim) { 671172396Srrs if ((sctp_is_mobility_feature_on(stcb->sctp_ep, 672172396Srrs SCTP_MOBILITY_BASE) || 673172396Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 674172396Srrs SCTP_MOBILITY_FASTHANDOFF)) && 675172396Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 676172396Srrs SCTP_MOBILITY_PRIM_DELETED)) { 677172396Srrs 678283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, 679283822Stuexen stcb->sctp_ep, stcb, NULL, 680283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_6); 681172396Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 682172396Srrs SCTP_MOBILITY_FASTHANDOFF)) { 683172396Srrs sctp_assoc_immediate_retrans(stcb, 684172396Srrs stcb->asoc.primary_destination); 685172396Srrs } 686172396Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 687172396Srrs SCTP_MOBILITY_BASE)) { 688212712Stuexen sctp_move_chunks_from_net(stcb, 689212712Stuexen stcb->asoc.deleted_primary); 690172396Srrs } 691172396Srrs sctp_delete_prim_timer(stcb->sctp_ep, stcb, 692172396Srrs stcb->asoc.deleted_primary); 693172396Srrs } 694172396Srrs } 695163953Srrs} 696163953Srrs 697185694Srrsstatic int 698185694Srrssctp_handle_nat_colliding_state(struct sctp_tcb *stcb) 699185694Srrs{ 700185694Srrs /* 701185694Srrs * return 0 means we want you to proceed with the abort non-zero 702185694Srrs * means no abort processing 703185694Srrs */ 704185694Srrs struct sctpasochead *head; 705185694Srrs 706185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) { 707185694Srrs /* generate a new vtag and send init */ 708185694Srrs LIST_REMOVE(stcb, sctp_asocs); 709185694Srrs stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 710185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 711185694Srrs /* 712185694Srrs * put it in the bucket in the vtag hash of assoc's for the 713185694Srrs * system 714185694Srrs */ 715185694Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 716185694Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 717185694Srrs return (1); 718185694Srrs } 719185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 720185694Srrs /* 721185694Srrs * treat like a case where the cookie expired i.e.: - dump 722185694Srrs * current cookie. - generate a new vtag. - resend init. 723185694Srrs */ 724185694Srrs /* generate a new vtag and send init */ 725185694Srrs LIST_REMOVE(stcb, sctp_asocs); 726185694Srrs stcb->asoc.state &= ~SCTP_STATE_COOKIE_ECHOED; 727185694Srrs stcb->asoc.state |= SCTP_STATE_COOKIE_WAIT; 728185694Srrs sctp_stop_all_cookie_timers(stcb); 729185694Srrs sctp_toss_old_cookies(stcb, &stcb->asoc); 730185694Srrs stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 731185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 732185694Srrs /* 733185694Srrs * put it in the bucket in the vtag hash of assoc's for the 734185694Srrs * system 735185694Srrs */ 736185694Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 737185694Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 738185694Srrs return (1); 739185694Srrs } 740185694Srrs return (0); 741185694Srrs} 742185694Srrs 743185694Srrsstatic int 744185694Srrssctp_handle_nat_missing_state(struct sctp_tcb *stcb, 745185694Srrs struct sctp_nets *net) 746185694Srrs{ 747185694Srrs /* 748185694Srrs * return 0 means we want you to proceed with the abort non-zero 749185694Srrs * means no abort processing 750185694Srrs */ 751270362Stuexen if (stcb->asoc.auth_supported == 0) { 752185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n"); 753185694Srrs return (0); 754185694Srrs } 755185694Srrs sctp_asconf_send_nat_state_update(stcb, net); 756185694Srrs return (1); 757185694Srrs} 758185694Srrs 759185694Srrs 760163953Srrsstatic void 761235360Stuexensctp_handle_abort(struct sctp_abort_chunk *abort, 762163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 763163953Srrs{ 764237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 765172090Srrs struct socket *so; 766172090Srrs 767172090Srrs#endif 768185694Srrs uint16_t len; 769235360Stuexen uint16_t error; 770172090Srrs 771169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n"); 772163953Srrs if (stcb == NULL) 773163953Srrs return; 774163953Srrs 775235360Stuexen len = ntohs(abort->ch.chunk_length); 776185694Srrs if (len > sizeof(struct sctp_chunkhdr)) { 777185694Srrs /* 778185694Srrs * Need to check the cause codes for our two magic nat 779185694Srrs * aborts which don't kill the assoc necessarily. 780185694Srrs */ 781294158Stuexen struct sctp_gen_error_cause *cause; 782185694Srrs 783294158Stuexen cause = (struct sctp_gen_error_cause *)(abort + 1); 784294158Stuexen error = ntohs(cause->code); 785235360Stuexen if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) { 786185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 787235360Stuexen abort->ch.chunk_flags); 788185694Srrs if (sctp_handle_nat_colliding_state(stcb)) { 789185694Srrs return; 790185694Srrs } 791235360Stuexen } else if (error == SCTP_CAUSE_NAT_MISSING_STATE) { 792185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 793235360Stuexen abort->ch.chunk_flags); 794185694Srrs if (sctp_handle_nat_missing_state(stcb, net)) { 795185694Srrs return; 796185694Srrs } 797185694Srrs } 798235360Stuexen } else { 799235360Stuexen error = 0; 800185694Srrs } 801163953Srrs /* stop any receive timers */ 802283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, 803283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_7); 804163953Srrs /* notify user of the abort and clean up... */ 805235403Stuexen sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED); 806163953Srrs /* free the tcb */ 807163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_aborted); 808163953Srrs if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 809163953Srrs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 810163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 811163953Srrs } 812168859Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 813168859Srrs sctp_print_out_track_log(stcb); 814168859Srrs#endif 815237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 816172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 817172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 818172090Srrs SCTP_TCB_UNLOCK(stcb); 819172090Srrs SCTP_SOCKET_LOCK(so, 1); 820172090Srrs SCTP_TCB_LOCK(stcb); 821172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 822172090Srrs#endif 823171990Srrs stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 824171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 825283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_8); 826237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 827172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 828172090Srrs#endif 829169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n"); 830163953Srrs} 831163953Srrs 832163953Srrsstatic void 833224641Stuexensctp_start_net_timers(struct sctp_tcb *stcb) 834224641Stuexen{ 835224641Stuexen uint32_t cnt_hb_sent; 836224641Stuexen struct sctp_nets *net; 837224641Stuexen 838224641Stuexen cnt_hb_sent = 0; 839224641Stuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 840224641Stuexen /* 841224641Stuexen * For each network start: 1) A pmtu timer. 2) A HB timer 3) 842224641Stuexen * If the dest in unconfirmed send a hb as well if under 843224641Stuexen * max_hb_burst have been sent. 844224641Stuexen */ 845224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net); 846224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 847224641Stuexen if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) && 848224641Stuexen (cnt_hb_sent < SCTP_BASE_SYSCTL(sctp_hb_maxburst))) { 849224641Stuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 850224641Stuexen cnt_hb_sent++; 851224641Stuexen } 852224641Stuexen } 853224641Stuexen if (cnt_hb_sent) { 854224641Stuexen sctp_chunk_output(stcb->sctp_ep, stcb, 855224641Stuexen SCTP_OUTPUT_FROM_COOKIE_ACK, 856224641Stuexen SCTP_SO_NOT_LOCKED); 857224641Stuexen } 858224641Stuexen} 859224641Stuexen 860224641Stuexen 861224641Stuexenstatic void 862163953Srrssctp_handle_shutdown(struct sctp_shutdown_chunk *cp, 863163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag) 864163953Srrs{ 865163953Srrs struct sctp_association *asoc; 866163953Srrs int some_on_streamwheel; 867294152Stuexen int old_state; 868163953Srrs 869237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 870172090Srrs struct socket *so; 871172090Srrs 872172090Srrs#endif 873172090Srrs 874169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 875169420Srrs "sctp_handle_shutdown: handling SHUTDOWN\n"); 876163953Srrs if (stcb == NULL) 877163953Srrs return; 878165220Srrs asoc = &stcb->asoc; 879165220Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 880165220Srrs (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 881163953Srrs return; 882163953Srrs } 883163953Srrs if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) { 884163953Srrs /* Shutdown NOT the expected size */ 885163953Srrs return; 886163953Srrs } 887294152Stuexen old_state = SCTP_GET_STATE(asoc); 888294152Stuexen sctp_update_acked(stcb, cp, abort_flag); 889294152Stuexen if (*abort_flag) { 890294152Stuexen return; 891294152Stuexen } 892165220Srrs if (asoc->control_pdapi) { 893163953Srrs /* 894163953Srrs * With a normal shutdown we assume the end of last record. 895163953Srrs */ 896163953Srrs SCTP_INP_READ_LOCK(stcb->sctp_ep); 897165220Srrs asoc->control_pdapi->end_added = 1; 898165220Srrs asoc->control_pdapi->pdapi_aborted = 1; 899165220Srrs asoc->control_pdapi = NULL; 900163953Srrs SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 901237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 902172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 903172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 904172090Srrs SCTP_TCB_UNLOCK(stcb); 905172090Srrs SCTP_SOCKET_LOCK(so, 1); 906172090Srrs SCTP_TCB_LOCK(stcb); 907172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 908172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 909172090Srrs /* assoc was freed while we were unlocked */ 910172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 911172090Srrs return; 912172090Srrs } 913172090Srrs#endif 914296052Stuexen if (stcb->sctp_socket) { 915296052Stuexen sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 916296052Stuexen } 917237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 918172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 919172090Srrs#endif 920163953Srrs } 921163953Srrs /* goto SHUTDOWN_RECEIVED state to block new requests */ 922163953Srrs if (stcb->sctp_socket) { 923163953Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 924170056Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) && 925163953Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 926171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_RECEIVED); 927172703Srrs SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 928163953Srrs /* 929163953Srrs * notify upper layer that peer has initiated a 930163953Srrs * shutdown 931163953Srrs */ 932172090Srrs sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 933163953Srrs 934163953Srrs /* reset time */ 935169378Srrs (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 936163953Srrs } 937163953Srrs } 938163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) { 939163953Srrs /* 940163953Srrs * stop the shutdown timer, since we WILL move to 941163953Srrs * SHUTDOWN-ACK-SENT. 942163953Srrs */ 943283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, 944283822Stuexen net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9); 945163953Srrs } 946171158Srrs /* Now is there unsent data on a stream somewhere? */ 947221627Stuexen some_on_streamwheel = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED); 948163953Srrs 949163953Srrs if (!TAILQ_EMPTY(&asoc->send_queue) || 950163953Srrs !TAILQ_EMPTY(&asoc->sent_queue) || 951163953Srrs some_on_streamwheel) { 952163953Srrs /* By returning we will push more data out */ 953163953Srrs return; 954163953Srrs } else { 955163953Srrs /* no outstanding data to send, so move on... */ 956163953Srrs /* send SHUTDOWN-ACK */ 957163953Srrs /* move to SHUTDOWN-ACK-SENT state */ 958166675Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 959166675Srrs (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 960163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 961163953Srrs } 962172703Srrs SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 963294152Stuexen if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) { 964294152Stuexen SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); 965294152Stuexen sctp_stop_timers_for_shutdown(stcb); 966294152Stuexen sctp_send_shutdown_ack(stcb, net); 967294152Stuexen sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, 968294152Stuexen stcb->sctp_ep, stcb, net); 969294152Stuexen } else if (old_state == SCTP_STATE_SHUTDOWN_ACK_SENT) { 970294152Stuexen sctp_send_shutdown_ack(stcb, net); 971294152Stuexen } 972163953Srrs } 973163953Srrs} 974163953Srrs 975163953Srrsstatic void 976228653Stuexensctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, 977204141Stuexen struct sctp_tcb *stcb, 978204141Stuexen struct sctp_nets *net) 979163953Srrs{ 980163953Srrs struct sctp_association *asoc; 981163953Srrs 982237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 983172090Srrs struct socket *so; 984172090Srrs 985172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 986172090Srrs#endif 987169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 988169420Srrs "sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n"); 989163953Srrs if (stcb == NULL) 990163953Srrs return; 991163953Srrs 992163953Srrs asoc = &stcb->asoc; 993163953Srrs /* process according to association state */ 994204141Stuexen if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 995204141Stuexen (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 996204141Stuexen /* unexpected SHUTDOWN-ACK... do OOTB handling... */ 997204141Stuexen sctp_send_shutdown_complete(stcb, net, 1); 998204141Stuexen SCTP_TCB_UNLOCK(stcb); 999204141Stuexen return; 1000204141Stuexen } 1001163953Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) && 1002163953Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { 1003163953Srrs /* unexpected SHUTDOWN-ACK... so ignore... */ 1004163953Srrs SCTP_TCB_UNLOCK(stcb); 1005163953Srrs return; 1006163953Srrs } 1007165220Srrs if (asoc->control_pdapi) { 1008163953Srrs /* 1009163953Srrs * With a normal shutdown we assume the end of last record. 1010163953Srrs */ 1011163953Srrs SCTP_INP_READ_LOCK(stcb->sctp_ep); 1012165220Srrs asoc->control_pdapi->end_added = 1; 1013165220Srrs asoc->control_pdapi->pdapi_aborted = 1; 1014165220Srrs asoc->control_pdapi = NULL; 1015163953Srrs SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 1016237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1017172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1018172090Srrs SCTP_TCB_UNLOCK(stcb); 1019172090Srrs SCTP_SOCKET_LOCK(so, 1); 1020172090Srrs SCTP_TCB_LOCK(stcb); 1021172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1022172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1023172090Srrs /* assoc was freed while we were unlocked */ 1024172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1025172090Srrs return; 1026172090Srrs } 1027172090Srrs#endif 1028163996Srrs sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 1029237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1030172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1031172090Srrs#endif 1032163953Srrs } 1033252585Stuexen#ifdef INVARIANTS 1034163953Srrs if (!TAILQ_EMPTY(&asoc->send_queue) || 1035163953Srrs !TAILQ_EMPTY(&asoc->sent_queue) || 1036217760Stuexen !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 1037252585Stuexen panic("Queues are not empty when handling SHUTDOWN-ACK"); 1038163953Srrs } 1039252585Stuexen#endif 1040163953Srrs /* stop the timer */ 1041283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, 1042283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_10); 1043163953Srrs /* send SHUTDOWN-COMPLETE */ 1044204141Stuexen sctp_send_shutdown_complete(stcb, net, 0); 1045163953Srrs /* notify upper layer protocol */ 1046163953Srrs if (stcb->sctp_socket) { 1047163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1048163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 1049229774Stuexen stcb->sctp_socket->so_snd.sb_cc = 0; 1050163953Srrs } 1051230379Stuexen sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1052163953Srrs } 1053163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 1054163953Srrs /* free the TCB but first save off the ep */ 1055237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1056172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1057172090Srrs SCTP_TCB_UNLOCK(stcb); 1058172090Srrs SCTP_SOCKET_LOCK(so, 1); 1059172090Srrs SCTP_TCB_LOCK(stcb); 1060172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1061172090Srrs#endif 1062171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 1063283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_11); 1064237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1065172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1066172090Srrs#endif 1067163953Srrs} 1068163953Srrs 1069163953Srrs/* 1070163953Srrs * Skip past the param header and then we will find the chunk that caused the 1071163953Srrs * problem. There are two possiblities ASCONF or FWD-TSN other than that and 1072163953Srrs * our peer must be broken. 1073163953Srrs */ 1074163953Srrsstatic void 1075163953Srrssctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr, 1076163953Srrs struct sctp_nets *net) 1077163953Srrs{ 1078163953Srrs struct sctp_chunkhdr *chk; 1079163953Srrs 1080163953Srrs chk = (struct sctp_chunkhdr *)((caddr_t)phdr + sizeof(*phdr)); 1081163953Srrs switch (chk->chunk_type) { 1082163953Srrs case SCTP_ASCONF_ACK: 1083163953Srrs case SCTP_ASCONF: 1084163953Srrs sctp_asconf_cleanup(stcb, net); 1085163953Srrs break; 1086163953Srrs case SCTP_FORWARD_CUM_TSN: 1087270357Stuexen stcb->asoc.prsctp_supported = 0; 1088163953Srrs break; 1089163953Srrs default: 1090169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1091169420Srrs "Peer does not support chunk type %d(%x)??\n", 1092169420Srrs chk->chunk_type, (uint32_t) chk->chunk_type); 1093163953Srrs break; 1094163953Srrs } 1095163953Srrs} 1096163953Srrs 1097163953Srrs/* 1098163953Srrs * Skip past the param header and then we will find the param that caused the 1099163953Srrs * problem. There are a number of param's in a ASCONF OR the prsctp param 1100163953Srrs * these will turn of specific features. 1101270362Stuexen * XXX: Is this the right thing to do? 1102163953Srrs */ 1103163953Srrsstatic void 1104163953Srrssctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr) 1105163953Srrs{ 1106163953Srrs struct sctp_paramhdr *pbad; 1107163953Srrs 1108163953Srrs pbad = phdr + 1; 1109163953Srrs switch (ntohs(pbad->param_type)) { 1110163953Srrs /* pr-sctp draft */ 1111163953Srrs case SCTP_PRSCTP_SUPPORTED: 1112270357Stuexen stcb->asoc.prsctp_supported = 0; 1113163953Srrs break; 1114163953Srrs case SCTP_SUPPORTED_CHUNK_EXT: 1115163953Srrs break; 1116163953Srrs /* draft-ietf-tsvwg-addip-sctp */ 1117185694Srrs case SCTP_HAS_NAT_SUPPORT: 1118185694Srrs stcb->asoc.peer_supports_nat = 0; 1119185694Srrs break; 1120163953Srrs case SCTP_ADD_IP_ADDRESS: 1121163953Srrs case SCTP_DEL_IP_ADDRESS: 1122163953Srrs case SCTP_SET_PRIM_ADDR: 1123270362Stuexen stcb->asoc.asconf_supported = 0; 1124163953Srrs break; 1125163953Srrs case SCTP_SUCCESS_REPORT: 1126163953Srrs case SCTP_ERROR_CAUSE_IND: 1127169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support success? or error cause?\n"); 1128169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1129169420Srrs "Turning off ASCONF to this strange peer\n"); 1130270362Stuexen stcb->asoc.asconf_supported = 0; 1131163953Srrs break; 1132163953Srrs default: 1133169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1134169420Srrs "Peer does not support param type %d(%x)??\n", 1135169420Srrs pbad->param_type, (uint32_t) pbad->param_type); 1136163953Srrs break; 1137163953Srrs } 1138163953Srrs} 1139163953Srrs 1140163953Srrsstatic int 1141163953Srrssctp_handle_error(struct sctp_chunkhdr *ch, 1142163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 1143163953Srrs{ 1144163953Srrs int chklen; 1145163953Srrs struct sctp_paramhdr *phdr; 1146235418Stuexen uint16_t error, error_type; 1147163953Srrs uint16_t error_len; 1148163953Srrs struct sctp_association *asoc; 1149163953Srrs int adjust; 1150163953Srrs 1151237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1152172090Srrs struct socket *so; 1153172090Srrs 1154172090Srrs#endif 1155172090Srrs 1156163953Srrs /* parse through all of the errors and process */ 1157163953Srrs asoc = &stcb->asoc; 1158163953Srrs phdr = (struct sctp_paramhdr *)((caddr_t)ch + 1159163953Srrs sizeof(struct sctp_chunkhdr)); 1160163953Srrs chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr); 1161235418Stuexen error = 0; 1162163953Srrs while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) { 1163163953Srrs /* Process an Error Cause */ 1164163953Srrs error_type = ntohs(phdr->param_type); 1165163953Srrs error_len = ntohs(phdr->param_length); 1166163953Srrs if ((error_len > chklen) || (error_len == 0)) { 1167163953Srrs /* invalid param length for this param */ 1168169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Bogus length in error param- chunk left:%d errorlen:%d\n", 1169169420Srrs chklen, error_len); 1170163953Srrs return (0); 1171163953Srrs } 1172235418Stuexen if (error == 0) { 1173235418Stuexen /* report the first error cause */ 1174235418Stuexen error = error_type; 1175235418Stuexen } 1176163953Srrs switch (error_type) { 1177163953Srrs case SCTP_CAUSE_INVALID_STREAM: 1178163953Srrs case SCTP_CAUSE_MISSING_PARAM: 1179163953Srrs case SCTP_CAUSE_INVALID_PARAM: 1180163953Srrs case SCTP_CAUSE_NO_USER_DATA: 1181169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Software error we got a %d back? We have a bug :/ (or do they?)\n", 1182169420Srrs error_type); 1183163953Srrs break; 1184185694Srrs case SCTP_CAUSE_NAT_COLLIDING_STATE: 1185185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 1186185694Srrs ch->chunk_flags); 1187185694Srrs if (sctp_handle_nat_colliding_state(stcb)) { 1188185694Srrs return (0); 1189185694Srrs } 1190185694Srrs break; 1191185694Srrs case SCTP_CAUSE_NAT_MISSING_STATE: 1192185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 1193185694Srrs ch->chunk_flags); 1194185694Srrs if (sctp_handle_nat_missing_state(stcb, net)) { 1195185694Srrs return (0); 1196185694Srrs } 1197185694Srrs break; 1198163953Srrs case SCTP_CAUSE_STALE_COOKIE: 1199163953Srrs /* 1200163953Srrs * We only act if we have echoed a cookie and are 1201163953Srrs * waiting. 1202163953Srrs */ 1203163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 1204163953Srrs int *p; 1205163953Srrs 1206163953Srrs p = (int *)((caddr_t)phdr + sizeof(*phdr)); 1207163953Srrs /* Save the time doubled */ 1208163953Srrs asoc->cookie_preserve_req = ntohl(*p) << 1; 1209163953Srrs asoc->stale_cookie_count++; 1210163953Srrs if (asoc->stale_cookie_count > 1211163953Srrs asoc->max_init_times) { 1212235403Stuexen sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); 1213163953Srrs /* now free the asoc */ 1214237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1215172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1216172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1217172090Srrs SCTP_TCB_UNLOCK(stcb); 1218172090Srrs SCTP_SOCKET_LOCK(so, 1); 1219172090Srrs SCTP_TCB_LOCK(stcb); 1220172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1221172090Srrs#endif 1222171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 1223283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_12); 1224237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1225172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1226172090Srrs#endif 1227163953Srrs return (-1); 1228163953Srrs } 1229163953Srrs /* blast back to INIT state */ 1230185694Srrs sctp_toss_old_cookies(stcb, &stcb->asoc); 1231163953Srrs asoc->state &= ~SCTP_STATE_COOKIE_ECHOED; 1232163953Srrs asoc->state |= SCTP_STATE_COOKIE_WAIT; 1233163953Srrs sctp_stop_all_cookie_timers(stcb); 1234172090Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 1235163953Srrs } 1236163953Srrs break; 1237163953Srrs case SCTP_CAUSE_UNRESOLVABLE_ADDR: 1238163953Srrs /* 1239163953Srrs * Nothing we can do here, we don't do hostname 1240163953Srrs * addresses so if the peer does not like my IPv6 1241163953Srrs * (or IPv4 for that matter) it does not matter. If 1242163953Srrs * they don't support that type of address, they can 1243163953Srrs * NOT possibly get that packet type... i.e. with no 1244163953Srrs * IPv6 you can't recieve a IPv6 packet. so we can 1245163953Srrs * safely ignore this one. If we ever added support 1246163953Srrs * for HOSTNAME Addresses, then we would need to do 1247163953Srrs * something here. 1248163953Srrs */ 1249163953Srrs break; 1250163953Srrs case SCTP_CAUSE_UNRECOG_CHUNK: 1251163953Srrs sctp_process_unrecog_chunk(stcb, phdr, net); 1252163953Srrs break; 1253163953Srrs case SCTP_CAUSE_UNRECOG_PARAM: 1254163953Srrs sctp_process_unrecog_param(stcb, phdr); 1255163953Srrs break; 1256163953Srrs case SCTP_CAUSE_COOKIE_IN_SHUTDOWN: 1257163953Srrs /* 1258163953Srrs * We ignore this since the timer will drive out a 1259163953Srrs * new cookie anyway and there timer will drive us 1260163953Srrs * to send a SHUTDOWN_COMPLETE. We can't send one 1261163953Srrs * here since we don't have their tag. 1262163953Srrs */ 1263163953Srrs break; 1264163953Srrs case SCTP_CAUSE_DELETING_LAST_ADDR: 1265163953Srrs case SCTP_CAUSE_RESOURCE_SHORTAGE: 1266163953Srrs case SCTP_CAUSE_DELETING_SRC_ADDR: 1267163953Srrs /* 1268163953Srrs * We should NOT get these here, but in a 1269166086Srrs * ASCONF-ACK. 1270163953Srrs */ 1271169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Peer sends ASCONF errors in a Operational Error?<%d>?\n", 1272169420Srrs error_type); 1273163953Srrs break; 1274163953Srrs case SCTP_CAUSE_OUT_OF_RESC: 1275163953Srrs /* 1276163953Srrs * And what, pray tell do we do with the fact that 1277163953Srrs * the peer is out of resources? Not really sure we 1278166086Srrs * could do anything but abort. I suspect this 1279163953Srrs * should have came WITH an abort instead of in a 1280163953Srrs * OP-ERROR. 1281163953Srrs */ 1282163953Srrs break; 1283163953Srrs default: 1284169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_handle_error: unknown error type = 0x%xh\n", 1285169420Srrs error_type); 1286163953Srrs break; 1287163953Srrs } 1288163953Srrs adjust = SCTP_SIZE32(error_len); 1289163953Srrs chklen -= adjust; 1290163953Srrs phdr = (struct sctp_paramhdr *)((caddr_t)phdr + adjust); 1291163953Srrs } 1292235418Stuexen sctp_ulp_notify(SCTP_NOTIFY_REMOTE_ERROR, stcb, error, ch, SCTP_SO_NOT_LOCKED); 1293163953Srrs return (0); 1294163953Srrs} 1295163953Srrs 1296163953Srrsstatic int 1297237715Stuexensctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, 1298237715Stuexen struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 1299237049Stuexen struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 1300237049Stuexen struct sctp_nets *net, int *abort_no_unlock, 1301281955Shiren uint8_t mflowtype, uint32_t mflowid, 1302237049Stuexen uint32_t vrf_id) 1303163953Srrs{ 1304163953Srrs struct sctp_init_ack *init_ack; 1305163953Srrs struct mbuf *op_err; 1306163953Srrs 1307169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1308169420Srrs "sctp_handle_init_ack: handling INIT-ACK\n"); 1309169420Srrs 1310163953Srrs if (stcb == NULL) { 1311169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1312169420Srrs "sctp_handle_init_ack: TCB is null\n"); 1313163953Srrs return (-1); 1314163953Srrs } 1315163953Srrs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) { 1316163953Srrs /* Invalid length */ 1317267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1318237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1319237715Stuexen src, dst, sh, op_err, 1320281955Shiren mflowtype, mflowid, 1321237049Stuexen vrf_id, net->port); 1322168299Srrs *abort_no_unlock = 1; 1323163953Srrs return (-1); 1324163953Srrs } 1325163953Srrs init_ack = &cp->init; 1326163953Srrs /* validate parameters */ 1327163953Srrs if (init_ack->initiate_tag == 0) { 1328163953Srrs /* protocol error... send an abort */ 1329267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1330237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1331237715Stuexen src, dst, sh, op_err, 1332281955Shiren mflowtype, mflowid, 1333237049Stuexen vrf_id, net->port); 1334168299Srrs *abort_no_unlock = 1; 1335163953Srrs return (-1); 1336163953Srrs } 1337163953Srrs if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) { 1338163953Srrs /* protocol error... send an abort */ 1339267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1340237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1341237715Stuexen src, dst, sh, op_err, 1342281955Shiren mflowtype, mflowid, 1343237049Stuexen vrf_id, net->port); 1344168299Srrs *abort_no_unlock = 1; 1345163953Srrs return (-1); 1346163953Srrs } 1347163953Srrs if (init_ack->num_inbound_streams == 0) { 1348163953Srrs /* protocol error... send an abort */ 1349267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1350237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1351237715Stuexen src, dst, sh, op_err, 1352281955Shiren mflowtype, mflowid, 1353237049Stuexen vrf_id, net->port); 1354168299Srrs *abort_no_unlock = 1; 1355163953Srrs return (-1); 1356163953Srrs } 1357163953Srrs if (init_ack->num_outbound_streams == 0) { 1358163953Srrs /* protocol error... send an abort */ 1359267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1360237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1361237715Stuexen src, dst, sh, op_err, 1362281955Shiren mflowtype, mflowid, 1363237049Stuexen vrf_id, net->port); 1364168299Srrs *abort_no_unlock = 1; 1365163953Srrs return (-1); 1366163953Srrs } 1367163953Srrs /* process according to association state... */ 1368171943Srrs switch (stcb->asoc.state & SCTP_STATE_MASK) { 1369163953Srrs case SCTP_STATE_COOKIE_WAIT: 1370163953Srrs /* this is the expected state for this chunk */ 1371163953Srrs /* process the INIT-ACK parameters */ 1372163953Srrs if (stcb->asoc.primary_destination->dest_state & 1373163953Srrs SCTP_ADDR_UNCONFIRMED) { 1374163953Srrs /* 1375163953Srrs * The primary is where we sent the INIT, we can 1376163953Srrs * always consider it confirmed when the INIT-ACK is 1377163953Srrs * returned. Do this before we load addresses 1378163953Srrs * though. 1379163953Srrs */ 1380163953Srrs stcb->asoc.primary_destination->dest_state &= 1381163953Srrs ~SCTP_ADDR_UNCONFIRMED; 1382163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 1383172090Srrs stcb, 0, (void *)stcb->asoc.primary_destination, SCTP_SO_NOT_LOCKED); 1384163953Srrs } 1385237715Stuexen if (sctp_process_init_ack(m, iphlen, offset, src, dst, sh, cp, stcb, 1386237049Stuexen net, abort_no_unlock, 1387281955Shiren mflowtype, mflowid, 1388237049Stuexen vrf_id) < 0) { 1389163953Srrs /* error in parsing parameters */ 1390163953Srrs return (-1); 1391163953Srrs } 1392163953Srrs /* update our state */ 1393169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to COOKIE-ECHOED state\n"); 1394171943Srrs SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_ECHOED); 1395163953Srrs 1396163953Srrs /* reset the RTO calc */ 1397179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1398171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1399171943Srrs stcb->asoc.overall_error_count, 1400171943Srrs 0, 1401171943Srrs SCTP_FROM_SCTP_INPUT, 1402171943Srrs __LINE__); 1403171943Srrs } 1404163953Srrs stcb->asoc.overall_error_count = 0; 1405169378Srrs (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 1406163953Srrs /* 1407163953Srrs * collapse the init timer back in case of a exponential 1408165220Srrs * backoff 1409163953Srrs */ 1410163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep, 1411163953Srrs stcb, net); 1412163953Srrs /* 1413163953Srrs * the send at the end of the inbound data processing will 1414163953Srrs * cause the cookie to be sent 1415163953Srrs */ 1416163953Srrs break; 1417163953Srrs case SCTP_STATE_SHUTDOWN_SENT: 1418163953Srrs /* incorrect state... discard */ 1419163953Srrs break; 1420163953Srrs case SCTP_STATE_COOKIE_ECHOED: 1421163953Srrs /* incorrect state... discard */ 1422163953Srrs break; 1423163953Srrs case SCTP_STATE_OPEN: 1424163953Srrs /* incorrect state... discard */ 1425163953Srrs break; 1426163953Srrs case SCTP_STATE_EMPTY: 1427163953Srrs case SCTP_STATE_INUSE: 1428163953Srrs default: 1429163953Srrs /* incorrect state... discard */ 1430163953Srrs return (-1); 1431163953Srrs break; 1432163953Srrs } 1433169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Leaving handle-init-ack end\n"); 1434163953Srrs return (0); 1435163953Srrs} 1436163953Srrs 1437185694Srrsstatic struct sctp_tcb * 1438185694Srrssctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 1439237715Stuexen struct sockaddr *src, struct sockaddr *dst, 1440185694Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 1441185694Srrs struct sctp_inpcb *inp, struct sctp_nets **netp, 1442185694Srrs struct sockaddr *init_src, int *notification, 1443185694Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1444281955Shiren uint8_t mflowtype, uint32_t mflowid, 1445185694Srrs uint32_t vrf_id, uint16_t port); 1446163953Srrs 1447185694Srrs 1448163953Srrs/* 1449163953Srrs * handle a state cookie for an existing association m: input packet mbuf 1450163953Srrs * chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a 1451163953Srrs * "split" mbuf and the cookie signature does not exist offset: offset into 1452163953Srrs * mbuf to the cookie-echo chunk 1453163953Srrs */ 1454163953Srrsstatic struct sctp_tcb * 1455163953Srrssctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, 1456237715Stuexen struct sockaddr *src, struct sockaddr *dst, 1457163953Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 1458185694Srrs struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp, 1459228653Stuexen struct sockaddr *init_src, int *notification, 1460237049Stuexen int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1461281955Shiren uint8_t mflowtype, uint32_t mflowid, 1462237049Stuexen uint32_t vrf_id, uint16_t port) 1463163953Srrs{ 1464163953Srrs struct sctp_association *asoc; 1465163953Srrs struct sctp_init_chunk *init_cp, init_buf; 1466163953Srrs struct sctp_init_ack_chunk *initack_cp, initack_buf; 1467185694Srrs struct sctp_nets *net; 1468185694Srrs struct mbuf *op_err; 1469165220Srrs int init_offset, initack_offset, i; 1470163953Srrs int retval; 1471164205Srrs int spec_flag = 0; 1472170140Srrs uint32_t how_indx; 1473163953Srrs 1474270363Stuexen#if defined(SCTP_DETAILED_STR_STATS) 1475270363Stuexen int j; 1476270363Stuexen 1477270363Stuexen#endif 1478270363Stuexen 1479185694Srrs net = *netp; 1480163953Srrs /* I know that the TCB is non-NULL from the caller */ 1481163953Srrs asoc = &stcb->asoc; 1482166675Srrs for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); how_indx++) { 1483166023Srrs if (asoc->cookie_how[how_indx] == 0) 1484166023Srrs break; 1485166023Srrs } 1486166023Srrs if (how_indx < sizeof(asoc->cookie_how)) { 1487166023Srrs asoc->cookie_how[how_indx] = 1; 1488166023Srrs } 1489163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 1490163953Srrs /* SHUTDOWN came in after sending INIT-ACK */ 1491163953Srrs sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination); 1492267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, ""); 1493237715Stuexen sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, 1494284633Stuexen mflowtype, mflowid, inp->fibnum, 1495179157Srrs vrf_id, net->port); 1496166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1497166023Srrs asoc->cookie_how[how_indx] = 2; 1498163953Srrs return (NULL); 1499163953Srrs } 1500163953Srrs /* 1501163953Srrs * find and validate the INIT chunk in the cookie (peer's info) the 1502163953Srrs * INIT should start after the cookie-echo header struct (chunk 1503163953Srrs * header, state cookie header struct) 1504163953Srrs */ 1505163953Srrs init_offset = offset += sizeof(struct sctp_cookie_echo_chunk); 1506163953Srrs 1507163953Srrs init_cp = (struct sctp_init_chunk *) 1508163953Srrs sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 1509163953Srrs (uint8_t *) & init_buf); 1510163953Srrs if (init_cp == NULL) { 1511163953Srrs /* could not pull a INIT chunk in cookie */ 1512163953Srrs return (NULL); 1513163953Srrs } 1514163953Srrs if (init_cp->ch.chunk_type != SCTP_INITIATION) { 1515163953Srrs return (NULL); 1516163953Srrs } 1517163953Srrs /* 1518163953Srrs * find and validate the INIT-ACK chunk in the cookie (my info) the 1519163953Srrs * INIT-ACK follows the INIT chunk 1520163953Srrs */ 1521228907Stuexen initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 1522163953Srrs initack_cp = (struct sctp_init_ack_chunk *) 1523163953Srrs sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 1524163953Srrs (uint8_t *) & initack_buf); 1525163953Srrs if (initack_cp == NULL) { 1526163953Srrs /* could not pull INIT-ACK chunk in cookie */ 1527163953Srrs return (NULL); 1528163953Srrs } 1529163953Srrs if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 1530163953Srrs return (NULL); 1531163953Srrs } 1532163953Srrs if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1533163953Srrs (ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag)) { 1534163953Srrs /* 1535163953Srrs * case D in Section 5.2.4 Table 2: MMAA process accordingly 1536163953Srrs * to get into the OPEN state 1537163953Srrs */ 1538166023Srrs if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 1539172091Srrs /*- 1540172091Srrs * Opps, this means that we somehow generated two vtag's 1541172091Srrs * the same. I.e. we did: 1542172091Srrs * Us Peer 1543172091Srrs * <---INIT(tag=a)------ 1544172091Srrs * ----INIT-ACK(tag=t)--> 1545172091Srrs * ----INIT(tag=t)------> *1 1546172091Srrs * <---INIT-ACK(tag=a)--- 1547172091Srrs * <----CE(tag=t)------------- *2 1548172091Srrs * 1549172091Srrs * At point *1 we should be generating a different 1550172091Srrs * tag t'. Which means we would throw away the CE and send 1551172091Srrs * ours instead. Basically this is case C (throw away side). 1552172091Srrs */ 1553172091Srrs if (how_indx < sizeof(asoc->cookie_how)) 1554172091Srrs asoc->cookie_how[how_indx] = 17; 1555172091Srrs return (NULL); 1556172091Srrs 1557166023Srrs } 1558267720Stuexen switch (SCTP_GET_STATE(asoc)) { 1559163953Srrs case SCTP_STATE_COOKIE_WAIT: 1560166023Srrs case SCTP_STATE_COOKIE_ECHOED: 1561163953Srrs /* 1562169352Srrs * INIT was sent but got a COOKIE_ECHO with the 1563166023Srrs * correct tags... just accept it...but we must 1564166023Srrs * process the init so that we can make sure we have 1565166023Srrs * the right seq no's. 1566163953Srrs */ 1567163953Srrs /* First we must process the INIT !! */ 1568228653Stuexen retval = sctp_process_init(init_cp, stcb); 1569163953Srrs if (retval < 0) { 1570166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1571166023Srrs asoc->cookie_how[how_indx] = 3; 1572163953Srrs return (NULL); 1573163953Srrs } 1574163953Srrs /* we have already processed the INIT so no problem */ 1575283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, 1576283822Stuexen stcb, net, 1577283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_13); 1578283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, 1579283822Stuexen stcb, net, 1580283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_14); 1581163953Srrs /* update current state */ 1582166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 1583166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 1584166675Srrs else 1585166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1586171943Srrs 1587171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1588163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1589163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1590163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1591163953Srrs } 1592166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1593165220Srrs sctp_stop_all_cookie_timers(stcb); 1594163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1595163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1596163953Srrs (inp->sctp_socket->so_qlimit == 0) 1597163953Srrs ) { 1598237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1599172090Srrs struct socket *so; 1600172090Srrs 1601172090Srrs#endif 1602163953Srrs /* 1603163953Srrs * Here is where collision would go if we 1604163953Srrs * did a connect() and instead got a 1605163953Srrs * init/init-ack/cookie done before the 1606163953Srrs * init-ack came back.. 1607163953Srrs */ 1608163953Srrs stcb->sctp_ep->sctp_flags |= 1609163953Srrs SCTP_PCB_FLAGS_CONNECTED; 1610237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1611172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1612172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1613172090Srrs SCTP_TCB_UNLOCK(stcb); 1614172090Srrs SCTP_SOCKET_LOCK(so, 1); 1615172090Srrs SCTP_TCB_LOCK(stcb); 1616172090Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1617172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1618172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1619172090Srrs return (NULL); 1620172090Srrs } 1621172090Srrs#endif 1622172090Srrs soisconnected(stcb->sctp_socket); 1623237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1624172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1625172090Srrs#endif 1626163953Srrs } 1627163953Srrs /* notify upper layer */ 1628163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 1629163953Srrs /* 1630163953Srrs * since we did not send a HB make sure we don't 1631163953Srrs * double things 1632163953Srrs */ 1633163953Srrs net->hb_responded = 1; 1634170642Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, 1635218186Srrs &cookie->time_entered, 1636218186Srrs sctp_align_unsafe_makecopy, 1637219397Srrs SCTP_RTT_FROM_NON_DATA); 1638163953Srrs 1639163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 1640163953Srrs (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) { 1641163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 1642163953Srrs inp, stcb, NULL); 1643163953Srrs } 1644163953Srrs break; 1645163953Srrs default: 1646163953Srrs /* 1647163953Srrs * we're in the OPEN state (or beyond), so peer must 1648163953Srrs * have simply lost the COOKIE-ACK 1649163953Srrs */ 1650163953Srrs break; 1651267720Stuexen } /* end switch */ 1652165220Srrs sctp_stop_all_cookie_timers(stcb); 1653163953Srrs /* 1654163953Srrs * We ignore the return code here.. not sure if we should 1655163953Srrs * somehow abort.. but we do have an existing asoc. This 1656163953Srrs * really should not fail. 1657163953Srrs */ 1658228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1659163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1660237715Stuexen initack_offset, src, dst, init_src)) { 1661166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1662166023Srrs asoc->cookie_how[how_indx] = 4; 1663163953Srrs return (NULL); 1664163953Srrs } 1665163953Srrs /* respond with a COOKIE-ACK */ 1666165220Srrs sctp_toss_old_cookies(stcb, asoc); 1667163953Srrs sctp_send_cookie_ack(stcb); 1668166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1669166023Srrs asoc->cookie_how[how_indx] = 5; 1670163953Srrs return (stcb); 1671169352Srrs } 1672163953Srrs if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 1673163953Srrs ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag && 1674163953Srrs cookie->tie_tag_my_vtag == 0 && 1675163953Srrs cookie->tie_tag_peer_vtag == 0) { 1676163953Srrs /* 1677163953Srrs * case C in Section 5.2.4 Table 2: XMOO silently discard 1678163953Srrs */ 1679166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1680166023Srrs asoc->cookie_how[how_indx] = 6; 1681163953Srrs return (NULL); 1682163953Srrs } 1683185694Srrs /* 1684185694Srrs * If nat support, and the below and stcb is established, send back 1685185694Srrs * a ABORT(colliding state) if we are established. 1686185694Srrs */ 1687185694Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) && 1688185694Srrs (asoc->peer_supports_nat) && 1689185694Srrs ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1690185694Srrs ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 1691185694Srrs (asoc->peer_vtag == 0)))) { 1692163953Srrs /* 1693185694Srrs * Special case - Peer's support nat. We may have two init's 1694185694Srrs * that we gave out the same tag on since one was not 1695185694Srrs * established.. i.e. we get INIT from host-1 behind the nat 1696185694Srrs * and we respond tag-a, we get a INIT from host-2 behind 1697185694Srrs * the nat and we get tag-a again. Then we bring up host-1 1698185694Srrs * (or 2's) assoc, Then comes the cookie from hsot-2 (or 1). 1699185694Srrs * Now we have colliding state. We must send an abort here 1700185694Srrs * with colliding state indication. 1701185694Srrs */ 1702267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_NAT_COLLIDING_STATE, ""); 1703237715Stuexen sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, 1704284633Stuexen mflowtype, mflowid, inp->fibnum, 1705237049Stuexen vrf_id, port); 1706185694Srrs return (NULL); 1707185694Srrs } 1708185694Srrs if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1709185694Srrs ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 1710185694Srrs (asoc->peer_vtag == 0))) { 1711185694Srrs /* 1712163953Srrs * case B in Section 5.2.4 Table 2: MXAA or MOAA my info 1713163953Srrs * should be ok, re-accept peer info 1714163953Srrs */ 1715166023Srrs if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 1716166023Srrs /* 1717166023Srrs * Extension of case C. If we hit this, then the 1718166023Srrs * random number generator returned the same vtag 1719166023Srrs * when we first sent our INIT-ACK and when we later 1720166023Srrs * sent our INIT. The side with the seq numbers that 1721166023Srrs * are different will be the one that normnally 1722166023Srrs * would have hit case C. This in effect "extends" 1723166023Srrs * our vtags in this collision case to be 64 bits. 1724166023Srrs * The same collision could occur aka you get both 1725166023Srrs * vtag and seq number the same twice in a row.. but 1726166023Srrs * is much less likely. If it did happen then we 1727166023Srrs * would proceed through and bring up the assoc.. we 1728166023Srrs * may end up with the wrong stream setup however.. 1729166023Srrs * which would be bad.. but there is no way to 1730166023Srrs * tell.. until we send on a stream that does not 1731166023Srrs * exist :-) 1732166023Srrs */ 1733166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1734166023Srrs asoc->cookie_how[how_indx] = 7; 1735166023Srrs 1736166023Srrs return (NULL); 1737166023Srrs } 1738166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1739166023Srrs asoc->cookie_how[how_indx] = 8; 1740283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, 1741283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_15); 1742163953Srrs sctp_stop_all_cookie_timers(stcb); 1743163953Srrs /* 1744163953Srrs * since we did not send a HB make sure we don't double 1745163953Srrs * things 1746163953Srrs */ 1747163953Srrs net->hb_responded = 1; 1748163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 1749163953Srrs sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 1750163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, 1751163953Srrs NULL); 1752163953Srrs } 1753163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 1754164205Srrs asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 1755164205Srrs 1756164205Srrs if (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) { 1757164205Srrs /* 1758164205Srrs * Ok the peer probably discarded our data (if we 1759164205Srrs * echoed a cookie+data). So anything on the 1760164205Srrs * sent_queue should be marked for retransmit, we 1761164205Srrs * may not get something to kick us so it COULD 1762164205Srrs * still take a timeout to move these.. but it can't 1763164205Srrs * hurt to mark them. 1764164205Srrs */ 1765164205Srrs struct sctp_tmit_chunk *chk; 1766163953Srrs 1767164205Srrs TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 1768164205Srrs if (chk->sent < SCTP_DATAGRAM_RESEND) { 1769164205Srrs chk->sent = SCTP_DATAGRAM_RESEND; 1770171440Srrs sctp_flight_size_decrease(chk); 1771171440Srrs sctp_total_flight_decrease(stcb, chk); 1772168124Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1773164205Srrs spec_flag++; 1774164205Srrs } 1775164205Srrs } 1776164205Srrs 1777164205Srrs } 1778163953Srrs /* process the INIT info (peer's info) */ 1779228653Stuexen retval = sctp_process_init(init_cp, stcb); 1780163953Srrs if (retval < 0) { 1781166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1782166023Srrs asoc->cookie_how[how_indx] = 9; 1783163953Srrs return (NULL); 1784163953Srrs } 1785228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1786163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1787237715Stuexen initack_offset, src, dst, init_src)) { 1788166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1789166023Srrs asoc->cookie_how[how_indx] = 10; 1790163953Srrs return (NULL); 1791163953Srrs } 1792163953Srrs if ((asoc->state & SCTP_STATE_COOKIE_WAIT) || 1793163953Srrs (asoc->state & SCTP_STATE_COOKIE_ECHOED)) { 1794163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 1795163953Srrs 1796163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1797163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1798163953Srrs (inp->sctp_socket->so_qlimit == 0)) { 1799237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1800172090Srrs struct socket *so; 1801172090Srrs 1802172090Srrs#endif 1803163953Srrs stcb->sctp_ep->sctp_flags |= 1804163953Srrs SCTP_PCB_FLAGS_CONNECTED; 1805237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1806172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1807172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1808172090Srrs SCTP_TCB_UNLOCK(stcb); 1809172090Srrs SCTP_SOCKET_LOCK(so, 1); 1810172090Srrs SCTP_TCB_LOCK(stcb); 1811172090Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1812172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1813172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1814172090Srrs return (NULL); 1815172090Srrs } 1816172090Srrs#endif 1817172090Srrs soisconnected(stcb->sctp_socket); 1818237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1819172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1820172090Srrs#endif 1821163953Srrs } 1822166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 1823166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 1824166675Srrs else 1825166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1826166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1827166675Srrs } else if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 1828166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_restartestab); 1829166675Srrs } else { 1830166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1831163953Srrs } 1832171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1833163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1834163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1835163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1836163953Srrs } 1837163953Srrs sctp_stop_all_cookie_timers(stcb); 1838165220Srrs sctp_toss_old_cookies(stcb, asoc); 1839163953Srrs sctp_send_cookie_ack(stcb); 1840164205Srrs if (spec_flag) { 1841164205Srrs /* 1842164205Srrs * only if we have retrans set do we do this. What 1843164205Srrs * this call does is get only the COOKIE-ACK out and 1844164205Srrs * then when we return the normal call to 1845164205Srrs * sctp_chunk_output will get the retrans out behind 1846164205Srrs * this. 1847164205Srrs */ 1848172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_COOKIE_ACK, SCTP_SO_NOT_LOCKED); 1849164205Srrs } 1850166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1851166023Srrs asoc->cookie_how[how_indx] = 11; 1852166023Srrs 1853163953Srrs return (stcb); 1854163953Srrs } 1855163953Srrs if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 1856163953Srrs ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) && 1857163953Srrs cookie->tie_tag_my_vtag == asoc->my_vtag_nonce && 1858163953Srrs cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce && 1859163953Srrs cookie->tie_tag_peer_vtag != 0) { 1860163953Srrs struct sctpasochead *head; 1861163953Srrs 1862252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1863252585Stuexen struct socket *so; 1864252585Stuexen 1865252585Stuexen#endif 1866252585Stuexen 1867185694Srrs if (asoc->peer_supports_nat) { 1868185694Srrs /* 1869252585Stuexen * This is a gross gross hack. Just call the 1870185694Srrs * cookie_new code since we are allowing a duplicate 1871185694Srrs * association. I hope this works... 1872185694Srrs */ 1873237715Stuexen return (sctp_process_cookie_new(m, iphlen, offset, src, dst, 1874237715Stuexen sh, cookie, cookie_len, 1875185694Srrs inp, netp, init_src, notification, 1876185694Srrs auth_skipped, auth_offset, auth_len, 1877281955Shiren mflowtype, mflowid, 1878185694Srrs vrf_id, port)); 1879185694Srrs } 1880163953Srrs /* 1881163953Srrs * case A in Section 5.2.4 Table 2: XXMM (peer restarted) 1882163953Srrs */ 1883165220Srrs /* temp code */ 1884166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1885166023Srrs asoc->cookie_how[how_indx] = 12; 1886283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, 1887283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); 1888283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, 1889283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_17); 1890165647Srrs 1891163953Srrs /* notify upper layer */ 1892163953Srrs *notification = SCTP_NOTIFY_ASSOC_RESTART; 1893165220Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1894166675Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN) && 1895166675Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 1896166675Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 1897166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1898166675Srrs } 1899166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 1900166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_restartestab); 1901166675Srrs } else if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { 1902166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_collisionestab); 1903166675Srrs } 1904165647Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1905171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1906165647Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1907165647Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1908165647Srrs 1909165647Srrs } else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) { 1910165647Srrs /* move to OPEN state, if not in SHUTDOWN_SENT */ 1911171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1912165647Srrs } 1913165647Srrs asoc->pre_open_streams = 1914165647Srrs ntohs(initack_cp->init.num_outbound_streams); 1915165647Srrs asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 1916165647Srrs asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 1917179157Srrs asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 1918165647Srrs 1919165647Srrs asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 1920165647Srrs 1921165647Srrs asoc->str_reset_seq_in = asoc->init_seq_number; 1922165647Srrs 1923165647Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 1924170138Srrs if (asoc->mapping_array) { 1925165647Srrs memset(asoc->mapping_array, 0, 1926165647Srrs asoc->mapping_array_size); 1927170138Srrs } 1928205627Srrs if (asoc->nr_mapping_array) { 1929185694Srrs memset(asoc->nr_mapping_array, 0, 1930206137Stuexen asoc->mapping_array_size); 1931185694Srrs } 1932165220Srrs SCTP_TCB_UNLOCK(stcb); 1933252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1934252585Stuexen so = SCTP_INP_SO(stcb->sctp_ep); 1935252585Stuexen SCTP_SOCKET_LOCK(so, 1); 1936252585Stuexen#endif 1937165220Srrs SCTP_INP_INFO_WLOCK(); 1938165220Srrs SCTP_INP_WLOCK(stcb->sctp_ep); 1939165220Srrs SCTP_TCB_LOCK(stcb); 1940165220Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1941163953Srrs /* send up all the data */ 1942164205Srrs SCTP_TCB_SEND_LOCK(stcb); 1943165220Srrs 1944252585Stuexen sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED); 1945165220Srrs for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 1946243157Stuexen stcb->asoc.strmout[i].chunks_on_queues = 0; 1947270363Stuexen#if defined(SCTP_DETAILED_STR_STATS) 1948270363Stuexen for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) { 1949270363Stuexen asoc->strmout[i].abandoned_sent[j] = 0; 1950270363Stuexen asoc->strmout[i].abandoned_unsent[j] = 0; 1951270363Stuexen } 1952270363Stuexen#else 1953270363Stuexen asoc->strmout[i].abandoned_sent[0] = 0; 1954270363Stuexen asoc->strmout[i].abandoned_unsent[0] = 0; 1955270363Stuexen#endif 1956165220Srrs stcb->asoc.strmout[i].stream_no = i; 1957242627Stuexen stcb->asoc.strmout[i].next_sequence_send = 0; 1958165220Srrs stcb->asoc.strmout[i].last_msg_incomplete = 0; 1959165220Srrs } 1960163953Srrs /* process the INIT-ACK info (my info) */ 1961163953Srrs asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 1962163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 1963163953Srrs 1964163953Srrs /* pull from vtag hash */ 1965163953Srrs LIST_REMOVE(stcb, sctp_asocs); 1966163953Srrs /* re-insert to new vtag position */ 1967179783Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, 1968179783Srrs SCTP_BASE_INFO(hashasocmark))]; 1969163953Srrs /* 1970163953Srrs * put it in the bucket in the vtag hash of assoc's for the 1971163953Srrs * system 1972163953Srrs */ 1973163953Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 1974163953Srrs 1975164205Srrs SCTP_TCB_SEND_UNLOCK(stcb); 1976165220Srrs SCTP_INP_WUNLOCK(stcb->sctp_ep); 1977165220Srrs SCTP_INP_INFO_WUNLOCK(); 1978252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1979252585Stuexen SCTP_SOCKET_UNLOCK(so, 1); 1980252585Stuexen#endif 1981252585Stuexen asoc->total_flight = 0; 1982252585Stuexen asoc->total_flight_count = 0; 1983252585Stuexen /* process the INIT info (peer's info) */ 1984228653Stuexen retval = sctp_process_init(init_cp, stcb); 1985163953Srrs if (retval < 0) { 1986166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1987166023Srrs asoc->cookie_how[how_indx] = 13; 1988166023Srrs 1989163953Srrs return (NULL); 1990163953Srrs } 1991163953Srrs /* 1992163953Srrs * since we did not send a HB make sure we don't double 1993163953Srrs * things 1994163953Srrs */ 1995163953Srrs net->hb_responded = 1; 1996163953Srrs 1997228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1998163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1999237715Stuexen initack_offset, src, dst, init_src)) { 2000166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 2001166023Srrs asoc->cookie_how[how_indx] = 14; 2002166023Srrs 2003163953Srrs return (NULL); 2004163953Srrs } 2005163953Srrs /* respond with a COOKIE-ACK */ 2006163953Srrs sctp_stop_all_cookie_timers(stcb); 2007165220Srrs sctp_toss_old_cookies(stcb, asoc); 2008163953Srrs sctp_send_cookie_ack(stcb); 2009166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 2010166023Srrs asoc->cookie_how[how_indx] = 15; 2011163953Srrs 2012163953Srrs return (stcb); 2013163953Srrs } 2014166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 2015166023Srrs asoc->cookie_how[how_indx] = 16; 2016163953Srrs /* all other cases... */ 2017163953Srrs return (NULL); 2018163953Srrs} 2019163953Srrs 2020166086Srrs 2021163953Srrs/* 2022163953Srrs * handle a state cookie for a new association m: input packet mbuf chain-- 2023163953Srrs * assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a "split" mbuf 2024163953Srrs * and the cookie signature does not exist offset: offset into mbuf to the 2025163953Srrs * cookie-echo chunk length: length of the cookie chunk to: where the init 2026163953Srrs * was from returns a new TCB 2027163953Srrs */ 2028237049Stuexenstatic struct sctp_tcb * 2029163953Srrssctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 2030237715Stuexen struct sockaddr *src, struct sockaddr *dst, 2031163953Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 2032163953Srrs struct sctp_inpcb *inp, struct sctp_nets **netp, 2033163953Srrs struct sockaddr *init_src, int *notification, 2034169352Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 2035281955Shiren uint8_t mflowtype, uint32_t mflowid, 2036179157Srrs uint32_t vrf_id, uint16_t port) 2037163953Srrs{ 2038163953Srrs struct sctp_tcb *stcb; 2039163953Srrs struct sctp_init_chunk *init_cp, init_buf; 2040163953Srrs struct sctp_init_ack_chunk *initack_cp, initack_buf; 2041271746Stuexen union sctp_sockstore store; 2042163953Srrs struct sctp_association *asoc; 2043163953Srrs int init_offset, initack_offset, initack_limit; 2044163953Srrs int retval; 2045163953Srrs int error = 0; 2046166675Srrs uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE]; 2047163953Srrs 2048237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2049172090Srrs struct socket *so; 2050172090Srrs 2051172090Srrs so = SCTP_INP_SO(inp); 2052172090Srrs#endif 2053172090Srrs 2054163953Srrs /* 2055163953Srrs * find and validate the INIT chunk in the cookie (peer's info) the 2056163953Srrs * INIT should start after the cookie-echo header struct (chunk 2057163953Srrs * header, state cookie header struct) 2058163953Srrs */ 2059163953Srrs init_offset = offset + sizeof(struct sctp_cookie_echo_chunk); 2060163953Srrs init_cp = (struct sctp_init_chunk *) 2061163953Srrs sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 2062163953Srrs (uint8_t *) & init_buf); 2063163953Srrs if (init_cp == NULL) { 2064163953Srrs /* could not pull a INIT chunk in cookie */ 2065169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 2066169420Srrs "process_cookie_new: could not pull INIT chunk hdr\n"); 2067163953Srrs return (NULL); 2068163953Srrs } 2069163953Srrs if (init_cp->ch.chunk_type != SCTP_INITIATION) { 2070169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "HUH? process_cookie_new: could not find INIT chunk!\n"); 2071163953Srrs return (NULL); 2072163953Srrs } 2073228907Stuexen initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 2074163953Srrs /* 2075163953Srrs * find and validate the INIT-ACK chunk in the cookie (my info) the 2076163953Srrs * INIT-ACK follows the INIT chunk 2077163953Srrs */ 2078163953Srrs initack_cp = (struct sctp_init_ack_chunk *) 2079163953Srrs sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 2080163953Srrs (uint8_t *) & initack_buf); 2081163953Srrs if (initack_cp == NULL) { 2082163953Srrs /* could not pull INIT-ACK chunk in cookie */ 2083169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: could not pull INIT-ACK chunk hdr\n"); 2084163953Srrs return (NULL); 2085163953Srrs } 2086163953Srrs if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 2087163953Srrs return (NULL); 2088163953Srrs } 2089163953Srrs /* 2090163953Srrs * NOTE: We can't use the INIT_ACK's chk_length to determine the 2091163953Srrs * "initack_limit" value. This is because the chk_length field 2092163953Srrs * includes the length of the cookie, but the cookie is omitted when 2093163953Srrs * the INIT and INIT_ACK are tacked onto the cookie... 2094163953Srrs */ 2095163953Srrs initack_limit = offset + cookie_len; 2096163953Srrs 2097163953Srrs /* 2098163953Srrs * now that we know the INIT/INIT-ACK are in place, create a new TCB 2099163953Srrs * and popluate 2100163953Srrs */ 2101171531Srrs 2102171531Srrs /* 2103171531Srrs * Here we do a trick, we set in NULL for the proc/thread argument. 2104171531Srrs * We do this since in effect we only use the p argument when the 2105171531Srrs * socket is unbound and we must do an implicit bind. Since we are 2106171531Srrs * getting a cookie, we cannot be unbound. 2107171531Srrs */ 2108206137Stuexen stcb = sctp_aloc_assoc(inp, init_src, &error, 2109171531Srrs ntohl(initack_cp->init.initiate_tag), vrf_id, 2110294215Stuexen ntohs(initack_cp->init.num_outbound_streams), 2111171531Srrs (struct thread *)NULL 2112171531Srrs ); 2113163953Srrs if (stcb == NULL) { 2114163953Srrs struct mbuf *op_err; 2115163953Srrs 2116163953Srrs /* memory problem? */ 2117169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 2118169420Srrs "process_cookie_new: no room for another TCB!\n"); 2119267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 2120163953Srrs sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 2121237715Stuexen src, dst, sh, op_err, 2122281955Shiren mflowtype, mflowid, 2123237049Stuexen vrf_id, port); 2124163953Srrs return (NULL); 2125163953Srrs } 2126163953Srrs /* get the correct sctp_nets */ 2127169420Srrs if (netp) 2128169420Srrs *netp = sctp_findnet(stcb, init_src); 2129169420Srrs 2130163953Srrs asoc = &stcb->asoc; 2131163953Srrs /* get scope variables out of cookie */ 2132246595Stuexen asoc->scope.ipv4_local_scope = cookie->ipv4_scope; 2133246595Stuexen asoc->scope.site_scope = cookie->site_scope; 2134246595Stuexen asoc->scope.local_scope = cookie->local_scope; 2135246595Stuexen asoc->scope.loopback_scope = cookie->loopback_scope; 2136163953Srrs 2137246595Stuexen if ((asoc->scope.ipv4_addr_legal != cookie->ipv4_addr_legal) || 2138246595Stuexen (asoc->scope.ipv6_addr_legal != cookie->ipv6_addr_legal)) { 2139163953Srrs struct mbuf *op_err; 2140163953Srrs 2141163953Srrs /* 2142163953Srrs * Houston we have a problem. The EP changed while the 2143163953Srrs * cookie was in flight. Only recourse is to abort the 2144163953Srrs * association. 2145163953Srrs */ 2146170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2147267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 2148163953Srrs sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 2149237715Stuexen src, dst, sh, op_err, 2150281955Shiren mflowtype, mflowid, 2151237049Stuexen vrf_id, port); 2152237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2153172090Srrs SCTP_TCB_UNLOCK(stcb); 2154172090Srrs SCTP_SOCKET_LOCK(so, 1); 2155172090Srrs SCTP_TCB_LOCK(stcb); 2156172090Srrs#endif 2157171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 2158283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_18); 2159237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2160172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2161172090Srrs#endif 2162172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2163163953Srrs return (NULL); 2164163953Srrs } 2165163953Srrs /* process the INIT-ACK info (my info) */ 2166185694Srrs asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 2167163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 2168163953Srrs asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 2169163953Srrs asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 2170163953Srrs asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 2171179157Srrs asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 2172163953Srrs asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 2173163953Srrs asoc->str_reset_seq_in = asoc->init_seq_number; 2174163953Srrs 2175163953Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 2176163953Srrs 2177163953Srrs /* process the INIT info (peer's info) */ 2178169420Srrs if (netp) 2179228653Stuexen retval = sctp_process_init(init_cp, stcb); 2180169420Srrs else 2181169420Srrs retval = 0; 2182163953Srrs if (retval < 0) { 2183170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2184237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2185172090Srrs SCTP_TCB_UNLOCK(stcb); 2186172090Srrs SCTP_SOCKET_LOCK(so, 1); 2187172090Srrs SCTP_TCB_LOCK(stcb); 2188172090Srrs#endif 2189283822Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 2190283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_19); 2191237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2192172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2193172090Srrs#endif 2194172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2195163953Srrs return (NULL); 2196163953Srrs } 2197163953Srrs /* load all addresses */ 2198228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 2199237715Stuexen init_offset + sizeof(struct sctp_init_chunk), initack_offset, 2200237715Stuexen src, dst, init_src)) { 2201170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2202237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2203172090Srrs SCTP_TCB_UNLOCK(stcb); 2204172090Srrs SCTP_SOCKET_LOCK(so, 1); 2205172090Srrs SCTP_TCB_LOCK(stcb); 2206172090Srrs#endif 2207283822Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 2208283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_20); 2209237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2210172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2211172090Srrs#endif 2212172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2213163953Srrs return (NULL); 2214163953Srrs } 2215163953Srrs /* 2216163953Srrs * verify any preceding AUTH chunk that was skipped 2217163953Srrs */ 2218163953Srrs /* pull the local authentication parameters from the cookie/init-ack */ 2219163953Srrs sctp_auth_get_cookie_params(stcb, m, 2220163953Srrs initack_offset + sizeof(struct sctp_init_ack_chunk), 2221163953Srrs initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk))); 2222163953Srrs if (auth_skipped) { 2223163953Srrs struct sctp_auth_chunk *auth; 2224163953Srrs 2225163953Srrs auth = (struct sctp_auth_chunk *) 2226166675Srrs sctp_m_getptr(m, auth_offset, auth_len, auth_chunk_buf); 2227169420Srrs if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, auth_offset)) { 2228163953Srrs /* auth HMAC failed, dump the assoc and packet */ 2229169420Srrs SCTPDBG(SCTP_DEBUG_AUTH1, 2230169420Srrs "COOKIE-ECHO: AUTH failed\n"); 2231171440Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2232237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2233172090Srrs SCTP_TCB_UNLOCK(stcb); 2234172090Srrs SCTP_SOCKET_LOCK(so, 1); 2235172090Srrs SCTP_TCB_LOCK(stcb); 2236172090Srrs#endif 2237283822Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 2238283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_21); 2239237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2240172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2241172090Srrs#endif 2242172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2243163953Srrs return (NULL); 2244163953Srrs } else { 2245163953Srrs /* remaining chunks checked... good to go */ 2246163953Srrs stcb->asoc.authenticated = 1; 2247163953Srrs } 2248163953Srrs } 2249163953Srrs /* update current state */ 2250169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 2251171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 2252163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 2253163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 2254163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 2255163953Srrs } 2256165220Srrs sctp_stop_all_cookie_timers(stcb); 2257163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_passiveestab); 2258163953Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 2259163953Srrs 2260163953Srrs /* 2261163953Srrs * if we're doing ASCONFs, check to see if we have any new local 2262163953Srrs * addresses that need to get added to the peer (eg. addresses 2263163953Srrs * changed while cookie echo in flight). This needs to be done 2264163953Srrs * after we go to the OPEN state to do the correct asconf 2265163953Srrs * processing. else, make sure we have the correct addresses in our 2266163953Srrs * lists 2267163953Srrs */ 2268163953Srrs 2269163953Srrs /* warning, we re-use sin, sin6, sa_store here! */ 2270163953Srrs /* pull in local_address (our "from" address) */ 2271221249Stuexen switch (cookie->laddr_type) { 2272221249Stuexen#ifdef INET 2273221249Stuexen case SCTP_IPV4_ADDRESS: 2274163953Srrs /* source addr is IPv4 */ 2275271746Stuexen memset(&store.sin, 0, sizeof(struct sockaddr_in)); 2276271746Stuexen store.sin.sin_family = AF_INET; 2277271746Stuexen store.sin.sin_len = sizeof(struct sockaddr_in); 2278271746Stuexen store.sin.sin_addr.s_addr = cookie->laddress[0]; 2279221249Stuexen break; 2280221249Stuexen#endif 2281221249Stuexen#ifdef INET6 2282221249Stuexen case SCTP_IPV6_ADDRESS: 2283163953Srrs /* source addr is IPv6 */ 2284271746Stuexen memset(&store.sin6, 0, sizeof(struct sockaddr_in6)); 2285271746Stuexen store.sin6.sin6_family = AF_INET6; 2286271746Stuexen store.sin6.sin6_len = sizeof(struct sockaddr_in6); 2287271746Stuexen store.sin6.sin6_scope_id = cookie->scope_id; 2288271746Stuexen memcpy(&store.sin6.sin6_addr, cookie->laddress, sizeof(struct in6_addr)); 2289221249Stuexen break; 2290221249Stuexen#endif 2291221249Stuexen default: 2292170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2293237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2294172090Srrs SCTP_TCB_UNLOCK(stcb); 2295172090Srrs SCTP_SOCKET_LOCK(so, 1); 2296172090Srrs SCTP_TCB_LOCK(stcb); 2297172090Srrs#endif 2298283822Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 2299283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_22); 2300237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2301172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2302172090Srrs#endif 2303172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2304163953Srrs return (NULL); 2305163953Srrs } 2306163953Srrs 2307163953Srrs /* set up to notify upper layer */ 2308163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 2309163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2310163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 2311163953Srrs (inp->sctp_socket->so_qlimit == 0)) { 2312163953Srrs /* 2313163953Srrs * This is an endpoint that called connect() how it got a 2314163953Srrs * cookie that is NEW is a bit of a mystery. It must be that 2315163953Srrs * the INIT was sent, but before it got there.. a complete 2316163953Srrs * INIT/INIT-ACK/COOKIE arrived. But of course then it 2317163953Srrs * should have went to the other code.. not here.. oh well.. 2318163953Srrs * a bit of protection is worth having.. 2319163953Srrs */ 2320163953Srrs stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 2321237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2322172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2323172090Srrs SCTP_TCB_UNLOCK(stcb); 2324172090Srrs SCTP_SOCKET_LOCK(so, 1); 2325172090Srrs SCTP_TCB_LOCK(stcb); 2326172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2327172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 2328172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2329172090Srrs return (NULL); 2330172090Srrs } 2331172090Srrs#endif 2332172090Srrs soisconnected(stcb->sctp_socket); 2333237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2334172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2335172090Srrs#endif 2336163953Srrs } else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 2337163953Srrs (inp->sctp_socket->so_qlimit)) { 2338163953Srrs /* 2339163953Srrs * We don't want to do anything with this one. Since it is 2340163953Srrs * the listening guy. The timer will get started for 2341163953Srrs * accepted connections in the caller. 2342163953Srrs */ 2343163953Srrs ; 2344163953Srrs } 2345163953Srrs /* since we did not send a HB make sure we don't double things */ 2346169420Srrs if ((netp) && (*netp)) 2347169420Srrs (*netp)->hb_responded = 1; 2348163953Srrs 2349163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 2350163953Srrs sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 2351163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL); 2352163953Srrs } 2353171440Srrs (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 2354294208Stuexen if ((netp != NULL) && (*netp != NULL)) { 2355283741Stuexen /* calculate the RTT and set the encaps port */ 2356169420Srrs (*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp, 2357218186Srrs &cookie->time_entered, sctp_align_unsafe_makecopy, 2358219397Srrs SCTP_RTT_FROM_NON_DATA); 2359294208Stuexen#if defined(INET) || defined(INET6) 2360294208Stuexen if (((*netp)->port == 0) && (port != 0)) { 2361294208Stuexen sctp_pathmtu_adjustment(stcb, (*netp)->mtu - sizeof(struct udphdr)); 2362294208Stuexen } 2363283741Stuexen (*netp)->port = port; 2364294208Stuexen#endif 2365170642Srrs } 2366172190Srrs /* respond with a COOKIE-ACK */ 2367163953Srrs sctp_send_cookie_ack(stcb); 2368172190Srrs 2369172190Srrs /* 2370172190Srrs * check the address lists for any ASCONFs that need to be sent 2371172190Srrs * AFTER the cookie-ack is sent 2372172190Srrs */ 2373172190Srrs sctp_check_address_list(stcb, m, 2374172190Srrs initack_offset + sizeof(struct sctp_init_ack_chunk), 2375172190Srrs initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)), 2376271746Stuexen &store.sa, cookie->local_scope, cookie->site_scope, 2377172190Srrs cookie->ipv4_scope, cookie->loopback_scope); 2378172190Srrs 2379172190Srrs 2380163953Srrs return (stcb); 2381163953Srrs} 2382163953Srrs 2383185694Srrs/* 2384185694Srrs * CODE LIKE THIS NEEDS TO RUN IF the peer supports the NAT extension, i.e 2385185694Srrs * we NEED to make sure we are not already using the vtag. If so we 2386185694Srrs * need to send back an ABORT-TRY-AGAIN-WITH-NEW-TAG No middle box bit! 2387185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag, 2388185694Srrs SCTP_BASE_INFO(hashasocmark))]; 2389185694Srrs LIST_FOREACH(stcb, head, sctp_asocs) { 2390185694Srrs if ((stcb->asoc.my_vtag == tag) && (stcb->rport == rport) && (inp == stcb->sctp_ep)) { 2391185694Srrs -- SEND ABORT - TRY AGAIN -- 2392185694Srrs } 2393185694Srrs } 2394185694Srrs*/ 2395163953Srrs 2396163953Srrs/* 2397163953Srrs * handles a COOKIE-ECHO message stcb: modified to either a new or left as 2398163953Srrs * existing (non-NULL) TCB 2399163953Srrs */ 2400163953Srrsstatic struct mbuf * 2401163953Srrssctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, 2402237715Stuexen struct sockaddr *src, struct sockaddr *dst, 2403163953Srrs struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp, 2404163953Srrs struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp, 2405169352Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 2406237049Stuexen struct sctp_tcb **locked_tcb, 2407281955Shiren uint8_t mflowtype, uint32_t mflowid, 2408237049Stuexen uint32_t vrf_id, uint16_t port) 2409163953Srrs{ 2410163953Srrs struct sctp_state_cookie *cookie; 2411163953Srrs struct sctp_tcb *l_stcb = *stcb; 2412163953Srrs struct sctp_inpcb *l_inp; 2413163953Srrs struct sockaddr *to; 2414163953Srrs struct sctp_pcb *ep; 2415163953Srrs struct mbuf *m_sig; 2416163953Srrs uint8_t calc_sig[SCTP_SIGNATURE_SIZE], tmp_sig[SCTP_SIGNATURE_SIZE]; 2417163953Srrs uint8_t *sig; 2418163953Srrs uint8_t cookie_ok = 0; 2419237541Stuexen unsigned int sig_offset, cookie_offset; 2420163953Srrs unsigned int cookie_len; 2421163953Srrs struct timeval now; 2422163953Srrs struct timeval time_expires; 2423163953Srrs int notification = 0; 2424163953Srrs struct sctp_nets *netl; 2425163953Srrs int had_a_existing_tcb = 0; 2426216887Stuexen int send_int_conf = 0; 2427163953Srrs 2428221249Stuexen#ifdef INET 2429221249Stuexen struct sockaddr_in sin; 2430221249Stuexen 2431221249Stuexen#endif 2432221249Stuexen#ifdef INET6 2433221249Stuexen struct sockaddr_in6 sin6; 2434221249Stuexen 2435221249Stuexen#endif 2436221249Stuexen 2437169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2438169420Srrs "sctp_handle_cookie: handling COOKIE-ECHO\n"); 2439163953Srrs 2440163953Srrs if (inp_p == NULL) { 2441163953Srrs return (NULL); 2442163953Srrs } 2443163953Srrs cookie = &cp->cookie; 2444163953Srrs cookie_offset = offset + sizeof(struct sctp_chunkhdr); 2445163953Srrs cookie_len = ntohs(cp->ch.chunk_length); 2446163953Srrs 2447294176Stuexen if ((cookie->peerport != sh->src_port) || 2448294176Stuexen (cookie->myport != sh->dest_port) || 2449163953Srrs (cookie->my_vtag != sh->v_tag)) { 2450163953Srrs /* 2451163953Srrs * invalid ports or bad tag. Note that we always leave the 2452163953Srrs * v_tag in the header in network order and when we stored 2453163953Srrs * it in the my_vtag slot we also left it in network order. 2454169352Srrs * This maintains the match even though it may be in the 2455163953Srrs * opposite byte order of the machine :-> 2456163953Srrs */ 2457163953Srrs return (NULL); 2458163953Srrs } 2459237541Stuexen if (cookie_len < sizeof(struct sctp_cookie_echo_chunk) + 2460163953Srrs sizeof(struct sctp_init_chunk) + 2461163953Srrs sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) { 2462237541Stuexen /* cookie too small */ 2463163953Srrs return (NULL); 2464163953Srrs } 2465163953Srrs /* 2466163953Srrs * split off the signature into its own mbuf (since it should not be 2467163953Srrs * calculated in the sctp_hmac_m() call). 2468163953Srrs */ 2469163953Srrs sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE; 2470243882Sglebius m_sig = m_split(m, sig_offset, M_NOWAIT); 2471163953Srrs if (m_sig == NULL) { 2472163953Srrs /* out of memory or ?? */ 2473163953Srrs return (NULL); 2474163953Srrs } 2475178202Srrs#ifdef SCTP_MBUF_LOGGING 2476179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 2477283708Stuexen sctp_log_mbc(m_sig, SCTP_MBUF_SPLIT); 2478178202Srrs } 2479178202Srrs#endif 2480178202Srrs 2481163953Srrs /* 2482163953Srrs * compute the signature/digest for the cookie 2483163953Srrs */ 2484163953Srrs ep = &(*inp_p)->sctp_ep; 2485163953Srrs l_inp = *inp_p; 2486163953Srrs if (l_stcb) { 2487163953Srrs SCTP_TCB_UNLOCK(l_stcb); 2488163953Srrs } 2489163953Srrs SCTP_INP_RLOCK(l_inp); 2490163953Srrs if (l_stcb) { 2491163953Srrs SCTP_TCB_LOCK(l_stcb); 2492163953Srrs } 2493163953Srrs /* which cookie is it? */ 2494163953Srrs if ((cookie->time_entered.tv_sec < (long)ep->time_of_secret_change) && 2495163953Srrs (ep->current_secret_number != ep->last_secret_number)) { 2496163953Srrs /* it's the old cookie */ 2497169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2498163953Srrs (uint8_t *) ep->secret_key[(int)ep->last_secret_number], 2499170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2500163953Srrs } else { 2501163953Srrs /* it's the current cookie */ 2502169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2503163953Srrs (uint8_t *) ep->secret_key[(int)ep->current_secret_number], 2504170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2505163953Srrs } 2506163953Srrs /* get the signature */ 2507163953Srrs SCTP_INP_RUNLOCK(l_inp); 2508163953Srrs sig = (uint8_t *) sctp_m_getptr(m_sig, 0, SCTP_SIGNATURE_SIZE, (uint8_t *) & tmp_sig); 2509163953Srrs if (sig == NULL) { 2510163953Srrs /* couldn't find signature */ 2511164085Srrs sctp_m_freem(m_sig); 2512163953Srrs return (NULL); 2513163953Srrs } 2514163953Srrs /* compare the received digest with the computed digest */ 2515163953Srrs if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) != 0) { 2516163953Srrs /* try the old cookie? */ 2517163953Srrs if ((cookie->time_entered.tv_sec == (long)ep->time_of_secret_change) && 2518163953Srrs (ep->current_secret_number != ep->last_secret_number)) { 2519163953Srrs /* compute digest with old */ 2520169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2521163953Srrs (uint8_t *) ep->secret_key[(int)ep->last_secret_number], 2522170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2523163953Srrs /* compare */ 2524163953Srrs if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) == 0) 2525163953Srrs cookie_ok = 1; 2526163953Srrs } 2527163953Srrs } else { 2528163953Srrs cookie_ok = 1; 2529163953Srrs } 2530163953Srrs 2531163953Srrs /* 2532163953Srrs * Now before we continue we must reconstruct our mbuf so that 2533163953Srrs * normal processing of any other chunks will work. 2534163953Srrs */ 2535163953Srrs { 2536163953Srrs struct mbuf *m_at; 2537163953Srrs 2538163953Srrs m_at = m; 2539165647Srrs while (SCTP_BUF_NEXT(m_at) != NULL) { 2540165647Srrs m_at = SCTP_BUF_NEXT(m_at); 2541163953Srrs } 2542165647Srrs SCTP_BUF_NEXT(m_at) = m_sig; 2543163953Srrs } 2544163953Srrs 2545163953Srrs if (cookie_ok == 0) { 2546169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "handle_cookie_echo: cookie signature validation failed!\n"); 2547169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2548169420Srrs "offset = %u, cookie_offset = %u, sig_offset = %u\n", 2549169420Srrs (uint32_t) offset, cookie_offset, sig_offset); 2550163953Srrs return (NULL); 2551163953Srrs } 2552163953Srrs /* 2553163953Srrs * check the cookie timestamps to be sure it's not stale 2554163953Srrs */ 2555169378Srrs (void)SCTP_GETTIME_TIMEVAL(&now); 2556163953Srrs /* Expire time is in Ticks, so we convert to seconds */ 2557169655Srrs time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life); 2558163953Srrs time_expires.tv_usec = cookie->time_entered.tv_usec; 2559180387Srrs /* 2560180387Srrs * TODO sctp_constants.h needs alternative time macros when _KERNEL 2561180387Srrs * is undefined. 2562180387Srrs */ 2563163953Srrs if (timevalcmp(&now, &time_expires, >)) { 2564163953Srrs /* cookie is stale! */ 2565163953Srrs struct mbuf *op_err; 2566294158Stuexen struct sctp_error_stale_cookie *cause; 2567163953Srrs uint32_t tim; 2568163953Srrs 2569294158Stuexen op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_stale_cookie), 2570243882Sglebius 0, M_NOWAIT, 1, MT_DATA); 2571163953Srrs if (op_err == NULL) { 2572163953Srrs /* FOOBAR */ 2573163953Srrs return (NULL); 2574163953Srrs } 2575163953Srrs /* Set the len */ 2576294158Stuexen SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_stale_cookie); 2577294158Stuexen cause = mtod(op_err, struct sctp_error_stale_cookie *); 2578294158Stuexen cause->cause.code = htons(SCTP_CAUSE_STALE_COOKIE); 2579294158Stuexen cause->cause.length = htons((sizeof(struct sctp_paramhdr) + 2580163953Srrs (sizeof(uint32_t)))); 2581163953Srrs /* seconds to usec */ 2582163953Srrs tim = (now.tv_sec - time_expires.tv_sec) * 1000000; 2583163953Srrs /* add in usec */ 2584163953Srrs if (tim == 0) 2585163953Srrs tim = now.tv_usec - cookie->time_entered.tv_usec; 2586294158Stuexen cause->stale_time = htonl(tim); 2587237715Stuexen sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, 2588284633Stuexen mflowtype, mflowid, l_inp->fibnum, 2589179157Srrs vrf_id, port); 2590163953Srrs return (NULL); 2591163953Srrs } 2592163953Srrs /* 2593163953Srrs * Now we must see with the lookup address if we have an existing 2594163953Srrs * asoc. This will only happen if we were in the COOKIE-WAIT state 2595163953Srrs * and a INIT collided with us and somewhere the peer sent the 2596163953Srrs * cookie on another address besides the single address our assoc 2597163953Srrs * had for him. In this case we will have one of the tie-tags set at 2598163953Srrs * least AND the address field in the cookie can be used to look it 2599163953Srrs * up. 2600163953Srrs */ 2601163953Srrs to = NULL; 2602221249Stuexen switch (cookie->addr_type) { 2603221249Stuexen#ifdef INET6 2604221249Stuexen case SCTP_IPV6_ADDRESS: 2605163953Srrs memset(&sin6, 0, sizeof(sin6)); 2606163953Srrs sin6.sin6_family = AF_INET6; 2607163953Srrs sin6.sin6_len = sizeof(sin6); 2608163953Srrs sin6.sin6_port = sh->src_port; 2609163953Srrs sin6.sin6_scope_id = cookie->scope_id; 2610163953Srrs memcpy(&sin6.sin6_addr.s6_addr, cookie->address, 2611163953Srrs sizeof(sin6.sin6_addr.s6_addr)); 2612163953Srrs to = (struct sockaddr *)&sin6; 2613221249Stuexen break; 2614221249Stuexen#endif 2615221249Stuexen#ifdef INET 2616221249Stuexen case SCTP_IPV4_ADDRESS: 2617163953Srrs memset(&sin, 0, sizeof(sin)); 2618163953Srrs sin.sin_family = AF_INET; 2619163953Srrs sin.sin_len = sizeof(sin); 2620163953Srrs sin.sin_port = sh->src_port; 2621163953Srrs sin.sin_addr.s_addr = cookie->address[0]; 2622163953Srrs to = (struct sockaddr *)&sin; 2623221249Stuexen break; 2624221249Stuexen#endif 2625221249Stuexen default: 2626169420Srrs /* This should not happen */ 2627169420Srrs return (NULL); 2628163953Srrs } 2629283712Stuexen if (*stcb == NULL) { 2630163953Srrs /* Yep, lets check */ 2631237715Stuexen *stcb = sctp_findassociation_ep_addr(inp_p, to, netp, dst, NULL); 2632163953Srrs if (*stcb == NULL) { 2633163953Srrs /* 2634163953Srrs * We should have only got back the same inp. If we 2635163953Srrs * got back a different ep we have a problem. The 2636163953Srrs * original findep got back l_inp and now 2637163953Srrs */ 2638163953Srrs if (l_inp != *inp_p) { 2639169420Srrs SCTP_PRINTF("Bad problem find_ep got a diff inp then special_locate?\n"); 2640163953Srrs } 2641165220Srrs } else { 2642165220Srrs if (*locked_tcb == NULL) { 2643165220Srrs /* 2644165220Srrs * In this case we found the assoc only 2645165220Srrs * after we locked the create lock. This 2646165220Srrs * means we are in a colliding case and we 2647165220Srrs * must make sure that we unlock the tcb if 2648165220Srrs * its one of the cases where we throw away 2649165220Srrs * the incoming packets. 2650165220Srrs */ 2651165220Srrs *locked_tcb = *stcb; 2652165220Srrs 2653165220Srrs /* 2654165220Srrs * We must also increment the inp ref count 2655165220Srrs * since the ref_count flags was set when we 2656165220Srrs * did not find the TCB, now we found it 2657165220Srrs * which reduces the refcount.. we must 2658165220Srrs * raise it back out to balance it all :-) 2659165220Srrs */ 2660165220Srrs SCTP_INP_INCR_REF((*stcb)->sctp_ep); 2661165220Srrs if ((*stcb)->sctp_ep != l_inp) { 2662169420Srrs SCTP_PRINTF("Huh? ep:%p diff then l_inp:%p?\n", 2663240148Stuexen (void *)(*stcb)->sctp_ep, (void *)l_inp); 2664165220Srrs } 2665165220Srrs } 2666163953Srrs } 2667163953Srrs } 2668163953Srrs cookie_len -= SCTP_SIGNATURE_SIZE; 2669163953Srrs if (*stcb == NULL) { 2670163953Srrs /* this is the "normal" case... get a new TCB */ 2671237715Stuexen *stcb = sctp_process_cookie_new(m, iphlen, offset, src, dst, sh, 2672237715Stuexen cookie, cookie_len, *inp_p, 2673237715Stuexen netp, to, ¬ification, 2674237049Stuexen auth_skipped, auth_offset, auth_len, 2675281955Shiren mflowtype, mflowid, 2676237049Stuexen vrf_id, port); 2677163953Srrs } else { 2678163953Srrs /* this is abnormal... cookie-echo on existing TCB */ 2679163953Srrs had_a_existing_tcb = 1; 2680237715Stuexen *stcb = sctp_process_cookie_existing(m, iphlen, offset, 2681237715Stuexen src, dst, sh, 2682185694Srrs cookie, cookie_len, *inp_p, *stcb, netp, to, 2683237049Stuexen ¬ification, auth_skipped, auth_offset, auth_len, 2684281955Shiren mflowtype, mflowid, 2685237049Stuexen vrf_id, port); 2686163953Srrs } 2687163953Srrs 2688163953Srrs if (*stcb == NULL) { 2689163953Srrs /* still no TCB... must be bad cookie-echo */ 2690163953Srrs return (NULL); 2691163953Srrs } 2692284634Stuexen if (*netp != NULL) { 2693281955Shiren (*netp)->flowtype = mflowtype; 2694284634Stuexen (*netp)->flowid = mflowid; 2695218335Stuexen } 2696163953Srrs /* 2697163953Srrs * Ok, we built an association so confirm the address we sent the 2698163953Srrs * INIT-ACK to. 2699163953Srrs */ 2700163953Srrs netl = sctp_findnet(*stcb, to); 2701163953Srrs /* 2702163953Srrs * This code should in theory NOT run but 2703163953Srrs */ 2704163953Srrs if (netl == NULL) { 2705163953Srrs /* TSNH! Huh, why do I need to add this address here? */ 2706228907Stuexen if (sctp_add_remote_addr(*stcb, to, NULL, SCTP_DONOT_SETSCOPE, SCTP_IN_COOKIE_PROC)) { 2707228907Stuexen return (NULL); 2708228907Stuexen } 2709163953Srrs netl = sctp_findnet(*stcb, to); 2710163953Srrs } 2711163953Srrs if (netl) { 2712163953Srrs if (netl->dest_state & SCTP_ADDR_UNCONFIRMED) { 2713163953Srrs netl->dest_state &= ~SCTP_ADDR_UNCONFIRMED; 2714169420Srrs (void)sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL, 2715163953Srrs netl); 2716216887Stuexen send_int_conf = 1; 2717163953Srrs } 2718163953Srrs } 2719224641Stuexen sctp_start_net_timers(*stcb); 2720163953Srrs if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) { 2721163953Srrs if (!had_a_existing_tcb || 2722163953Srrs (((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) { 2723163953Srrs /* 2724163953Srrs * If we have a NEW cookie or the connect never 2725163953Srrs * reached the connected state during collision we 2726163953Srrs * must do the TCP accept thing. 2727163953Srrs */ 2728163953Srrs struct socket *so, *oso; 2729163953Srrs struct sctp_inpcb *inp; 2730163953Srrs 2731163953Srrs if (notification == SCTP_NOTIFY_ASSOC_RESTART) { 2732163953Srrs /* 2733163953Srrs * For a restart we will keep the same 2734163953Srrs * socket, no need to do anything. I THINK!! 2735163953Srrs */ 2736228653Stuexen sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2737216887Stuexen if (send_int_conf) { 2738216887Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2739216887Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2740216887Stuexen } 2741163953Srrs return (m); 2742163953Srrs } 2743163953Srrs oso = (*inp_p)->sctp_socket; 2744171858Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2745163953Srrs SCTP_TCB_UNLOCK((*stcb)); 2746218757Sbz CURVNET_SET(oso->so_vnet); 2747166086Srrs so = sonewconn(oso, 0 2748163953Srrs ); 2749218757Sbz CURVNET_RESTORE(); 2750163953Srrs SCTP_TCB_LOCK((*stcb)); 2751171858Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2752171858Srrs 2753163953Srrs if (so == NULL) { 2754163953Srrs struct mbuf *op_err; 2755163953Srrs 2756237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2757172090Srrs struct socket *pcb_so; 2758172090Srrs 2759172090Srrs#endif 2760163953Srrs /* Too many sockets */ 2761169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n"); 2762267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 2763163953Srrs sctp_abort_association(*inp_p, NULL, m, iphlen, 2764237715Stuexen src, dst, sh, op_err, 2765281955Shiren mflowtype, mflowid, 2766237049Stuexen vrf_id, port); 2767237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2768172090Srrs pcb_so = SCTP_INP_SO(*inp_p); 2769172090Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2770172090Srrs SCTP_TCB_UNLOCK((*stcb)); 2771172090Srrs SCTP_SOCKET_LOCK(pcb_so, 1); 2772172090Srrs SCTP_TCB_LOCK((*stcb)); 2773172090Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2774172090Srrs#endif 2775283822Stuexen (void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, 2776283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_23); 2777237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2778172090Srrs SCTP_SOCKET_UNLOCK(pcb_so, 1); 2779172090Srrs#endif 2780163953Srrs return (NULL); 2781163953Srrs } 2782163953Srrs inp = (struct sctp_inpcb *)so->so_pcb; 2783166086Srrs SCTP_INP_INCR_REF(inp); 2784166086Srrs /* 2785166086Srrs * We add the unbound flag here so that if we get an 2786166086Srrs * soabort() before we get the move_pcb done, we 2787166086Srrs * will properly cleanup. 2788166086Srrs */ 2789163953Srrs inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | 2790163953Srrs SCTP_PCB_FLAGS_CONNECTED | 2791163953Srrs SCTP_PCB_FLAGS_IN_TCPPOOL | 2792166086Srrs SCTP_PCB_FLAGS_UNBOUND | 2793163953Srrs (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) | 2794163953Srrs SCTP_PCB_FLAGS_DONT_WAKE); 2795163953Srrs inp->sctp_features = (*inp_p)->sctp_features; 2796172091Srrs inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features; 2797163953Srrs inp->sctp_socket = so; 2798163953Srrs inp->sctp_frag_point = (*inp_p)->sctp_frag_point; 2799283724Stuexen inp->max_cwnd = (*inp_p)->max_cwnd; 2800211944Stuexen inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off; 2801270356Stuexen inp->ecn_supported = (*inp_p)->ecn_supported; 2802270357Stuexen inp->prsctp_supported = (*inp_p)->prsctp_supported; 2803270362Stuexen inp->auth_supported = (*inp_p)->auth_supported; 2804270362Stuexen inp->asconf_supported = (*inp_p)->asconf_supported; 2805270361Stuexen inp->reconfig_supported = (*inp_p)->reconfig_supported; 2806270359Stuexen inp->nrsack_supported = (*inp_p)->nrsack_supported; 2807270360Stuexen inp->pktdrop_supported = (*inp_p)->pktdrop_supported; 2808163953Srrs inp->partial_delivery_point = (*inp_p)->partial_delivery_point; 2809163953Srrs inp->sctp_context = (*inp_p)->sctp_context; 2810233660Srrs inp->local_strreset_support = (*inp_p)->local_strreset_support; 2811284633Stuexen inp->fibnum = (*inp_p)->fibnum; 2812163953Srrs inp->inp_starting_point_for_iterator = NULL; 2813163953Srrs /* 2814163953Srrs * copy in the authentication parameters from the 2815163953Srrs * original endpoint 2816163953Srrs */ 2817163953Srrs if (inp->sctp_ep.local_hmacs) 2818163953Srrs sctp_free_hmaclist(inp->sctp_ep.local_hmacs); 2819163953Srrs inp->sctp_ep.local_hmacs = 2820163953Srrs sctp_copy_hmaclist((*inp_p)->sctp_ep.local_hmacs); 2821163953Srrs if (inp->sctp_ep.local_auth_chunks) 2822163953Srrs sctp_free_chunklist(inp->sctp_ep.local_auth_chunks); 2823163953Srrs inp->sctp_ep.local_auth_chunks = 2824163953Srrs sctp_copy_chunklist((*inp_p)->sctp_ep.local_auth_chunks); 2825163953Srrs 2826163953Srrs /* 2827163953Srrs * Now we must move it from one hash table to 2828163953Srrs * another and get the tcb in the right place. 2829163953Srrs */ 2830207924Srrs 2831207924Srrs /* 2832207924Srrs * This is where the one-2-one socket is put into 2833207924Srrs * the accept state waiting for the accept! 2834207924Srrs */ 2835207924Srrs if (*stcb) { 2836207924Srrs (*stcb)->asoc.state |= SCTP_STATE_IN_ACCEPT_QUEUE; 2837207924Srrs } 2838163953Srrs sctp_move_pcb_and_assoc(*inp_p, inp, *stcb); 2839170056Srrs 2840170056Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2841170056Srrs SCTP_TCB_UNLOCK((*stcb)); 2842170056Srrs 2843175845Srwatson sctp_pull_off_control_to_new_inp((*inp_p), inp, *stcb, 2844175845Srwatson 0); 2845170056Srrs SCTP_TCB_LOCK((*stcb)); 2846170056Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2847163953Srrs 2848170056Srrs 2849166086Srrs /* 2850166086Srrs * now we must check to see if we were aborted while 2851166086Srrs * the move was going on and the lock/unlock 2852166086Srrs * happened. 2853166086Srrs */ 2854166086Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 2855166086Srrs /* 2856166086Srrs * yep it was, we leave the assoc attached 2857166086Srrs * to the socket since the sctp_inpcb_free() 2858166086Srrs * call will send an abort for us. 2859166086Srrs */ 2860166086Srrs SCTP_INP_DECR_REF(inp); 2861166086Srrs return (NULL); 2862166086Srrs } 2863166086Srrs SCTP_INP_DECR_REF(inp); 2864163953Srrs /* Switch over to the new guy */ 2865163953Srrs *inp_p = inp; 2866172090Srrs sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2867216887Stuexen if (send_int_conf) { 2868216887Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2869216887Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2870216887Stuexen } 2871166086Srrs /* 2872166086Srrs * Pull it from the incomplete queue and wake the 2873166086Srrs * guy 2874166086Srrs */ 2875237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2876172090Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2877172090Srrs SCTP_TCB_UNLOCK((*stcb)); 2878172090Srrs SCTP_SOCKET_LOCK(so, 1); 2879172090Srrs#endif 2880166086Srrs soisconnected(so); 2881237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2882172118Srrs SCTP_TCB_LOCK((*stcb)); 2883172118Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2884172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2885172090Srrs#endif 2886163953Srrs return (m); 2887163953Srrs } 2888163953Srrs } 2889238454Stuexen if (notification) { 2890238454Stuexen sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2891163953Srrs } 2892238454Stuexen if (send_int_conf) { 2893238454Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2894238454Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2895238454Stuexen } 2896163953Srrs return (m); 2897163953Srrs} 2898163953Srrs 2899163953Srrsstatic void 2900228653Stuexensctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED, 2901163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 2902163953Srrs{ 2903163953Srrs /* cp must not be used, others call this without a c-ack :-) */ 2904163953Srrs struct sctp_association *asoc; 2905163953Srrs 2906169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2907169420Srrs "sctp_handle_cookie_ack: handling COOKIE-ACK\n"); 2908271746Stuexen if ((stcb == NULL) || (net == NULL)) { 2909163953Srrs return; 2910271746Stuexen } 2911163953Srrs asoc = &stcb->asoc; 2912163953Srrs 2913163953Srrs sctp_stop_all_cookie_timers(stcb); 2914163953Srrs /* process according to association state */ 2915163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 2916163953Srrs /* state change only needed when I am in right state */ 2917169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 2918171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 2919224641Stuexen sctp_start_net_timers(stcb); 2920163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 2921163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 2922163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 2923163953Srrs 2924163953Srrs } 2925163953Srrs /* update RTO */ 2926163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 2927163953Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 2928163953Srrs if (asoc->overall_error_count == 0) { 2929163953Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, 2930218186Srrs &asoc->time_entered, sctp_align_safe_nocopy, 2931219397Srrs SCTP_RTT_FROM_NON_DATA); 2932163953Srrs } 2933169378Srrs (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 2934172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2935163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2936163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 2937237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2938172090Srrs struct socket *so; 2939172090Srrs 2940172090Srrs#endif 2941163953Srrs stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 2942237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2943172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 2944172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2945172090Srrs SCTP_TCB_UNLOCK(stcb); 2946172090Srrs SCTP_SOCKET_LOCK(so, 1); 2947172090Srrs SCTP_TCB_LOCK(stcb); 2948172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2949218641Srrs#endif 2950218641Srrs if ((stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) == 0) { 2951218641Srrs soisconnected(stcb->sctp_socket); 2952172090Srrs } 2953237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2954172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2955172090Srrs#endif 2956163953Srrs } 2957163953Srrs /* 2958163953Srrs * since we did not send a HB make sure we don't double 2959163953Srrs * things 2960163953Srrs */ 2961163953Srrs net->hb_responded = 1; 2962163953Srrs 2963218641Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 2964218641Srrs /* 2965218641Srrs * We don't need to do the asconf thing, nor hb or 2966218641Srrs * autoclose if the socket is closed. 2967218641Srrs */ 2968218641Srrs goto closed_socket; 2969218641Srrs } 2970218641Srrs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, 2971218641Srrs stcb, net); 2972218641Srrs 2973218641Srrs 2974163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 2975163953Srrs sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTOCLOSE)) { 2976163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 2977163953Srrs stcb->sctp_ep, stcb, NULL); 2978163953Srrs } 2979163953Srrs /* 2980171572Srrs * send ASCONF if parameters are pending and ASCONFs are 2981171572Srrs * allowed (eg. addresses changed when init/cookie echo were 2982171572Srrs * in flight) 2983163953Srrs */ 2984163953Srrs if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) && 2985270362Stuexen (stcb->asoc.asconf_supported == 1) && 2986163953Srrs (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) { 2987171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 2988163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2989163953Srrs stcb->sctp_ep, stcb, 2990163953Srrs stcb->asoc.primary_destination); 2991171572Srrs#else 2992172190Srrs sctp_send_asconf(stcb, stcb->asoc.primary_destination, 2993172190Srrs SCTP_ADDR_NOT_LOCKED); 2994171572Srrs#endif 2995163953Srrs } 2996163953Srrs } 2997218641Srrsclosed_socket: 2998163953Srrs /* Toss the cookie if I can */ 2999163953Srrs sctp_toss_old_cookies(stcb, asoc); 3000163953Srrs if (!TAILQ_EMPTY(&asoc->sent_queue)) { 3001163953Srrs /* Restart the timer if we have pending data */ 3002163953Srrs struct sctp_tmit_chunk *chk; 3003163953Srrs 3004163953Srrs chk = TAILQ_FIRST(&asoc->sent_queue); 3005216822Stuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 3006163953Srrs } 3007163953Srrs} 3008163953Srrs 3009163953Srrsstatic void 3010163953Srrssctp_handle_ecn_echo(struct sctp_ecne_chunk *cp, 3011163953Srrs struct sctp_tcb *stcb) 3012163953Srrs{ 3013163953Srrs struct sctp_nets *net; 3014163953Srrs struct sctp_tmit_chunk *lchk; 3015218072Srrs struct sctp_ecne_chunk bkup; 3016228907Stuexen uint8_t override_bit; 3017218072Srrs uint32_t tsn, window_data_tsn; 3018218072Srrs int len; 3019218232Srrs unsigned int pkt_cnt; 3020163953Srrs 3021218072Srrs len = ntohs(cp->ch.chunk_length); 3022218072Srrs if ((len != sizeof(struct sctp_ecne_chunk)) && 3023218072Srrs (len != sizeof(struct old_sctp_ecne_chunk))) { 3024163953Srrs return; 3025163953Srrs } 3026218072Srrs if (len == sizeof(struct old_sctp_ecne_chunk)) { 3027218072Srrs /* Its the old format */ 3028218072Srrs memcpy(&bkup, cp, sizeof(struct old_sctp_ecne_chunk)); 3029218072Srrs bkup.num_pkts_since_cwr = htonl(1); 3030218072Srrs cp = &bkup; 3031218072Srrs } 3032163953Srrs SCTP_STAT_INCR(sctps_recvecne); 3033163953Srrs tsn = ntohl(cp->tsn); 3034218072Srrs pkt_cnt = ntohl(cp->num_pkts_since_cwr); 3035218072Srrs lchk = TAILQ_LAST(&stcb->asoc.send_queue, sctpchunk_listhead); 3036163953Srrs if (lchk == NULL) { 3037218129Srrs window_data_tsn = stcb->asoc.sending_seq - 1; 3038163953Srrs } else { 3039218129Srrs window_data_tsn = lchk->rec.data.TSN_seq; 3040163953Srrs } 3041163953Srrs 3042218072Srrs /* Find where it was sent to if possible. */ 3043163953Srrs net = NULL; 3044216822Stuexen TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) { 3045163953Srrs if (lchk->rec.data.TSN_seq == tsn) { 3046163953Srrs net = lchk->whoTo; 3047218186Srrs net->ecn_prev_cwnd = lchk->rec.data.cwnd_at_send; 3048163953Srrs break; 3049163953Srrs } 3050216825Stuexen if (SCTP_TSN_GT(lchk->rec.data.TSN_seq, tsn)) { 3051163953Srrs break; 3052216825Stuexen } 3053163953Srrs } 3054218072Srrs if (net == NULL) { 3055163953Srrs /* 3056218072Srrs * What to do. A previous send of a CWR was possibly lost. 3057218072Srrs * See how old it is, we may have it marked on the actual 3058218072Srrs * net. 3059218072Srrs */ 3060218072Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 3061218072Srrs if (tsn == net->last_cwr_tsn) { 3062218072Srrs /* Found him, send it off */ 3063228907Stuexen break; 3064218072Srrs } 3065218072Srrs } 3066228907Stuexen if (net == NULL) { 3067228907Stuexen /* 3068228907Stuexen * If we reach here, we need to send a special CWR 3069228907Stuexen * that says hey, we did this a long time ago and 3070228907Stuexen * you lost the response. 3071228907Stuexen */ 3072228907Stuexen net = TAILQ_FIRST(&stcb->asoc.nets); 3073228907Stuexen if (net == NULL) { 3074228907Stuexen /* TSNH */ 3075228907Stuexen return; 3076228907Stuexen } 3077228907Stuexen override_bit = SCTP_CWR_REDUCE_OVERRIDE; 3078228907Stuexen } else { 3079228907Stuexen override_bit = 0; 3080228907Stuexen } 3081228907Stuexen } else { 3082228907Stuexen override_bit = 0; 3083218072Srrs } 3084218129Srrs if (SCTP_TSN_GT(tsn, net->cwr_window_tsn) && 3085218129Srrs ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 3086218072Srrs /* 3087171440Srrs * JRS - Use the congestion control given in the pluggable 3088171440Srrs * CC module 3089171440Srrs */ 3090218129Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 0, pkt_cnt); 3091171440Srrs /* 3092218072Srrs * We reduce once every RTT. So we will only lower cwnd at 3093218072Srrs * the next sending seq i.e. the window_data_tsn 3094163953Srrs */ 3095218072Srrs net->cwr_window_tsn = window_data_tsn; 3096218072Srrs net->ecn_ce_pkt_cnt += pkt_cnt; 3097218072Srrs net->lost_cnt = pkt_cnt; 3098218072Srrs net->last_cwr_tsn = tsn; 3099218072Srrs } else { 3100218072Srrs override_bit |= SCTP_CWR_IN_SAME_WINDOW; 3101218129Srrs if (SCTP_TSN_GT(tsn, net->last_cwr_tsn) && 3102218129Srrs ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 3103218072Srrs /* 3104218129Srrs * Another loss in the same window update how many 3105218129Srrs * marks/packets lost we have had. 3106218072Srrs */ 3107218129Srrs int cnt = 1; 3108218072Srrs 3109218072Srrs if (pkt_cnt > net->lost_cnt) { 3110218072Srrs /* Should be the case */ 3111218129Srrs cnt = (pkt_cnt - net->lost_cnt); 3112218129Srrs net->ecn_ce_pkt_cnt += cnt; 3113218072Srrs } 3114218129Srrs net->lost_cnt = pkt_cnt; 3115218072Srrs net->last_cwr_tsn = tsn; 3116218129Srrs /* 3117218129Srrs * Most CC functions will ignore this call, since we 3118218129Srrs * are in-window yet of the initial CE the peer saw. 3119218129Srrs */ 3120218129Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 1, cnt); 3121218072Srrs } 3122163953Srrs } 3123163953Srrs /* 3124163953Srrs * We always send a CWR this way if our previous one was lost our 3125163953Srrs * peer will get an update, or if it is not time again to reduce we 3126218072Srrs * still get the cwr to the peer. Note we set the override when we 3127218072Srrs * could not find the TSN on the chunk or the destination network. 3128163953Srrs */ 3129218072Srrs sctp_send_cwr(stcb, net, net->last_cwr_tsn, override_bit); 3130163953Srrs} 3131163953Srrs 3132163953Srrsstatic void 3133218072Srrssctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sctp_nets *net) 3134163953Srrs{ 3135163953Srrs /* 3136163953Srrs * Here we get a CWR from the peer. We must look in the outqueue and 3137240520Seadler * make sure that we have a covered ECNE in the control chunk part. 3138163953Srrs * If so remove it. 3139163953Srrs */ 3140163953Srrs struct sctp_tmit_chunk *chk; 3141163953Srrs struct sctp_ecne_chunk *ecne; 3142218072Srrs int override; 3143218072Srrs uint32_t cwr_tsn; 3144163953Srrs 3145218072Srrs cwr_tsn = ntohl(cp->tsn); 3146218072Srrs override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE; 3147163953Srrs TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 3148163953Srrs if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) { 3149163953Srrs continue; 3150163953Srrs } 3151218072Srrs if ((override == 0) && (chk->whoTo != net)) { 3152218072Srrs /* Must be from the right src unless override is set */ 3153218072Srrs continue; 3154218072Srrs } 3155163953Srrs ecne = mtod(chk->data, struct sctp_ecne_chunk *); 3156218072Srrs if (SCTP_TSN_GE(cwr_tsn, ntohl(ecne->tsn))) { 3157163953Srrs /* this covers this ECNE, we can remove it */ 3158163953Srrs stcb->asoc.ecn_echo_cnt_onq--; 3159163953Srrs TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk, 3160163953Srrs sctp_next); 3161283718Stuexen sctp_m_freem(chk->data); 3162283718Stuexen chk->data = NULL; 3163163953Srrs stcb->asoc.ctrl_queue_cnt--; 3164221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 3165218072Srrs if (override == 0) { 3166218072Srrs break; 3167218072Srrs } 3168163953Srrs } 3169163953Srrs } 3170163953Srrs} 3171163953Srrs 3172163953Srrsstatic void 3173228653Stuexensctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSED, 3174163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 3175163953Srrs{ 3176163953Srrs struct sctp_association *asoc; 3177163953Srrs 3178237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3179172090Srrs struct socket *so; 3180172090Srrs 3181172090Srrs#endif 3182172090Srrs 3183169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3184169420Srrs "sctp_handle_shutdown_complete: handling SHUTDOWN-COMPLETE\n"); 3185163953Srrs if (stcb == NULL) 3186163953Srrs return; 3187163953Srrs 3188163953Srrs asoc = &stcb->asoc; 3189163953Srrs /* process according to association state */ 3190163953Srrs if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) { 3191163953Srrs /* unexpected SHUTDOWN-COMPLETE... so ignore... */ 3192171990Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3193171990Srrs "sctp_handle_shutdown_complete: not in SCTP_STATE_SHUTDOWN_ACK_SENT --- ignore\n"); 3194163953Srrs SCTP_TCB_UNLOCK(stcb); 3195163953Srrs return; 3196163953Srrs } 3197163953Srrs /* notify upper layer protocol */ 3198163953Srrs if (stcb->sctp_socket) { 3199172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 3200163953Srrs } 3201252585Stuexen#ifdef INVARIANTS 3202252585Stuexen if (!TAILQ_EMPTY(&asoc->send_queue) || 3203252585Stuexen !TAILQ_EMPTY(&asoc->sent_queue) || 3204252585Stuexen !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 3205252585Stuexen panic("Queues are not empty when handling SHUTDOWN-COMPLETE"); 3206252585Stuexen } 3207252585Stuexen#endif 3208163953Srrs /* stop the timer */ 3209283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, 3210283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_24); 3211163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 3212163953Srrs /* free the TCB */ 3213171990Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3214171990Srrs "sctp_handle_shutdown_complete: calls free-asoc\n"); 3215237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3216172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 3217172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 3218172090Srrs SCTP_TCB_UNLOCK(stcb); 3219172090Srrs SCTP_SOCKET_LOCK(so, 1); 3220172090Srrs SCTP_TCB_LOCK(stcb); 3221172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 3222172090Srrs#endif 3223283822Stuexen (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 3224283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_25); 3225237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3226172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 3227172090Srrs#endif 3228163953Srrs return; 3229163953Srrs} 3230163953Srrs 3231163953Srrsstatic int 3232163953Srrsprocess_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, 3233163953Srrs struct sctp_nets *net, uint8_t flg) 3234163953Srrs{ 3235163953Srrs switch (desc->chunk_type) { 3236211969Stuexen case SCTP_DATA: 3237163953Srrs /* find the tsn to resend (possibly */ 3238163953Srrs { 3239163953Srrs uint32_t tsn; 3240163953Srrs struct sctp_tmit_chunk *tp1; 3241163953Srrs 3242163953Srrs tsn = ntohl(desc->tsn_ifany); 3243216822Stuexen TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3244163953Srrs if (tp1->rec.data.TSN_seq == tsn) { 3245163953Srrs /* found it */ 3246163953Srrs break; 3247163953Srrs } 3248216825Stuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, tsn)) { 3249163953Srrs /* not found */ 3250163953Srrs tp1 = NULL; 3251163953Srrs break; 3252163953Srrs } 3253163953Srrs } 3254163953Srrs if (tp1 == NULL) { 3255163953Srrs /* 3256163953Srrs * Do it the other way , aka without paying 3257163953Srrs * attention to queue seq order. 3258163953Srrs */ 3259163953Srrs SCTP_STAT_INCR(sctps_pdrpdnfnd); 3260216822Stuexen TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3261163953Srrs if (tp1->rec.data.TSN_seq == tsn) { 3262163953Srrs /* found it */ 3263163953Srrs break; 3264163953Srrs } 3265163953Srrs } 3266163953Srrs } 3267163953Srrs if (tp1 == NULL) { 3268163953Srrs SCTP_STAT_INCR(sctps_pdrptsnnf); 3269163953Srrs } 3270163953Srrs if ((tp1) && (tp1->sent < SCTP_DATAGRAM_ACKED)) { 3271163953Srrs uint8_t *ddp; 3272163953Srrs 3273214877Stuexen if (((flg & SCTP_BADCRC) == 0) && 3274214877Stuexen ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 3275214877Stuexen return (0); 3276214877Stuexen } 3277163953Srrs if ((stcb->asoc.peers_rwnd == 0) && 3278163953Srrs ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 3279163953Srrs SCTP_STAT_INCR(sctps_pdrpdiwnp); 3280163953Srrs return (0); 3281163953Srrs } 3282163953Srrs if (stcb->asoc.peers_rwnd == 0 && 3283163953Srrs (flg & SCTP_FROM_MIDDLE_BOX)) { 3284163953Srrs SCTP_STAT_INCR(sctps_pdrpdizrw); 3285163953Srrs return (0); 3286163953Srrs } 3287163953Srrs ddp = (uint8_t *) (mtod(tp1->data, caddr_t)+ 3288163953Srrs sizeof(struct sctp_data_chunk)); 3289163953Srrs { 3290163953Srrs unsigned int iii; 3291163953Srrs 3292163953Srrs for (iii = 0; iii < sizeof(desc->data_bytes); 3293163953Srrs iii++) { 3294163953Srrs if (ddp[iii] != desc->data_bytes[iii]) { 3295163953Srrs SCTP_STAT_INCR(sctps_pdrpbadd); 3296163953Srrs return (-1); 3297163953Srrs } 3298163953Srrs } 3299163953Srrs } 3300163953Srrs 3301163953Srrs if (tp1->do_rtt) { 3302163953Srrs /* 3303163953Srrs * this guy had a RTO calculation 3304163953Srrs * pending on it, cancel it 3305163953Srrs */ 3306219397Srrs if (tp1->whoTo->rto_needed == 0) { 3307219397Srrs tp1->whoTo->rto_needed = 1; 3308219397Srrs } 3309163953Srrs tp1->do_rtt = 0; 3310163953Srrs } 3311163953Srrs SCTP_STAT_INCR(sctps_pdrpmark); 3312163953Srrs if (tp1->sent != SCTP_DATAGRAM_RESEND) 3313163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3314163953Srrs /* 3315163953Srrs * mark it as if we were doing a FR, since 3316163953Srrs * we will be getting gap ack reports behind 3317163953Srrs * the info from the router. 3318163953Srrs */ 3319163953Srrs tp1->rec.data.doing_fast_retransmit = 1; 3320163953Srrs /* 3321163953Srrs * mark the tsn with what sequences can 3322163953Srrs * cause a new FR. 3323163953Srrs */ 3324163953Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue)) { 3325163953Srrs tp1->rec.data.fast_retran_tsn = stcb->asoc.sending_seq; 3326163953Srrs } else { 3327163953Srrs tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq; 3328163953Srrs } 3329163953Srrs 3330163953Srrs /* restart the timer */ 3331163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 3332283822Stuexen stcb, tp1->whoTo, 3333283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_26); 3334163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 3335163953Srrs stcb, tp1->whoTo); 3336163953Srrs 3337163953Srrs /* fix counts and things */ 3338179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 3339170744Srrs sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP, 3340170744Srrs tp1->whoTo->flight_size, 3341170744Srrs tp1->book_size, 3342170744Srrs (uintptr_t) stcb, 3343170744Srrs tp1->rec.data.TSN_seq); 3344170744Srrs } 3345190689Srrs if (tp1->sent < SCTP_DATAGRAM_RESEND) { 3346190689Srrs sctp_flight_size_decrease(tp1); 3347190689Srrs sctp_total_flight_decrease(stcb, tp1); 3348190689Srrs } 3349216502Stuexen tp1->sent = SCTP_DATAGRAM_RESEND; 3350163953Srrs } { 3351163953Srrs /* audit code */ 3352163953Srrs unsigned int audit; 3353163953Srrs 3354163953Srrs audit = 0; 3355163953Srrs TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3356163953Srrs if (tp1->sent == SCTP_DATAGRAM_RESEND) 3357163953Srrs audit++; 3358163953Srrs } 3359163953Srrs TAILQ_FOREACH(tp1, &stcb->asoc.control_send_queue, 3360163953Srrs sctp_next) { 3361163953Srrs if (tp1->sent == SCTP_DATAGRAM_RESEND) 3362163953Srrs audit++; 3363163953Srrs } 3364163953Srrs if (audit != stcb->asoc.sent_queue_retran_cnt) { 3365169420Srrs SCTP_PRINTF("**Local Audit finds cnt:%d asoc cnt:%d\n", 3366163953Srrs audit, stcb->asoc.sent_queue_retran_cnt); 3367163953Srrs#ifndef SCTP_AUDITING_ENABLED 3368163953Srrs stcb->asoc.sent_queue_retran_cnt = audit; 3369163953Srrs#endif 3370163953Srrs } 3371163953Srrs } 3372163953Srrs } 3373163953Srrs break; 3374163953Srrs case SCTP_ASCONF: 3375163953Srrs { 3376163953Srrs struct sctp_tmit_chunk *asconf; 3377163953Srrs 3378163953Srrs TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue, 3379163953Srrs sctp_next) { 3380163953Srrs if (asconf->rec.chunk_id.id == SCTP_ASCONF) { 3381163953Srrs break; 3382163953Srrs } 3383163953Srrs } 3384163953Srrs if (asconf) { 3385163953Srrs if (asconf->sent != SCTP_DATAGRAM_RESEND) 3386163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3387163953Srrs asconf->sent = SCTP_DATAGRAM_RESEND; 3388163953Srrs asconf->snd_count--; 3389163953Srrs } 3390163953Srrs } 3391163953Srrs break; 3392163953Srrs case SCTP_INITIATION: 3393163953Srrs /* resend the INIT */ 3394163953Srrs stcb->asoc.dropped_special_cnt++; 3395163953Srrs if (stcb->asoc.dropped_special_cnt < SCTP_RETRY_DROPPED_THRESH) { 3396163953Srrs /* 3397163953Srrs * If we can get it in, in a few attempts we do 3398163953Srrs * this, otherwise we let the timer fire. 3399163953Srrs */ 3400163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, 3401283822Stuexen stcb, net, 3402283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_27); 3403172090Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 3404163953Srrs } 3405163953Srrs break; 3406163953Srrs case SCTP_SELECTIVE_ACK: 3407206137Stuexen case SCTP_NR_SELECTIVE_ACK: 3408163953Srrs /* resend the sack */ 3409221627Stuexen sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 3410163953Srrs break; 3411163953Srrs case SCTP_HEARTBEAT_REQUEST: 3412163953Srrs /* resend a demand HB */ 3413171440Srrs if ((stcb->asoc.overall_error_count + 3) < stcb->asoc.max_send_times) { 3414171440Srrs /* 3415171440Srrs * Only retransmit if we KNOW we wont destroy the 3416171440Srrs * tcb 3417171440Srrs */ 3418224641Stuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 3419171440Srrs } 3420163953Srrs break; 3421163953Srrs case SCTP_SHUTDOWN: 3422163953Srrs sctp_send_shutdown(stcb, net); 3423163953Srrs break; 3424163953Srrs case SCTP_SHUTDOWN_ACK: 3425163953Srrs sctp_send_shutdown_ack(stcb, net); 3426163953Srrs break; 3427163953Srrs case SCTP_COOKIE_ECHO: 3428163953Srrs { 3429163953Srrs struct sctp_tmit_chunk *cookie; 3430163953Srrs 3431163953Srrs cookie = NULL; 3432163953Srrs TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, 3433163953Srrs sctp_next) { 3434163953Srrs if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) { 3435163953Srrs break; 3436163953Srrs } 3437163953Srrs } 3438163953Srrs if (cookie) { 3439163953Srrs if (cookie->sent != SCTP_DATAGRAM_RESEND) 3440163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3441163953Srrs cookie->sent = SCTP_DATAGRAM_RESEND; 3442163953Srrs sctp_stop_all_cookie_timers(stcb); 3443163953Srrs } 3444163953Srrs } 3445163953Srrs break; 3446163953Srrs case SCTP_COOKIE_ACK: 3447163953Srrs sctp_send_cookie_ack(stcb); 3448163953Srrs break; 3449163953Srrs case SCTP_ASCONF_ACK: 3450163953Srrs /* resend last asconf ack */ 3451171990Srrs sctp_send_asconf_ack(stcb); 3452163953Srrs break; 3453163953Srrs case SCTP_FORWARD_CUM_TSN: 3454163953Srrs send_forward_tsn(stcb, &stcb->asoc); 3455163953Srrs break; 3456163953Srrs /* can't do anything with these */ 3457163953Srrs case SCTP_PACKET_DROPPED: 3458163953Srrs case SCTP_INITIATION_ACK: /* this should not happen */ 3459163953Srrs case SCTP_HEARTBEAT_ACK: 3460163953Srrs case SCTP_ABORT_ASSOCIATION: 3461163953Srrs case SCTP_OPERATION_ERROR: 3462163953Srrs case SCTP_SHUTDOWN_COMPLETE: 3463163953Srrs case SCTP_ECN_ECHO: 3464163953Srrs case SCTP_ECN_CWR: 3465163953Srrs default: 3466163953Srrs break; 3467163953Srrs } 3468163953Srrs return (0); 3469163953Srrs} 3470163953Srrs 3471163953Srrsvoid 3472240198Stuexensctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list) 3473163953Srrs{ 3474240198Stuexen uint32_t i; 3475163953Srrs uint16_t temp; 3476163953Srrs 3477163953Srrs /* 3478163953Srrs * We set things to 0xffff since this is the last delivered sequence 3479163953Srrs * and we will be sending in 0 after the reset. 3480163953Srrs */ 3481163953Srrs 3482163953Srrs if (number_entries) { 3483163953Srrs for (i = 0; i < number_entries; i++) { 3484163953Srrs temp = ntohs(list[i]); 3485163953Srrs if (temp >= stcb->asoc.streamincnt) { 3486163953Srrs continue; 3487163953Srrs } 3488163953Srrs stcb->asoc.strmin[temp].last_sequence_delivered = 0xffff; 3489163953Srrs } 3490163953Srrs } else { 3491163953Srrs list = NULL; 3492163953Srrs for (i = 0; i < stcb->asoc.streamincnt; i++) { 3493163953Srrs stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 3494163953Srrs } 3495163953Srrs } 3496172090Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 3497163953Srrs} 3498163953Srrs 3499163953Srrsstatic void 3500252585Stuexensctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list) 3501163953Srrs{ 3502252585Stuexen uint32_t i; 3503252585Stuexen uint16_t temp; 3504163953Srrs 3505252585Stuexen if (number_entries > 0) { 3506163953Srrs for (i = 0; i < number_entries; i++) { 3507163953Srrs temp = ntohs(list[i]); 3508163953Srrs if (temp >= stcb->asoc.streamoutcnt) { 3509163953Srrs /* no such stream */ 3510163953Srrs continue; 3511163953Srrs } 3512242627Stuexen stcb->asoc.strmout[temp].next_sequence_send = 0; 3513163953Srrs } 3514252585Stuexen } else { 3515252585Stuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 3516252585Stuexen stcb->asoc.strmout[i].next_sequence_send = 0; 3517252585Stuexen } 3518163953Srrs } 3519172090Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 3520163953Srrs} 3521163953Srrs 3522294140Stuexenstatic void 3523294140Stuexensctp_reset_clear_pending(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list) 3524294140Stuexen{ 3525294140Stuexen uint32_t i; 3526294140Stuexen uint16_t temp; 3527163953Srrs 3528294140Stuexen if (number_entries > 0) { 3529294140Stuexen for (i = 0; i < number_entries; i++) { 3530294140Stuexen temp = ntohs(list[i]); 3531294140Stuexen if (temp >= stcb->asoc.streamoutcnt) { 3532294140Stuexen /* no such stream */ 3533294140Stuexen continue; 3534294140Stuexen } 3535294140Stuexen stcb->asoc.strmout[temp].state = SCTP_STREAM_OPEN; 3536294140Stuexen } 3537294140Stuexen } else { 3538294140Stuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 3539294140Stuexen stcb->asoc.strmout[i].state = SCTP_STREAM_OPEN; 3540294140Stuexen } 3541294140Stuexen } 3542294140Stuexen} 3543294140Stuexen 3544294140Stuexen 3545273275Stuexenstruct sctp_stream_reset_request * 3546163953Srrssctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk) 3547163953Srrs{ 3548163953Srrs struct sctp_association *asoc; 3549240198Stuexen struct sctp_chunkhdr *ch; 3550273275Stuexen struct sctp_stream_reset_request *r; 3551163953Srrs struct sctp_tmit_chunk *chk; 3552163953Srrs int len, clen; 3553163953Srrs 3554163953Srrs asoc = &stcb->asoc; 3555163953Srrs if (TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 3556169208Srrs asoc->stream_reset_outstanding = 0; 3557163953Srrs return (NULL); 3558163953Srrs } 3559163953Srrs if (stcb->asoc.str_reset == NULL) { 3560169208Srrs asoc->stream_reset_outstanding = 0; 3561163953Srrs return (NULL); 3562163953Srrs } 3563163953Srrs chk = stcb->asoc.str_reset; 3564163953Srrs if (chk->data == NULL) { 3565163953Srrs return (NULL); 3566163953Srrs } 3567163953Srrs if (bchk) { 3568163953Srrs /* he wants a copy of the chk pointer */ 3569163953Srrs *bchk = chk; 3570163953Srrs } 3571163953Srrs clen = chk->send_size; 3572240198Stuexen ch = mtod(chk->data, struct sctp_chunkhdr *); 3573273275Stuexen r = (struct sctp_stream_reset_request *)(ch + 1); 3574163953Srrs if (ntohl(r->request_seq) == seq) { 3575163953Srrs /* found it */ 3576163953Srrs return (r); 3577163953Srrs } 3578163953Srrs len = SCTP_SIZE32(ntohs(r->ph.param_length)); 3579163953Srrs if (clen > (len + (int)sizeof(struct sctp_chunkhdr))) { 3580163953Srrs /* move to the next one, there can only be a max of two */ 3581273275Stuexen r = (struct sctp_stream_reset_request *)((caddr_t)r + len); 3582163953Srrs if (ntohl(r->request_seq) == seq) { 3583163953Srrs return (r); 3584163953Srrs } 3585163953Srrs } 3586163953Srrs /* that seq is not here */ 3587163953Srrs return (NULL); 3588163953Srrs} 3589163953Srrs 3590163953Srrsstatic void 3591163953Srrssctp_clean_up_stream_reset(struct sctp_tcb *stcb) 3592163953Srrs{ 3593163953Srrs struct sctp_association *asoc; 3594163953Srrs struct sctp_tmit_chunk *chk = stcb->asoc.str_reset; 3595163953Srrs 3596163953Srrs if (stcb->asoc.str_reset == NULL) { 3597163953Srrs return; 3598163953Srrs } 3599166675Srrs asoc = &stcb->asoc; 3600166675Srrs 3601283822Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, 3602283822Stuexen chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_28); 3603163953Srrs TAILQ_REMOVE(&asoc->control_send_queue, 3604163953Srrs chk, 3605163953Srrs sctp_next); 3606163953Srrs if (chk->data) { 3607163953Srrs sctp_m_freem(chk->data); 3608163953Srrs chk->data = NULL; 3609163953Srrs } 3610163953Srrs asoc->ctrl_queue_cnt--; 3611221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 3612172156Srrs /* sa_ignore NO_NULL_CHK */ 3613163953Srrs stcb->asoc.str_reset = NULL; 3614163953Srrs} 3615163953Srrs 3616163953Srrs 3617163953Srrsstatic int 3618163953Srrssctp_handle_stream_reset_response(struct sctp_tcb *stcb, 3619163953Srrs uint32_t seq, uint32_t action, 3620164139Srrs struct sctp_stream_reset_response *respin) 3621163953Srrs{ 3622163953Srrs uint16_t type; 3623163953Srrs int lparm_len; 3624163953Srrs struct sctp_association *asoc = &stcb->asoc; 3625163953Srrs struct sctp_tmit_chunk *chk; 3626273275Stuexen struct sctp_stream_reset_request *req_param; 3627273275Stuexen struct sctp_stream_reset_out_request *req_out_param; 3628273275Stuexen struct sctp_stream_reset_in_request *req_in_param; 3629252585Stuexen uint32_t number_entries; 3630163953Srrs 3631163953Srrs if (asoc->stream_reset_outstanding == 0) { 3632163953Srrs /* duplicate */ 3633163953Srrs return (0); 3634163953Srrs } 3635163953Srrs if (seq == stcb->asoc.str_reset_seq_out) { 3636273275Stuexen req_param = sctp_find_stream_reset(stcb, seq, &chk); 3637273275Stuexen if (req_param != NULL) { 3638163953Srrs stcb->asoc.str_reset_seq_out++; 3639273275Stuexen type = ntohs(req_param->ph.param_type); 3640273275Stuexen lparm_len = ntohs(req_param->ph.param_length); 3641163953Srrs if (type == SCTP_STR_RESET_OUT_REQUEST) { 3642294140Stuexen int no_clear = 0; 3643294140Stuexen 3644273275Stuexen req_out_param = (struct sctp_stream_reset_out_request *)req_param; 3645164139Srrs number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t); 3646163953Srrs asoc->stream_reset_out_is_outstanding = 0; 3647163953Srrs if (asoc->stream_reset_outstanding) 3648163953Srrs asoc->stream_reset_outstanding--; 3649235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3650163953Srrs /* do it */ 3651273275Stuexen sctp_reset_out_streams(stcb, number_entries, req_out_param->list_of_streams); 3652235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3653273275Stuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED); 3654294140Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_IN_PROGRESS) { 3655294140Stuexen /* 3656294140Stuexen * Set it up so we don't stop 3657294140Stuexen * retransmitting 3658294140Stuexen */ 3659294213Stuexen asoc->stream_reset_outstanding++; 3660294140Stuexen stcb->asoc.str_reset_seq_out--; 3661294140Stuexen asoc->stream_reset_out_is_outstanding = 1; 3662294140Stuexen no_clear = 1; 3663163953Srrs } else { 3664273275Stuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED); 3665163953Srrs } 3666294140Stuexen if (no_clear == 0) { 3667294140Stuexen sctp_reset_clear_pending(stcb, number_entries, req_out_param->list_of_streams); 3668294140Stuexen } 3669163953Srrs } else if (type == SCTP_STR_RESET_IN_REQUEST) { 3670273275Stuexen req_in_param = (struct sctp_stream_reset_in_request *)req_param; 3671164139Srrs number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t); 3672163953Srrs if (asoc->stream_reset_outstanding) 3673163953Srrs asoc->stream_reset_outstanding--; 3674235066Stuexen if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3675235066Stuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_IN, stcb, 3676273275Stuexen number_entries, req_in_param->list_of_streams, SCTP_SO_NOT_LOCKED); 3677235066Stuexen } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 3678233660Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb, 3679273275Stuexen number_entries, req_in_param->list_of_streams, SCTP_SO_NOT_LOCKED); 3680163953Srrs } 3681233660Srrs } else if (type == SCTP_STR_RESET_ADD_OUT_STREAMS) { 3682188854Srrs /* Ok we now may have more streams */ 3683233660Srrs int num_stream; 3684233660Srrs 3685233660Srrs num_stream = stcb->asoc.strm_pending_add_size; 3686233660Srrs if (num_stream > (stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt)) { 3687233660Srrs /* TSNH */ 3688233660Srrs num_stream = stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt; 3689233660Srrs } 3690233660Srrs stcb->asoc.strm_pending_add_size = 0; 3691189121Srrs if (asoc->stream_reset_outstanding) 3692189121Srrs asoc->stream_reset_outstanding--; 3693235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3694188854Srrs /* Put the new streams into effect */ 3695294140Stuexen int i; 3696294140Stuexen 3697294140Stuexen for (i = asoc->streamoutcnt; i < (asoc->streamoutcnt + num_stream); i++) { 3698294140Stuexen asoc->strmout[i].state = SCTP_STREAM_OPEN; 3699294140Stuexen } 3700294140Stuexen asoc->streamoutcnt += num_stream; 3701233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 3702235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3703235066Stuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3704235066Stuexen SCTP_STREAM_CHANGE_DENIED); 3705188854Srrs } else { 3706233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3707235066Stuexen SCTP_STREAM_CHANGE_FAILED); 3708188854Srrs } 3709233660Srrs } else if (type == SCTP_STR_RESET_ADD_IN_STREAMS) { 3710233660Srrs if (asoc->stream_reset_outstanding) 3711233660Srrs asoc->stream_reset_outstanding--; 3712235066Stuexen if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3713233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3714235066Stuexen SCTP_STREAM_CHANGE_DENIED); 3715235066Stuexen } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 3716235066Stuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3717235066Stuexen SCTP_STREAM_CHANGE_FAILED); 3718233660Srrs } 3719163953Srrs } else if (type == SCTP_STR_RESET_TSN_REQUEST) { 3720163953Srrs /** 3721163953Srrs * a) Adopt the new in tsn. 3722163953Srrs * b) reset the map 3723163953Srrs * c) Adopt the new out-tsn 3724163953Srrs */ 3725163953Srrs struct sctp_stream_reset_response_tsn *resp; 3726163953Srrs struct sctp_forward_tsn_chunk fwdtsn; 3727163953Srrs int abort_flag = 0; 3728163953Srrs 3729163953Srrs if (respin == NULL) { 3730163953Srrs /* huh ? */ 3731163953Srrs return (0); 3732163953Srrs } 3733277807Sdelphij if (ntohs(respin->ph.param_length) < sizeof(struct sctp_stream_reset_response_tsn)) { 3734277807Sdelphij return (0); 3735277807Sdelphij } 3736235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3737163953Srrs resp = (struct sctp_stream_reset_response_tsn *)respin; 3738163953Srrs asoc->stream_reset_outstanding--; 3739163953Srrs fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 3740163953Srrs fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 3741163953Srrs fwdtsn.new_cumulative_tsn = htonl(ntohl(resp->senders_next_tsn) - 1); 3742170992Srrs sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 3743163953Srrs if (abort_flag) { 3744163953Srrs return (1); 3745163953Srrs } 3746163953Srrs stcb->asoc.highest_tsn_inside_map = (ntohl(resp->senders_next_tsn) - 1); 3747179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 3748179783Srrs sctp_log_map(0, 7, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 3749179783Srrs } 3750180955Srrs stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map; 3751163953Srrs stcb->asoc.mapping_array_base_tsn = ntohl(resp->senders_next_tsn); 3752163953Srrs memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); 3753185694Srrs 3754205627Srrs stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; 3755206137Stuexen memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size); 3756205627Srrs 3757163953Srrs stcb->asoc.sending_seq = ntohl(resp->receivers_next_tsn); 3758163953Srrs stcb->asoc.last_acked_seq = stcb->asoc.cumulative_tsn; 3759163953Srrs 3760163953Srrs sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 3761163953Srrs sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 3762233660Srrs sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 0); 3763235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3764235066Stuexen sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 3765235066Stuexen SCTP_ASSOC_RESET_DENIED); 3766233660Srrs } else { 3767233660Srrs sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 3768235066Stuexen SCTP_ASSOC_RESET_FAILED); 3769163953Srrs } 3770163953Srrs } 3771163953Srrs /* get rid of the request and get the request flags */ 3772163953Srrs if (asoc->stream_reset_outstanding == 0) { 3773163953Srrs sctp_clean_up_stream_reset(stcb); 3774163953Srrs } 3775163953Srrs } 3776163953Srrs } 3777294140Stuexen if (asoc->stream_reset_outstanding == 0) { 3778294141Stuexen sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED); 3779294140Stuexen } 3780163953Srrs return (0); 3781163953Srrs} 3782163953Srrs 3783163953Srrsstatic void 3784163953Srrssctp_handle_str_reset_request_in(struct sctp_tcb *stcb, 3785163953Srrs struct sctp_tmit_chunk *chk, 3786170992Srrs struct sctp_stream_reset_in_request *req, int trunc) 3787163953Srrs{ 3788163953Srrs uint32_t seq; 3789163953Srrs int len, i; 3790163953Srrs int number_entries; 3791163953Srrs uint16_t temp; 3792163953Srrs 3793163953Srrs /* 3794163953Srrs * peer wants me to send a str-reset to him for my outgoing seq's if 3795163953Srrs * seq_in is right. 3796163953Srrs */ 3797163953Srrs struct sctp_association *asoc = &stcb->asoc; 3798163953Srrs 3799163953Srrs seq = ntohl(req->request_seq); 3800163953Srrs if (asoc->str_reset_seq_in == seq) { 3801235064Stuexen asoc->last_reset_action[1] = asoc->last_reset_action[0]; 3802235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 3803235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3804235064Stuexen } else if (trunc) { 3805170992Srrs /* Can't do it, since they exceeded our buffer size */ 3806235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3807170992Srrs } else if (stcb->asoc.stream_reset_out_is_outstanding == 0) { 3808163953Srrs len = ntohs(req->ph.param_length); 3809163953Srrs number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t)); 3810294140Stuexen if (number_entries) { 3811294140Stuexen for (i = 0; i < number_entries; i++) { 3812294140Stuexen temp = ntohs(req->list_of_streams[i]); 3813294140Stuexen if (temp >= stcb->asoc.streamoutcnt) { 3814294140Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3815294140Stuexen goto bad_boy; 3816294140Stuexen } 3817294140Stuexen req->list_of_streams[i] = temp; 3818294140Stuexen } 3819294140Stuexen for (i = 0; i < number_entries; i++) { 3820294140Stuexen if (stcb->asoc.strmout[req->list_of_streams[i]].state == SCTP_STREAM_OPEN) { 3821294140Stuexen stcb->asoc.strmout[req->list_of_streams[i]].state = SCTP_STREAM_RESET_PENDING; 3822294140Stuexen } 3823294140Stuexen } 3824294140Stuexen } else { 3825294140Stuexen /* Its all */ 3826294140Stuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 3827294140Stuexen if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) 3828294140Stuexen stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING; 3829294140Stuexen } 3830163953Srrs } 3831235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3832163953Srrs } else { 3833163953Srrs /* Can't do it, since we have sent one out */ 3834235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 3835163953Srrs } 3836294140Stuexenbad_boy: 3837233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3838163953Srrs asoc->str_reset_seq_in++; 3839163953Srrs } else if (asoc->str_reset_seq_in - 1 == seq) { 3840163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3841163953Srrs } else if (asoc->str_reset_seq_in - 2 == seq) { 3842163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 3843163953Srrs } else { 3844235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3845163953Srrs } 3846294141Stuexen sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED); 3847163953Srrs} 3848163953Srrs 3849163953Srrsstatic int 3850163953Srrssctp_handle_str_reset_request_tsn(struct sctp_tcb *stcb, 3851163953Srrs struct sctp_tmit_chunk *chk, 3852163953Srrs struct sctp_stream_reset_tsn_request *req) 3853163953Srrs{ 3854163953Srrs /* reset all in and out and update the tsn */ 3855163953Srrs /* 3856163953Srrs * A) reset my str-seq's on in and out. B) Select a receive next, 3857163953Srrs * and set cum-ack to it. Also process this selected number as a 3858163953Srrs * fwd-tsn as well. C) set in the response my next sending seq. 3859163953Srrs */ 3860163953Srrs struct sctp_forward_tsn_chunk fwdtsn; 3861163953Srrs struct sctp_association *asoc = &stcb->asoc; 3862163953Srrs int abort_flag = 0; 3863163953Srrs uint32_t seq; 3864163953Srrs 3865163953Srrs seq = ntohl(req->request_seq); 3866163953Srrs if (asoc->str_reset_seq_in == seq) { 3867235283Stuexen asoc->last_reset_action[1] = stcb->asoc.last_reset_action[0]; 3868235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 3869235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3870235283Stuexen } else { 3871235064Stuexen fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 3872235283Stuexen fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 3873235283Stuexen fwdtsn.ch.chunk_flags = 0; 3874235283Stuexen fwdtsn.new_cumulative_tsn = htonl(stcb->asoc.highest_tsn_inside_map + 1); 3875235283Stuexen sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 3876235283Stuexen if (abort_flag) { 3877235283Stuexen return (1); 3878235283Stuexen } 3879235283Stuexen asoc->highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA; 3880235283Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 3881235283Stuexen sctp_log_map(0, 10, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 3882235283Stuexen } 3883235283Stuexen asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->highest_tsn_inside_map; 3884235283Stuexen asoc->mapping_array_base_tsn = asoc->highest_tsn_inside_map + 1; 3885235283Stuexen memset(asoc->mapping_array, 0, asoc->mapping_array_size); 3886235283Stuexen asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 3887235283Stuexen memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size); 3888235283Stuexen atomic_add_int(&asoc->sending_seq, 1); 3889235283Stuexen /* save off historical data for retrans */ 3890235283Stuexen asoc->last_sending_seq[1] = asoc->last_sending_seq[0]; 3891235283Stuexen asoc->last_sending_seq[0] = asoc->sending_seq; 3892235283Stuexen asoc->last_base_tsnsent[1] = asoc->last_base_tsnsent[0]; 3893235283Stuexen asoc->last_base_tsnsent[0] = asoc->mapping_array_base_tsn; 3894235283Stuexen sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 3895235283Stuexen sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 3896235283Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3897235283Stuexen sctp_notify_stream_reset_tsn(stcb, asoc->sending_seq, (asoc->mapping_array_base_tsn + 1), 0); 3898163953Srrs } 3899235283Stuexen sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 3900235283Stuexen asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 3901163953Srrs asoc->str_reset_seq_in++; 3902163953Srrs } else if (asoc->str_reset_seq_in - 1 == seq) { 3903163953Srrs sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 3904235064Stuexen asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 3905163953Srrs } else if (asoc->str_reset_seq_in - 2 == seq) { 3906163953Srrs sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[1], 3907235064Stuexen asoc->last_sending_seq[1], asoc->last_base_tsnsent[1]); 3908163953Srrs } else { 3909235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3910163953Srrs } 3911163953Srrs return (0); 3912163953Srrs} 3913163953Srrs 3914163953Srrsstatic void 3915163953Srrssctp_handle_str_reset_request_out(struct sctp_tcb *stcb, 3916163953Srrs struct sctp_tmit_chunk *chk, 3917170992Srrs struct sctp_stream_reset_out_request *req, int trunc) 3918163953Srrs{ 3919163953Srrs uint32_t seq, tsn; 3920163953Srrs int number_entries, len; 3921163953Srrs struct sctp_association *asoc = &stcb->asoc; 3922163953Srrs 3923163953Srrs seq = ntohl(req->request_seq); 3924163953Srrs 3925163953Srrs /* now if its not a duplicate we process it */ 3926163953Srrs if (asoc->str_reset_seq_in == seq) { 3927163953Srrs len = ntohs(req->ph.param_length); 3928163953Srrs number_entries = ((len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t)); 3929163953Srrs /* 3930163953Srrs * the sender is resetting, handle the list issue.. we must 3931163953Srrs * a) verify if we can do the reset, if so no problem b) If 3932163953Srrs * we can't do the reset we must copy the request. c) queue 3933163953Srrs * it, and setup the data in processor to trigger it off 3934163953Srrs * when needed and dequeue all the queued data. 3935163953Srrs */ 3936163953Srrs tsn = ntohl(req->send_reset_at_tsn); 3937163953Srrs 3938163953Srrs /* move the reset action back one */ 3939163953Srrs asoc->last_reset_action[1] = asoc->last_reset_action[0]; 3940235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 3941235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3942235064Stuexen } else if (trunc) { 3943235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3944216825Stuexen } else if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) { 3945163953Srrs /* we can do it now */ 3946163953Srrs sctp_reset_in_stream(stcb, number_entries, req->list_of_streams); 3947235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3948163953Srrs } else { 3949163953Srrs /* 3950163953Srrs * we must queue it up and thus wait for the TSN's 3951163953Srrs * to arrive that are at or before tsn 3952163953Srrs */ 3953163953Srrs struct sctp_stream_reset_list *liste; 3954163953Srrs int siz; 3955163953Srrs 3956163953Srrs siz = sizeof(struct sctp_stream_reset_list) + (number_entries * sizeof(uint16_t)); 3957163953Srrs SCTP_MALLOC(liste, struct sctp_stream_reset_list *, 3958170091Srrs siz, SCTP_M_STRESET); 3959163953Srrs if (liste == NULL) { 3960163953Srrs /* gak out of memory */ 3961235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3962235064Stuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3963163953Srrs return; 3964163953Srrs } 3965294140Stuexen liste->seq = seq; 3966163953Srrs liste->tsn = tsn; 3967163953Srrs liste->number_entries = number_entries; 3968240198Stuexen memcpy(&liste->list_of_streams, req->list_of_streams, number_entries * sizeof(uint16_t)); 3969163953Srrs TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp); 3970294140Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_IN_PROGRESS; 3971163953Srrs } 3972233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3973163953Srrs asoc->str_reset_seq_in++; 3974163953Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 3975163953Srrs /* 3976163953Srrs * one seq back, just echo back last action since my 3977163953Srrs * response was lost. 3978163953Srrs */ 3979163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3980163953Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 3981163953Srrs /* 3982163953Srrs * two seq back, just echo back last action since my 3983163953Srrs * response was lost. 3984163953Srrs */ 3985163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 3986163953Srrs } else { 3987235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3988163953Srrs } 3989163953Srrs} 3990163953Srrs 3991188854Srrsstatic void 3992188854Srrssctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 3993188854Srrs struct sctp_stream_reset_add_strm *str_add) 3994188854Srrs{ 3995188854Srrs /* 3996188854Srrs * Peer is requesting to add more streams. If its within our 3997188854Srrs * max-streams we will allow it. 3998188854Srrs */ 3999233660Srrs uint32_t num_stream, i; 4000188854Srrs uint32_t seq; 4001189121Srrs struct sctp_association *asoc = &stcb->asoc; 4002216822Stuexen struct sctp_queued_to_read *ctl, *nctl; 4003188854Srrs 4004188854Srrs /* Get the number. */ 4005188854Srrs seq = ntohl(str_add->request_seq); 4006188854Srrs num_stream = ntohs(str_add->number_of_streams); 4007188854Srrs /* Now what would be the new total? */ 4008189121Srrs if (asoc->str_reset_seq_in == seq) { 4009189121Srrs num_stream += stcb->asoc.streamincnt; 4010235064Stuexen stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 4011235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 4012235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4013235064Stuexen } else if ((num_stream > stcb->asoc.max_inbound_streams) || 4014233660Srrs (num_stream > 0xffff)) { 4015189121Srrs /* We must reject it they ask for to many */ 4016189121Srrs denied: 4017235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4018189121Srrs } else { 4019189121Srrs /* Ok, we can do that :-) */ 4020189121Srrs struct sctp_stream_in *oldstrm; 4021189121Srrs 4022189121Srrs /* save off the old */ 4023189121Srrs oldstrm = stcb->asoc.strmin; 4024189121Srrs SCTP_MALLOC(stcb->asoc.strmin, struct sctp_stream_in *, 4025189121Srrs (num_stream * sizeof(struct sctp_stream_in)), 4026189121Srrs SCTP_M_STRMI); 4027189121Srrs if (stcb->asoc.strmin == NULL) { 4028189121Srrs stcb->asoc.strmin = oldstrm; 4029189121Srrs goto denied; 4030189121Srrs } 4031189121Srrs /* copy off the old data */ 4032189121Srrs for (i = 0; i < stcb->asoc.streamincnt; i++) { 4033189121Srrs TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 4034189121Srrs stcb->asoc.strmin[i].stream_no = i; 4035189121Srrs stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered; 4036189121Srrs stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started; 4037189121Srrs /* now anything on those queues? */ 4038216822Stuexen TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next, nctl) { 4039189121Srrs TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next); 4040189121Srrs TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next); 4041189121Srrs } 4042189121Srrs } 4043189121Srrs /* Init the new streams */ 4044189121Srrs for (i = stcb->asoc.streamincnt; i < num_stream; i++) { 4045189121Srrs TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 4046189121Srrs stcb->asoc.strmin[i].stream_no = i; 4047189121Srrs stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 4048189121Srrs stcb->asoc.strmin[i].delivery_started = 0; 4049189121Srrs } 4050189121Srrs SCTP_FREE(oldstrm, SCTP_M_STRMI); 4051189121Srrs /* update the size */ 4052189121Srrs stcb->asoc.streamincnt = num_stream; 4053235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 4054233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 4055189121Srrs } 4056233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 4057233660Srrs asoc->str_reset_seq_in++; 4058189121Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 4059189121Srrs /* 4060189121Srrs * one seq back, just echo back last action since my 4061189121Srrs * response was lost. 4062189121Srrs */ 4063189121Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 4064189121Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 4065189121Srrs /* 4066189121Srrs * two seq back, just echo back last action since my 4067189121Srrs * response was lost. 4068189121Srrs */ 4069189121Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 4070188854Srrs } else { 4071235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 4072188854Srrs 4073188854Srrs } 4074188854Srrs} 4075188854Srrs 4076233660Srrsstatic void 4077233660Srrssctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 4078233660Srrs struct sctp_stream_reset_add_strm *str_add) 4079233660Srrs{ 4080233660Srrs /* 4081233660Srrs * Peer is requesting to add more streams. If its within our 4082233660Srrs * max-streams we will allow it. 4083233660Srrs */ 4084233660Srrs uint16_t num_stream; 4085233660Srrs uint32_t seq; 4086233660Srrs struct sctp_association *asoc = &stcb->asoc; 4087233660Srrs 4088233660Srrs /* Get the number. */ 4089233660Srrs seq = ntohl(str_add->request_seq); 4090233660Srrs num_stream = ntohs(str_add->number_of_streams); 4091233660Srrs /* Now what would be the new total? */ 4092233660Srrs if (asoc->str_reset_seq_in == seq) { 4093235064Stuexen stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 4094235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 4095235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4096235064Stuexen } else if (stcb->asoc.stream_reset_outstanding) { 4097233660Srrs /* We must reject it we have something pending */ 4098235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 4099233660Srrs } else { 4100233660Srrs /* Ok, we can do that :-) */ 4101233660Srrs int mychk; 4102233660Srrs 4103233660Srrs mychk = stcb->asoc.streamoutcnt; 4104233660Srrs mychk += num_stream; 4105233660Srrs if (mychk < 0x10000) { 4106235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 4107294140Stuexen if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, num_stream, 0, 1)) { 4108235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4109233660Srrs } 4110233660Srrs } else { 4111235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4112233660Srrs } 4113233660Srrs } 4114233660Srrs sctp_add_stream_reset_result(chk, seq, stcb->asoc.last_reset_action[0]); 4115233660Srrs asoc->str_reset_seq_in++; 4116233660Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 4117233660Srrs /* 4118233660Srrs * one seq back, just echo back last action since my 4119233660Srrs * response was lost. 4120233660Srrs */ 4121233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 4122233660Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 4123233660Srrs /* 4124233660Srrs * two seq back, just echo back last action since my 4125233660Srrs * response was lost. 4126233660Srrs */ 4127233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 4128233660Srrs } else { 4129235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 4130233660Srrs } 4131233660Srrs} 4132233660Srrs 4133170992Srrs#ifdef __GNUC__ 4134170992Srrs__attribute__((noinline)) 4135170992Srrs#endif 4136170992Srrs static int 4137170992Srrs sctp_handle_stream_reset(struct sctp_tcb *stcb, struct mbuf *m, int offset, 4138240198Stuexen struct sctp_chunkhdr *ch_req) 4139163953Srrs{ 4140277807Sdelphij uint16_t remaining_length, param_len, ptype; 4141170992Srrs struct sctp_paramhdr pstore; 4142170992Srrs uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE]; 4143233660Srrs uint32_t seq = 0; 4144163953Srrs int num_req = 0; 4145170992Srrs int trunc = 0; 4146163953Srrs struct sctp_tmit_chunk *chk; 4147163953Srrs struct sctp_chunkhdr *ch; 4148163953Srrs struct sctp_paramhdr *ph; 4149166675Srrs int ret_code = 0; 4150166675Srrs int num_param = 0; 4151163953Srrs 4152163953Srrs /* now it may be a reset or a reset-response */ 4153277807Sdelphij remaining_length = ntohs(ch_req->chunk_length) - sizeof(struct sctp_chunkhdr); 4154163953Srrs 4155163953Srrs /* setup for adding the response */ 4156163953Srrs sctp_alloc_a_chunk(stcb, chk); 4157163953Srrs if (chk == NULL) { 4158163953Srrs return (ret_code); 4159163953Srrs } 4160273002Stuexen chk->copy_by_ref = 0; 4161163953Srrs chk->rec.chunk_id.id = SCTP_STREAM_RESET; 4162169208Srrs chk->rec.chunk_id.can_take_data = 0; 4163273002Stuexen chk->flags = 0; 4164163953Srrs chk->asoc = &stcb->asoc; 4165163953Srrs chk->no_fr_allowed = 0; 4166163953Srrs chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr); 4167166023Srrs chk->book_size_scale = 0; 4168243882Sglebius chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); 4169163953Srrs if (chk->data == NULL) { 4170163953Srrsstrres_nochunk: 4171163953Srrs if (chk->data) { 4172163953Srrs sctp_m_freem(chk->data); 4173163953Srrs chk->data = NULL; 4174163953Srrs } 4175221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 4176163953Srrs return (ret_code); 4177163953Srrs } 4178165647Srrs SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); 4179163953Srrs 4180163953Srrs /* setup chunk parameters */ 4181163953Srrs chk->sent = SCTP_DATAGRAM_UNSENT; 4182163953Srrs chk->snd_count = 0; 4183224641Stuexen chk->whoTo = NULL; 4184163953Srrs 4185163953Srrs ch = mtod(chk->data, struct sctp_chunkhdr *); 4186163953Srrs ch->chunk_type = SCTP_STREAM_RESET; 4187163953Srrs ch->chunk_flags = 0; 4188163953Srrs ch->chunk_length = htons(chk->send_size); 4189165647Srrs SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size); 4190170992Srrs offset += sizeof(struct sctp_chunkhdr); 4191277807Sdelphij while (remaining_length >= sizeof(struct sctp_paramhdr)) { 4192170992Srrs ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(pstore), (uint8_t *) & pstore); 4193277807Sdelphij if (ph == NULL) { 4194277807Sdelphij /* TSNH */ 4195170992Srrs break; 4196277807Sdelphij } 4197163953Srrs param_len = ntohs(ph->param_length); 4198277807Sdelphij if ((param_len > remaining_length) || 4199277807Sdelphij (param_len < (sizeof(struct sctp_paramhdr) + sizeof(uint32_t)))) { 4200277807Sdelphij /* bad parameter length */ 4201163953Srrs break; 4202163953Srrs } 4203277807Sdelphij ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, sizeof(cstore)), 4204170992Srrs (uint8_t *) & cstore); 4205277807Sdelphij if (ph == NULL) { 4206277807Sdelphij /* TSNH */ 4207277807Sdelphij break; 4208277807Sdelphij } 4209163953Srrs ptype = ntohs(ph->param_type); 4210163953Srrs num_param++; 4211277807Sdelphij if (param_len > sizeof(cstore)) { 4212170992Srrs trunc = 1; 4213170992Srrs } else { 4214170992Srrs trunc = 0; 4215170992Srrs } 4216163953Srrs if (num_param > SCTP_MAX_RESET_PARAMS) { 4217163953Srrs /* hit the max of parameters already sorry.. */ 4218163953Srrs break; 4219163953Srrs } 4220163953Srrs if (ptype == SCTP_STR_RESET_OUT_REQUEST) { 4221163953Srrs struct sctp_stream_reset_out_request *req_out; 4222163953Srrs 4223277807Sdelphij if (param_len < sizeof(struct sctp_stream_reset_out_request)) { 4224277807Sdelphij break; 4225277807Sdelphij } 4226163953Srrs req_out = (struct sctp_stream_reset_out_request *)ph; 4227163953Srrs num_req++; 4228163953Srrs if (stcb->asoc.stream_reset_outstanding) { 4229163953Srrs seq = ntohl(req_out->response_seq); 4230163953Srrs if (seq == stcb->asoc.str_reset_seq_out) { 4231163953Srrs /* implicit ack */ 4232235064Stuexen (void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_RESULT_PERFORMED, NULL); 4233163953Srrs } 4234163953Srrs } 4235170992Srrs sctp_handle_str_reset_request_out(stcb, chk, req_out, trunc); 4236233660Srrs } else if (ptype == SCTP_STR_RESET_ADD_OUT_STREAMS) { 4237188854Srrs struct sctp_stream_reset_add_strm *str_add; 4238188854Srrs 4239277807Sdelphij if (param_len < sizeof(struct sctp_stream_reset_add_strm)) { 4240277807Sdelphij break; 4241277807Sdelphij } 4242188854Srrs str_add = (struct sctp_stream_reset_add_strm *)ph; 4243188854Srrs num_req++; 4244188854Srrs sctp_handle_str_reset_add_strm(stcb, chk, str_add); 4245233660Srrs } else if (ptype == SCTP_STR_RESET_ADD_IN_STREAMS) { 4246233660Srrs struct sctp_stream_reset_add_strm *str_add; 4247233660Srrs 4248277807Sdelphij if (param_len < sizeof(struct sctp_stream_reset_add_strm)) { 4249277807Sdelphij break; 4250277807Sdelphij } 4251233660Srrs str_add = (struct sctp_stream_reset_add_strm *)ph; 4252233660Srrs num_req++; 4253233660Srrs sctp_handle_str_reset_add_out_strm(stcb, chk, str_add); 4254163953Srrs } else if (ptype == SCTP_STR_RESET_IN_REQUEST) { 4255163953Srrs struct sctp_stream_reset_in_request *req_in; 4256163953Srrs 4257163953Srrs num_req++; 4258163953Srrs req_in = (struct sctp_stream_reset_in_request *)ph; 4259170992Srrs sctp_handle_str_reset_request_in(stcb, chk, req_in, trunc); 4260163953Srrs } else if (ptype == SCTP_STR_RESET_TSN_REQUEST) { 4261163953Srrs struct sctp_stream_reset_tsn_request *req_tsn; 4262163953Srrs 4263163953Srrs num_req++; 4264163953Srrs req_tsn = (struct sctp_stream_reset_tsn_request *)ph; 4265163953Srrs if (sctp_handle_str_reset_request_tsn(stcb, chk, req_tsn)) { 4266163953Srrs ret_code = 1; 4267163953Srrs goto strres_nochunk; 4268163953Srrs } 4269163953Srrs /* no more */ 4270163953Srrs break; 4271163953Srrs } else if (ptype == SCTP_STR_RESET_RESPONSE) { 4272163953Srrs struct sctp_stream_reset_response *resp; 4273163953Srrs uint32_t result; 4274163953Srrs 4275277807Sdelphij if (param_len < sizeof(struct sctp_stream_reset_response)) { 4276277807Sdelphij break; 4277277807Sdelphij } 4278163953Srrs resp = (struct sctp_stream_reset_response *)ph; 4279163953Srrs seq = ntohl(resp->response_seq); 4280163953Srrs result = ntohl(resp->result); 4281163953Srrs if (sctp_handle_stream_reset_response(stcb, seq, result, resp)) { 4282163953Srrs ret_code = 1; 4283163953Srrs goto strres_nochunk; 4284163953Srrs } 4285163953Srrs } else { 4286163953Srrs break; 4287163953Srrs } 4288170992Srrs offset += SCTP_SIZE32(param_len); 4289277807Sdelphij if (remaining_length >= SCTP_SIZE32(param_len)) { 4290277807Sdelphij remaining_length -= SCTP_SIZE32(param_len); 4291277807Sdelphij } else { 4292277807Sdelphij remaining_length = 0; 4293277807Sdelphij } 4294163953Srrs } 4295163953Srrs if (num_req == 0) { 4296163953Srrs /* we have no response free the stuff */ 4297163953Srrs goto strres_nochunk; 4298163953Srrs } 4299163953Srrs /* ok we have a chunk to link in */ 4300163953Srrs TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue, 4301163953Srrs chk, 4302163953Srrs sctp_next); 4303163953Srrs stcb->asoc.ctrl_queue_cnt++; 4304163953Srrs return (ret_code); 4305163953Srrs} 4306163953Srrs 4307163953Srrs/* 4308163953Srrs * Handle a router or endpoints report of a packet loss, there are two ways 4309163953Srrs * to handle this, either we get the whole packet and must disect it 4310163953Srrs * ourselves (possibly with truncation and or corruption) or it is a summary 4311163953Srrs * from a middle box that did the disectting for us. 4312163953Srrs */ 4313163953Srrsstatic void 4314163953Srrssctp_handle_packet_dropped(struct sctp_pktdrop_chunk *cp, 4315170781Srrs struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t limit) 4316163953Srrs{ 4317163953Srrs uint32_t bottle_bw, on_queue; 4318163953Srrs uint16_t trunc_len; 4319163953Srrs unsigned int chlen; 4320163953Srrs unsigned int at; 4321163953Srrs struct sctp_chunk_desc desc; 4322163953Srrs struct sctp_chunkhdr *ch; 4323163953Srrs 4324163953Srrs chlen = ntohs(cp->ch.chunk_length); 4325163953Srrs chlen -= sizeof(struct sctp_pktdrop_chunk); 4326163953Srrs /* XXX possible chlen underflow */ 4327163953Srrs if (chlen == 0) { 4328163953Srrs ch = NULL; 4329163953Srrs if (cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) 4330163953Srrs SCTP_STAT_INCR(sctps_pdrpbwrpt); 4331163953Srrs } else { 4332163953Srrs ch = (struct sctp_chunkhdr *)(cp->data + sizeof(struct sctphdr)); 4333163953Srrs chlen -= sizeof(struct sctphdr); 4334163953Srrs /* XXX possible chlen underflow */ 4335163953Srrs memset(&desc, 0, sizeof(desc)); 4336163953Srrs } 4337163953Srrs trunc_len = (uint16_t) ntohs(cp->trunc_len); 4338170781Srrs if (trunc_len > limit) { 4339170781Srrs trunc_len = limit; 4340170781Srrs } 4341163953Srrs /* now the chunks themselves */ 4342163953Srrs while ((ch != NULL) && (chlen >= sizeof(struct sctp_chunkhdr))) { 4343163953Srrs desc.chunk_type = ch->chunk_type; 4344163953Srrs /* get amount we need to move */ 4345163953Srrs at = ntohs(ch->chunk_length); 4346163953Srrs if (at < sizeof(struct sctp_chunkhdr)) { 4347163953Srrs /* corrupt chunk, maybe at the end? */ 4348163953Srrs SCTP_STAT_INCR(sctps_pdrpcrupt); 4349163953Srrs break; 4350163953Srrs } 4351163953Srrs if (trunc_len == 0) { 4352163953Srrs /* we are supposed to have all of it */ 4353163953Srrs if (at > chlen) { 4354163953Srrs /* corrupt skip it */ 4355163953Srrs SCTP_STAT_INCR(sctps_pdrpcrupt); 4356163953Srrs break; 4357163953Srrs } 4358163953Srrs } else { 4359163953Srrs /* is there enough of it left ? */ 4360163953Srrs if (desc.chunk_type == SCTP_DATA) { 4361163953Srrs if (chlen < (sizeof(struct sctp_data_chunk) + 4362163953Srrs sizeof(desc.data_bytes))) { 4363163953Srrs break; 4364163953Srrs } 4365163953Srrs } else { 4366163953Srrs if (chlen < sizeof(struct sctp_chunkhdr)) { 4367163953Srrs break; 4368163953Srrs } 4369163953Srrs } 4370163953Srrs } 4371163953Srrs if (desc.chunk_type == SCTP_DATA) { 4372163953Srrs /* can we get out the tsn? */ 4373163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 4374163953Srrs SCTP_STAT_INCR(sctps_pdrpmbda); 4375163953Srrs 4376163953Srrs if (chlen >= (sizeof(struct sctp_data_chunk) + sizeof(uint32_t))) { 4377163953Srrs /* yep */ 4378163953Srrs struct sctp_data_chunk *dcp; 4379163953Srrs uint8_t *ddp; 4380163953Srrs unsigned int iii; 4381163953Srrs 4382163953Srrs dcp = (struct sctp_data_chunk *)ch; 4383163953Srrs ddp = (uint8_t *) (dcp + 1); 4384163953Srrs for (iii = 0; iii < sizeof(desc.data_bytes); iii++) { 4385163953Srrs desc.data_bytes[iii] = ddp[iii]; 4386163953Srrs } 4387163953Srrs desc.tsn_ifany = dcp->dp.tsn; 4388163953Srrs } else { 4389163953Srrs /* nope we are done. */ 4390163953Srrs SCTP_STAT_INCR(sctps_pdrpnedat); 4391163953Srrs break; 4392163953Srrs } 4393163953Srrs } else { 4394163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 4395163953Srrs SCTP_STAT_INCR(sctps_pdrpmbct); 4396163953Srrs } 4397163953Srrs 4398163953Srrs if (process_chunk_drop(stcb, &desc, net, cp->ch.chunk_flags)) { 4399163953Srrs SCTP_STAT_INCR(sctps_pdrppdbrk); 4400163953Srrs break; 4401163953Srrs } 4402163953Srrs if (SCTP_SIZE32(at) > chlen) { 4403163953Srrs break; 4404163953Srrs } 4405163953Srrs chlen -= SCTP_SIZE32(at); 4406163953Srrs if (chlen < sizeof(struct sctp_chunkhdr)) { 4407163953Srrs /* done, none left */ 4408163953Srrs break; 4409163953Srrs } 4410163953Srrs ch = (struct sctp_chunkhdr *)((caddr_t)ch + SCTP_SIZE32(at)); 4411163953Srrs } 4412163953Srrs /* Now update any rwnd --- possibly */ 4413163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) == 0) { 4414163953Srrs /* From a peer, we get a rwnd report */ 4415163953Srrs uint32_t a_rwnd; 4416163953Srrs 4417163953Srrs SCTP_STAT_INCR(sctps_pdrpfehos); 4418163953Srrs 4419163953Srrs bottle_bw = ntohl(cp->bottle_bw); 4420163953Srrs on_queue = ntohl(cp->current_onq); 4421163953Srrs if (bottle_bw && on_queue) { 4422163953Srrs /* a rwnd report is in here */ 4423163953Srrs if (bottle_bw > on_queue) 4424163953Srrs a_rwnd = bottle_bw - on_queue; 4425163953Srrs else 4426163953Srrs a_rwnd = 0; 4427163953Srrs 4428163953Srrs if (a_rwnd == 0) 4429163953Srrs stcb->asoc.peers_rwnd = 0; 4430163953Srrs else { 4431163953Srrs if (a_rwnd > stcb->asoc.total_flight) { 4432163953Srrs stcb->asoc.peers_rwnd = 4433163953Srrs a_rwnd - stcb->asoc.total_flight; 4434163953Srrs } else { 4435163953Srrs stcb->asoc.peers_rwnd = 0; 4436163953Srrs } 4437163953Srrs if (stcb->asoc.peers_rwnd < 4438163953Srrs stcb->sctp_ep->sctp_ep.sctp_sws_sender) { 4439163953Srrs /* SWS sender side engages */ 4440163953Srrs stcb->asoc.peers_rwnd = 0; 4441163953Srrs } 4442163953Srrs } 4443163953Srrs } 4444163953Srrs } else { 4445163953Srrs SCTP_STAT_INCR(sctps_pdrpfmbox); 4446163953Srrs } 4447163953Srrs 4448163953Srrs /* now middle boxes in sat networks get a cwnd bump */ 4449163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) && 4450163953Srrs (stcb->asoc.sat_t3_loss_recovery == 0) && 4451163953Srrs (stcb->asoc.sat_network)) { 4452163953Srrs /* 4453163953Srrs * This is debateable but for sat networks it makes sense 4454163953Srrs * Note if a T3 timer has went off, we will prohibit any 4455163953Srrs * changes to cwnd until we exit the t3 loss recovery. 4456163953Srrs */ 4457171440Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped(stcb, 4458171440Srrs net, cp, &bottle_bw, &on_queue); 4459163953Srrs } 4460163953Srrs} 4461163953Srrs 4462163953Srrs/* 4463163953Srrs * handles all control chunks in a packet inputs: - m: mbuf chain, assumed to 4464163953Srrs * still contain IP/SCTP header - stcb: is the tcb found for this packet - 4465163953Srrs * offset: offset into the mbuf chain to first chunkhdr - length: is the 4466163953Srrs * length of the complete packet outputs: - length: modified to remaining 4467163953Srrs * length after control processing - netp: modified to new sctp_nets after 4468163953Srrs * cookie-echo processing - return NULL to discard the packet (ie. no asoc, 4469163953Srrs * bad packet,...) otherwise return the tcb for this packet 4470163953Srrs */ 4471170099Srrs#ifdef __GNUC__ 4472170099Srrs__attribute__((noinline)) 4473170099Srrs#endif 4474170099Srrs static struct sctp_tcb * 4475170099Srrs sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, 4476237715Stuexen struct sockaddr *src, struct sockaddr *dst, 4477170099Srrs struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp, 4478170099Srrs struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen, 4479284633Stuexen uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, 4480179157Srrs uint32_t vrf_id, uint16_t port) 4481163953Srrs{ 4482163953Srrs struct sctp_association *asoc; 4483267723Stuexen struct mbuf *op_err; 4484267723Stuexen char msg[SCTP_DIAG_INFO_LEN]; 4485163953Srrs uint32_t vtag_in; 4486163953Srrs int num_chunks = 0; /* number of control chunks processed */ 4487170140Srrs uint32_t chk_length; 4488163953Srrs int ret; 4489168299Srrs int abort_no_unlock = 0; 4490218186Srrs int ecne_seen = 0; 4491163953Srrs 4492163953Srrs /* 4493163953Srrs * How big should this be, and should it be alloc'd? Lets try the 4494163953Srrs * d-mtu-ceiling for now (2k) and that should hopefully work ... 4495163953Srrs * until we get into jumbo grams and such.. 4496163953Srrs */ 4497166675Srrs uint8_t chunk_buf[SCTP_CHUNK_BUFFER_SIZE]; 4498163953Srrs struct sctp_tcb *locked_tcb = stcb; 4499163953Srrs int got_auth = 0; 4500163953Srrs uint32_t auth_offset = 0, auth_len = 0; 4501163953Srrs int auth_skipped = 0; 4502171990Srrs int asconf_cnt = 0; 4503163953Srrs 4504237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4505172090Srrs struct socket *so; 4506172090Srrs 4507172090Srrs#endif 4508172090Srrs 4509169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n", 4510240148Stuexen iphlen, *offset, length, (void *)stcb); 4511163953Srrs 4512163953Srrs /* validate chunk header length... */ 4513163953Srrs if (ntohs(ch->chunk_length) < sizeof(*ch)) { 4514170056Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Invalid header length %d\n", 4515170056Srrs ntohs(ch->chunk_length)); 4516170091Srrs if (locked_tcb) { 4517170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4518170091Srrs } 4519163953Srrs return (NULL); 4520163953Srrs } 4521163953Srrs /* 4522163953Srrs * validate the verification tag 4523163953Srrs */ 4524163953Srrs vtag_in = ntohl(sh->v_tag); 4525163953Srrs 4526165220Srrs if (locked_tcb) { 4527165220Srrs SCTP_TCB_LOCK_ASSERT(locked_tcb); 4528165220Srrs } 4529163953Srrs if (ch->chunk_type == SCTP_INITIATION) { 4530170056Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Its an INIT of len:%d vtag:%x\n", 4531170056Srrs ntohs(ch->chunk_length), vtag_in); 4532163953Srrs if (vtag_in != 0) { 4533163953Srrs /* protocol error- silently discard... */ 4534163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4535169378Srrs if (locked_tcb) { 4536163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4537169378Srrs } 4538163953Srrs return (NULL); 4539163953Srrs } 4540163953Srrs } else if (ch->chunk_type != SCTP_COOKIE_ECHO) { 4541163953Srrs /* 4542163953Srrs * If there is no stcb, skip the AUTH chunk and process 4543163953Srrs * later after a stcb is found (to validate the lookup was 4544163953Srrs * valid. 4545163953Srrs */ 4546163953Srrs if ((ch->chunk_type == SCTP_AUTHENTICATION) && 4547179783Srrs (stcb == NULL) && 4548270362Stuexen (inp->auth_supported == 1)) { 4549163953Srrs /* save this chunk for later processing */ 4550163953Srrs auth_skipped = 1; 4551163953Srrs auth_offset = *offset; 4552163953Srrs auth_len = ntohs(ch->chunk_length); 4553163953Srrs 4554163953Srrs /* (temporarily) move past this chunk */ 4555163953Srrs *offset += SCTP_SIZE32(auth_len); 4556163953Srrs if (*offset >= length) { 4557163953Srrs /* no more data left in the mbuf chain */ 4558163953Srrs *offset = length; 4559170091Srrs if (locked_tcb) { 4560170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4561170091Srrs } 4562163953Srrs return (NULL); 4563163953Srrs } 4564163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4565163953Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 4566163953Srrs } 4567169420Srrs if (ch == NULL) { 4568169420Srrs /* Help */ 4569169420Srrs *offset = length; 4570170091Srrs if (locked_tcb) { 4571170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4572170091Srrs } 4573169420Srrs return (NULL); 4574169420Srrs } 4575163953Srrs if (ch->chunk_type == SCTP_COOKIE_ECHO) { 4576163953Srrs goto process_control_chunks; 4577163953Srrs } 4578163953Srrs /* 4579163953Srrs * first check if it's an ASCONF with an unknown src addr we 4580163953Srrs * need to look inside to find the association 4581163953Srrs */ 4582163953Srrs if (ch->chunk_type == SCTP_ASCONF && stcb == NULL) { 4583171990Srrs struct sctp_chunkhdr *asconf_ch = ch; 4584171990Srrs uint32_t asconf_offset = 0, asconf_len = 0; 4585171990Srrs 4586163953Srrs /* inp's refcount may be reduced */ 4587163953Srrs SCTP_INP_INCR_REF(inp); 4588163953Srrs 4589171990Srrs asconf_offset = *offset; 4590171990Srrs do { 4591171990Srrs asconf_len = ntohs(asconf_ch->chunk_length); 4592171990Srrs if (asconf_len < sizeof(struct sctp_asconf_paramhdr)) 4593171990Srrs break; 4594228653Stuexen stcb = sctp_findassociation_ep_asconf(m, 4595237715Stuexen *offset, 4596237715Stuexen dst, 4597237715Stuexen sh, &inp, netp, vrf_id); 4598171990Srrs if (stcb != NULL) 4599171990Srrs break; 4600171990Srrs asconf_offset += SCTP_SIZE32(asconf_len); 4601171990Srrs asconf_ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, asconf_offset, 4602171990Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 4603171990Srrs } while (asconf_ch != NULL && asconf_ch->chunk_type == SCTP_ASCONF); 4604163953Srrs if (stcb == NULL) { 4605163953Srrs /* 4606163953Srrs * reduce inp's refcount if not reduced in 4607163953Srrs * sctp_findassociation_ep_asconf(). 4608163953Srrs */ 4609163953Srrs SCTP_INP_DECR_REF(inp); 4610171990Srrs } else { 4611171990Srrs locked_tcb = stcb; 4612163953Srrs } 4613171990Srrs 4614163953Srrs /* now go back and verify any auth chunk to be sure */ 4615163953Srrs if (auth_skipped && (stcb != NULL)) { 4616163953Srrs struct sctp_auth_chunk *auth; 4617163953Srrs 4618163953Srrs auth = (struct sctp_auth_chunk *) 4619163953Srrs sctp_m_getptr(m, auth_offset, 4620163953Srrs auth_len, chunk_buf); 4621163953Srrs got_auth = 1; 4622163953Srrs auth_skipped = 0; 4623169420Srrs if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, 4624163953Srrs auth_offset)) { 4625163953Srrs /* auth HMAC failed so dump it */ 4626163953Srrs *offset = length; 4627170091Srrs if (locked_tcb) { 4628170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4629170091Srrs } 4630163953Srrs return (NULL); 4631163953Srrs } else { 4632163953Srrs /* remaining chunks are HMAC checked */ 4633163953Srrs stcb->asoc.authenticated = 1; 4634163953Srrs } 4635163953Srrs } 4636163953Srrs } 4637163953Srrs if (stcb == NULL) { 4638294174Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); 4639267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 4640267723Stuexen msg); 4641163953Srrs /* no association, so it's out of the blue... */ 4642267723Stuexen sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err, 4643284633Stuexen mflowtype, mflowid, inp->fibnum, 4644179157Srrs vrf_id, port); 4645163953Srrs *offset = length; 4646169378Srrs if (locked_tcb) { 4647163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4648169378Srrs } 4649163953Srrs return (NULL); 4650163953Srrs } 4651163953Srrs asoc = &stcb->asoc; 4652163953Srrs /* ABORT and SHUTDOWN can use either v_tag... */ 4653163953Srrs if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) || 4654163953Srrs (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) || 4655163953Srrs (ch->chunk_type == SCTP_PACKET_DROPPED)) { 4656252718Stuexen /* Take the T-bit always into account. */ 4657252718Stuexen if ((((ch->chunk_flags & SCTP_HAD_NO_TCB) == 0) && 4658252718Stuexen (vtag_in == asoc->my_vtag)) || 4659252718Stuexen (((ch->chunk_flags & SCTP_HAD_NO_TCB) == SCTP_HAD_NO_TCB) && 4660163953Srrs (vtag_in == asoc->peer_vtag))) { 4661163953Srrs /* this is valid */ 4662163953Srrs } else { 4663163953Srrs /* drop this packet... */ 4664163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4665169378Srrs if (locked_tcb) { 4666163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4667169378Srrs } 4668163953Srrs return (NULL); 4669163953Srrs } 4670163953Srrs } else if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 4671163953Srrs if (vtag_in != asoc->my_vtag) { 4672163953Srrs /* 4673163953Srrs * this could be a stale SHUTDOWN-ACK or the 4674163953Srrs * peer never got the SHUTDOWN-COMPLETE and 4675163953Srrs * is still hung; we have started a new asoc 4676163953Srrs * but it won't complete until the shutdown 4677163953Srrs * is completed 4678163953Srrs */ 4679169378Srrs if (locked_tcb) { 4680163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4681169378Srrs } 4682294174Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); 4683267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 4684267723Stuexen msg); 4685237715Stuexen sctp_handle_ootb(m, iphlen, *offset, src, dst, 4686267723Stuexen sh, inp, op_err, 4687284633Stuexen mflowtype, mflowid, fibnum, 4688236450Stuexen vrf_id, port); 4689163953Srrs return (NULL); 4690163953Srrs } 4691163953Srrs } else { 4692163953Srrs /* for all other chunks, vtag must match */ 4693163953Srrs if (vtag_in != asoc->my_vtag) { 4694163953Srrs /* invalid vtag... */ 4695169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 4696169420Srrs "invalid vtag: %xh, expect %xh\n", 4697169420Srrs vtag_in, asoc->my_vtag); 4698163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4699169378Srrs if (locked_tcb) { 4700163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4701169378Srrs } 4702163953Srrs *offset = length; 4703163953Srrs return (NULL); 4704163953Srrs } 4705163953Srrs } 4706163953Srrs } /* end if !SCTP_COOKIE_ECHO */ 4707163953Srrs /* 4708163953Srrs * process all control chunks... 4709163953Srrs */ 4710163953Srrs if (((ch->chunk_type == SCTP_SELECTIVE_ACK) || 4711185694Srrs (ch->chunk_type == SCTP_NR_SELECTIVE_ACK) || 4712163953Srrs (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) && 4713163953Srrs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { 4714163953Srrs /* implied cookie-ack.. we must have lost the ack */ 4715179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 4716171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 4717171943Srrs stcb->asoc.overall_error_count, 4718171943Srrs 0, 4719171943Srrs SCTP_FROM_SCTP_INPUT, 4720171943Srrs __LINE__); 4721171943Srrs } 4722163953Srrs stcb->asoc.overall_error_count = 0; 4723163953Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, 4724163953Srrs *netp); 4725163953Srrs } 4726163953Srrsprocess_control_chunks: 4727163953Srrs while (IS_SCTP_CONTROL(ch)) { 4728163953Srrs /* validate chunk length */ 4729163953Srrs chk_length = ntohs(ch->chunk_length); 4730169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_process_control: processing a chunk type=%u, len=%u\n", 4731169420Srrs ch->chunk_type, chk_length); 4732170744Srrs SCTP_LTRACE_CHK(inp, stcb, ch->chunk_type, chk_length); 4733170140Srrs if (chk_length < sizeof(*ch) || 4734170140Srrs (*offset + (int)chk_length) > length) { 4735163953Srrs *offset = length; 4736169378Srrs if (locked_tcb) { 4737163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4738169378Srrs } 4739163953Srrs return (NULL); 4740163953Srrs } 4741163953Srrs SCTP_STAT_INCR_COUNTER64(sctps_incontrolchunks); 4742163953Srrs /* 4743163953Srrs * INIT-ACK only gets the init ack "header" portion only 4744163953Srrs * because we don't have to process the peer's COOKIE. All 4745163953Srrs * others get a complete chunk. 4746163953Srrs */ 4747169208Srrs if ((ch->chunk_type == SCTP_INITIATION_ACK) || 4748169208Srrs (ch->chunk_type == SCTP_INITIATION)) { 4749163953Srrs /* get an init-ack chunk */ 4750163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4751163953Srrs sizeof(struct sctp_init_ack_chunk), chunk_buf); 4752163953Srrs if (ch == NULL) { 4753163953Srrs *offset = length; 4754169378Srrs if (locked_tcb) { 4755163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4756169378Srrs } 4757163953Srrs return (NULL); 4758163953Srrs } 4759170642Srrs } else { 4760170786Srrs /* For cookies and all other chunks. */ 4761169208Srrs if (chk_length > sizeof(chunk_buf)) { 4762169208Srrs /* 4763169208Srrs * use just the size of the chunk buffer so 4764170642Srrs * the front part of our chunks fit in 4765170642Srrs * contiguous space up to the chunk buffer 4766170642Srrs * size (508 bytes). For chunks that need to 4767170786Srrs * get more than that they must use the 4768170642Srrs * sctp_m_getptr() function or other means 4769170786Srrs * (e.g. know how to parse mbuf chains). 4770170786Srrs * Cookies do this already. 4771169208Srrs */ 4772169208Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4773169208Srrs (sizeof(chunk_buf) - 4), 4774169208Srrs chunk_buf); 4775169208Srrs if (ch == NULL) { 4776169208Srrs *offset = length; 4777169378Srrs if (locked_tcb) { 4778169208Srrs SCTP_TCB_UNLOCK(locked_tcb); 4779169378Srrs } 4780169208Srrs return (NULL); 4781169208Srrs } 4782169208Srrs } else { 4783169208Srrs /* We can fit it all */ 4784170642Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4785170642Srrs chk_length, chunk_buf); 4786170642Srrs if (ch == NULL) { 4787170642Srrs SCTP_PRINTF("sctp_process_control: Can't get the all data....\n"); 4788170642Srrs *offset = length; 4789170642Srrs if (locked_tcb) { 4790170642Srrs SCTP_TCB_UNLOCK(locked_tcb); 4791169208Srrs } 4792170642Srrs return (NULL); 4793163953Srrs } 4794163953Srrs } 4795163953Srrs } 4796163953Srrs num_chunks++; 4797163953Srrs /* Save off the last place we got a control from */ 4798163953Srrs if (stcb != NULL) { 4799169420Srrs if (((netp != NULL) && (*netp != NULL)) || (ch->chunk_type == SCTP_ASCONF)) { 4800163953Srrs /* 4801163953Srrs * allow last_control to be NULL if 4802163953Srrs * ASCONF... ASCONF processing will find the 4803163953Srrs * right net later 4804163953Srrs */ 4805169420Srrs if ((netp != NULL) && (*netp != NULL)) 4806169420Srrs stcb->asoc.last_control_chunk_from = *netp; 4807163953Srrs } 4808163953Srrs } 4809163953Srrs#ifdef SCTP_AUDITING_ENABLED 4810163953Srrs sctp_audit_log(0xB0, ch->chunk_type); 4811163953Srrs#endif 4812163953Srrs 4813163953Srrs /* check to see if this chunk required auth, but isn't */ 4814179783Srrs if ((stcb != NULL) && 4815270362Stuexen (stcb->asoc.auth_supported == 1) && 4816179783Srrs sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) && 4817163953Srrs !stcb->asoc.authenticated) { 4818163953Srrs /* "silently" ignore */ 4819163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 4820163953Srrs goto next_chunk; 4821163953Srrs } 4822163953Srrs switch (ch->chunk_type) { 4823163953Srrs case SCTP_INITIATION: 4824169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT\n"); 4825229774Stuexen /* The INIT chunk must be the only chunk. */ 4826229774Stuexen if ((num_chunks > 1) || 4827229775Stuexen (length - *offset > (int)SCTP_SIZE32(chk_length))) { 4828294155Stuexen /* RFC 4960 requires that no ABORT is sent */ 4829163953Srrs *offset = length; 4830294155Stuexen if (locked_tcb) { 4831294155Stuexen SCTP_TCB_UNLOCK(locked_tcb); 4832294155Stuexen } 4833163953Srrs return (NULL); 4834163953Srrs } 4835229774Stuexen /* Honor our resource limit. */ 4836229774Stuexen if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) { 4837267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 4838237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, 4839237715Stuexen src, dst, sh, op_err, 4840281955Shiren mflowtype, mflowid, 4841237049Stuexen vrf_id, port); 4842163953Srrs *offset = length; 4843163953Srrs return (NULL); 4844163953Srrs } 4845237715Stuexen sctp_handle_init(m, iphlen, *offset, src, dst, sh, 4846229774Stuexen (struct sctp_init_chunk *)ch, inp, 4847295208Stuexen stcb, *netp, &abort_no_unlock, 4848281955Shiren mflowtype, mflowid, 4849237049Stuexen vrf_id, port); 4850163953Srrs *offset = length; 4851229774Stuexen if ((!abort_no_unlock) && (locked_tcb)) { 4852163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4853169378Srrs } 4854163953Srrs return (NULL); 4855163953Srrs break; 4856170642Srrs case SCTP_PAD_CHUNK: 4857170642Srrs break; 4858163953Srrs case SCTP_INITIATION_ACK: 4859169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n"); 4860163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 4861163953Srrs /* We are not interested anymore */ 4862163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 4863163953Srrs ; 4864163953Srrs } else { 4865296052Stuexen if ((locked_tcb != NULL) && (locked_tcb != stcb)) { 4866208876Srrs /* Very unlikely */ 4867163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4868169378Srrs } 4869163953Srrs *offset = length; 4870163953Srrs if (stcb) { 4871237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4872172090Srrs so = SCTP_INP_SO(inp); 4873172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 4874172090Srrs SCTP_TCB_UNLOCK(stcb); 4875172090Srrs SCTP_SOCKET_LOCK(so, 1); 4876172090Srrs SCTP_TCB_LOCK(stcb); 4877172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 4878172090Srrs#endif 4879283822Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 4880283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_29); 4881237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4882172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4883172090Srrs#endif 4884163953Srrs } 4885163953Srrs return (NULL); 4886163953Srrs } 4887163953Srrs } 4888229775Stuexen /* The INIT-ACK chunk must be the only chunk. */ 4889163953Srrs if ((num_chunks > 1) || 4890229775Stuexen (length - *offset > (int)SCTP_SIZE32(chk_length))) { 4891163953Srrs *offset = length; 4892169378Srrs if (locked_tcb) { 4893163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4894169378Srrs } 4895163953Srrs return (NULL); 4896163953Srrs } 4897169420Srrs if ((netp) && (*netp)) { 4898237715Stuexen ret = sctp_handle_init_ack(m, iphlen, *offset, 4899237715Stuexen src, dst, sh, 4900237049Stuexen (struct sctp_init_ack_chunk *)ch, 4901237049Stuexen stcb, *netp, 4902237049Stuexen &abort_no_unlock, 4903281955Shiren mflowtype, mflowid, 4904237049Stuexen vrf_id); 4905169420Srrs } else { 4906169420Srrs ret = -1; 4907169420Srrs } 4908229774Stuexen *offset = length; 4909229774Stuexen if (abort_no_unlock) { 4910229774Stuexen return (NULL); 4911229774Stuexen } 4912163953Srrs /* 4913163953Srrs * Special case, I must call the output routine to 4914163953Srrs * get the cookie echoed 4915163953Srrs */ 4916229774Stuexen if ((stcb != NULL) && (ret == 0)) { 4917172090Srrs sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 4918229774Stuexen } 4919169378Srrs if (locked_tcb) { 4920163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4921169378Srrs } 4922163953Srrs return (NULL); 4923163953Srrs break; 4924163953Srrs case SCTP_SELECTIVE_ACK: 4925163953Srrs { 4926163953Srrs struct sctp_sack_chunk *sack; 4927163953Srrs int abort_now = 0; 4928163953Srrs uint32_t a_rwnd, cum_ack; 4929202526Stuexen uint16_t num_seg, num_dup; 4930202526Stuexen uint8_t flags; 4931202526Stuexen int offset_seg, offset_dup; 4932163953Srrs 4933211944Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n"); 4934211944Stuexen SCTP_STAT_INCR(sctps_recvsacks); 4935202526Stuexen if (stcb == NULL) { 4936202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing SACK chunk\n"); 4937202526Stuexen break; 4938169208Srrs } 4939202526Stuexen if (chk_length < sizeof(struct sctp_sack_chunk)) { 4940202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on SACK chunk, too small\n"); 4941202526Stuexen break; 4942202526Stuexen } 4943171990Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 4944171990Srrs /*- 4945171990Srrs * If we have sent a shutdown-ack, we will pay no 4946171990Srrs * attention to a sack sent in to us since 4947171990Srrs * we don't care anymore. 4948171990Srrs */ 4949184883Srrs break; 4950171990Srrs } 4951163953Srrs sack = (struct sctp_sack_chunk *)ch; 4952202526Stuexen flags = ch->chunk_flags; 4953163953Srrs cum_ack = ntohl(sack->sack.cum_tsn_ack); 4954163953Srrs num_seg = ntohs(sack->sack.num_gap_ack_blks); 4955202526Stuexen num_dup = ntohs(sack->sack.num_dup_tsns); 4956163953Srrs a_rwnd = (uint32_t) ntohl(sack->sack.a_rwnd); 4957202526Stuexen if (sizeof(struct sctp_sack_chunk) + 4958202526Stuexen num_seg * sizeof(struct sctp_gap_ack_block) + 4959202526Stuexen num_dup * sizeof(uint32_t) != chk_length) { 4960202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of SACK chunk\n"); 4961202526Stuexen break; 4962202526Stuexen } 4963202526Stuexen offset_seg = *offset + sizeof(struct sctp_sack_chunk); 4964202526Stuexen offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 4965170606Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 4966202526Stuexen cum_ack, num_seg, a_rwnd); 4967163953Srrs stcb->asoc.seen_a_sack_this_pkt = 1; 4968163953Srrs if ((stcb->asoc.pr_sctp_cnt == 0) && 4969163953Srrs (num_seg == 0) && 4970216825Stuexen SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 4971163953Srrs (stcb->asoc.saw_sack_with_frags == 0) && 4972216188Stuexen (stcb->asoc.saw_sack_with_nr_frags == 0) && 4973163953Srrs (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) 4974163953Srrs ) { 4975163953Srrs /* 4976163953Srrs * We have a SIMPLE sack having no 4977163953Srrs * prior segments and data on sent 4978163953Srrs * queue to be acked.. Use the 4979163953Srrs * faster path sack processing. We 4980163953Srrs * also allow window update sacks 4981163953Srrs * with no missing segments to go 4982163953Srrs * this way too. 4983163953Srrs */ 4984218186Srrs sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now, ecne_seen); 4985163953Srrs } else { 4986169420Srrs if (netp && *netp) 4987228653Stuexen sctp_handle_sack(m, offset_seg, offset_dup, stcb, 4988202526Stuexen num_seg, 0, num_dup, &abort_now, flags, 4989218186Srrs cum_ack, a_rwnd, ecne_seen); 4990163953Srrs } 4991202526Stuexen if (abort_now) { 4992202526Stuexen /* ABORT signal from sack processing */ 4993202526Stuexen *offset = length; 4994202526Stuexen return (NULL); 4995202526Stuexen } 4996185694Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 4997185694Srrs TAILQ_EMPTY(&stcb->asoc.sent_queue) && 4998185694Srrs (stcb->asoc.stream_queue_cnt == 0)) { 4999185694Srrs sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 5000185694Srrs } 5001163953Srrs } 5002163953Srrs break; 5003185694Srrs /* 5004185694Srrs * EY - nr_sack: If the received chunk is an 5005185694Srrs * nr_sack chunk 5006185694Srrs */ 5007185694Srrs case SCTP_NR_SELECTIVE_ACK: 5008185694Srrs { 5009185694Srrs struct sctp_nr_sack_chunk *nr_sack; 5010185694Srrs int abort_now = 0; 5011185694Srrs uint32_t a_rwnd, cum_ack; 5012202526Stuexen uint16_t num_seg, num_nr_seg, num_dup; 5013202526Stuexen uint8_t flags; 5014202526Stuexen int offset_seg, offset_dup; 5015185694Srrs 5016211944Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n"); 5017211944Stuexen SCTP_STAT_INCR(sctps_recvsacks); 5018212225Srrs if (stcb == NULL) { 5019212225Srrs SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing NR-SACK chunk\n"); 5020212225Srrs break; 5021212225Srrs } 5022270359Stuexen if (stcb->asoc.nrsack_supported == 0) { 5023185694Srrs goto unknown_chunk; 5024185694Srrs } 5025202526Stuexen if (chk_length < sizeof(struct sctp_nr_sack_chunk)) { 5026202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on NR-SACK chunk, too small\n"); 5027202526Stuexen break; 5028202526Stuexen } 5029185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 5030185694Srrs /*- 5031185694Srrs * If we have sent a shutdown-ack, we will pay no 5032185694Srrs * attention to a sack sent in to us since 5033185694Srrs * we don't care anymore. 5034185694Srrs */ 5035202526Stuexen break; 5036185694Srrs } 5037185694Srrs nr_sack = (struct sctp_nr_sack_chunk *)ch; 5038202526Stuexen flags = ch->chunk_flags; 5039185694Srrs cum_ack = ntohl(nr_sack->nr_sack.cum_tsn_ack); 5040185694Srrs num_seg = ntohs(nr_sack->nr_sack.num_gap_ack_blks); 5041185694Srrs num_nr_seg = ntohs(nr_sack->nr_sack.num_nr_gap_ack_blks); 5042202526Stuexen num_dup = ntohs(nr_sack->nr_sack.num_dup_tsns); 5043185694Srrs a_rwnd = (uint32_t) ntohl(nr_sack->nr_sack.a_rwnd); 5044202526Stuexen if (sizeof(struct sctp_nr_sack_chunk) + 5045202526Stuexen (num_seg + num_nr_seg) * sizeof(struct sctp_gap_ack_block) + 5046202526Stuexen num_dup * sizeof(uint32_t) != chk_length) { 5047202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of NR_SACK chunk\n"); 5048202526Stuexen break; 5049202526Stuexen } 5050202526Stuexen offset_seg = *offset + sizeof(struct sctp_nr_sack_chunk); 5051202526Stuexen offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 5052185694Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 5053202526Stuexen cum_ack, num_seg, a_rwnd); 5054185694Srrs stcb->asoc.seen_a_sack_this_pkt = 1; 5055185694Srrs if ((stcb->asoc.pr_sctp_cnt == 0) && 5056202526Stuexen (num_seg == 0) && (num_nr_seg == 0) && 5057216825Stuexen SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 5058185694Srrs (stcb->asoc.saw_sack_with_frags == 0) && 5059216188Stuexen (stcb->asoc.saw_sack_with_nr_frags == 0) && 5060202526Stuexen (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 5061185694Srrs /* 5062185694Srrs * We have a SIMPLE sack having no 5063185694Srrs * prior segments and data on sent 5064202526Stuexen * queue to be acked. Use the faster 5065202526Stuexen * path sack processing. We also 5066202526Stuexen * allow window update sacks with no 5067202526Stuexen * missing segments to go this way 5068202526Stuexen * too. 5069185694Srrs */ 5070218129Srrs sctp_express_handle_sack(stcb, cum_ack, a_rwnd, 5071218186Srrs &abort_now, ecne_seen); 5072185694Srrs } else { 5073185694Srrs if (netp && *netp) 5074228653Stuexen sctp_handle_sack(m, offset_seg, offset_dup, stcb, 5075202526Stuexen num_seg, num_nr_seg, num_dup, &abort_now, flags, 5076218186Srrs cum_ack, a_rwnd, ecne_seen); 5077185694Srrs } 5078202526Stuexen if (abort_now) { 5079202526Stuexen /* ABORT signal from sack processing */ 5080202526Stuexen *offset = length; 5081202526Stuexen return (NULL); 5082202526Stuexen } 5083185694Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 5084185694Srrs TAILQ_EMPTY(&stcb->asoc.sent_queue) && 5085185694Srrs (stcb->asoc.stream_queue_cnt == 0)) { 5086185694Srrs sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 5087185694Srrs } 5088185694Srrs } 5089185694Srrs break; 5090185694Srrs 5091163953Srrs case SCTP_HEARTBEAT_REQUEST: 5092169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT\n"); 5093169420Srrs if ((stcb) && netp && *netp) { 5094169420Srrs SCTP_STAT_INCR(sctps_recvheartbeat); 5095169420Srrs sctp_send_heartbeat_ack(stcb, m, *offset, 5096169420Srrs chk_length, *netp); 5097169420Srrs 5098169420Srrs /* He's alive so give him credit */ 5099179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5100171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5101171943Srrs stcb->asoc.overall_error_count, 5102171943Srrs 0, 5103171943Srrs SCTP_FROM_SCTP_INPUT, 5104171943Srrs __LINE__); 5105171943Srrs } 5106169420Srrs stcb->asoc.overall_error_count = 0; 5107163953Srrs } 5108163953Srrs break; 5109163953Srrs case SCTP_HEARTBEAT_ACK: 5110169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT-ACK\n"); 5111169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_heartbeat_chunk))) { 5112169208Srrs /* Its not ours */ 5113169352Srrs *offset = length; 5114169378Srrs if (locked_tcb) { 5115169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5116169378Srrs } 5117169208Srrs return (NULL); 5118169208Srrs } 5119163953Srrs /* He's alive so give him credit */ 5120179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5121171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5122171943Srrs stcb->asoc.overall_error_count, 5123171943Srrs 0, 5124171943Srrs SCTP_FROM_SCTP_INPUT, 5125171943Srrs __LINE__); 5126171943Srrs } 5127163953Srrs stcb->asoc.overall_error_count = 0; 5128163953Srrs SCTP_STAT_INCR(sctps_recvheartbeatack); 5129169420Srrs if (netp && *netp) 5130169420Srrs sctp_handle_heartbeat_ack((struct sctp_heartbeat_chunk *)ch, 5131169420Srrs stcb, *netp); 5132163953Srrs break; 5133163953Srrs case SCTP_ABORT_ASSOCIATION: 5134170091Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT, stcb %p\n", 5135240148Stuexen (void *)stcb); 5136169420Srrs if ((stcb) && netp && *netp) 5137169420Srrs sctp_handle_abort((struct sctp_abort_chunk *)ch, 5138169420Srrs stcb, *netp); 5139163953Srrs *offset = length; 5140163953Srrs return (NULL); 5141163953Srrs break; 5142163953Srrs case SCTP_SHUTDOWN: 5143170091Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN, stcb %p\n", 5144240148Stuexen (void *)stcb); 5145169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_shutdown_chunk))) { 5146169208Srrs *offset = length; 5147169378Srrs if (locked_tcb) { 5148169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5149169378Srrs } 5150169208Srrs return (NULL); 5151169420Srrs } 5152169420Srrs if (netp && *netp) { 5153163953Srrs int abort_flag = 0; 5154163953Srrs 5155163953Srrs sctp_handle_shutdown((struct sctp_shutdown_chunk *)ch, 5156163953Srrs stcb, *netp, &abort_flag); 5157163953Srrs if (abort_flag) { 5158163953Srrs *offset = length; 5159163953Srrs return (NULL); 5160163953Srrs } 5161163953Srrs } 5162163953Srrs break; 5163163953Srrs case SCTP_SHUTDOWN_ACK: 5164240148Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", (void *)stcb); 5165169420Srrs if ((stcb) && (netp) && (*netp)) 5166169420Srrs sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp); 5167163953Srrs *offset = length; 5168163953Srrs return (NULL); 5169163953Srrs break; 5170169420Srrs 5171163953Srrs case SCTP_OPERATION_ERROR: 5172169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_OP-ERR\n"); 5173169420Srrs if ((stcb) && netp && *netp && sctp_handle_error(ch, stcb, *netp) < 0) { 5174163953Srrs *offset = length; 5175163953Srrs return (NULL); 5176163953Srrs } 5177163953Srrs break; 5178163953Srrs case SCTP_COOKIE_ECHO: 5179169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 5180240148Stuexen "SCTP_COOKIE-ECHO, stcb %p\n", (void *)stcb); 5181163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 5182163953Srrs ; 5183163953Srrs } else { 5184169420Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5185163953Srrs /* We are not interested anymore */ 5186208878Srrs abend: 5187208853Srrs if (stcb) { 5188208853Srrs SCTP_TCB_UNLOCK(stcb); 5189208853Srrs } 5190163953Srrs *offset = length; 5191163953Srrs return (NULL); 5192163953Srrs } 5193163953Srrs } 5194163953Srrs /* 5195163953Srrs * First are we accepting? We do this again here 5196207924Srrs * since it is possible that a previous endpoint WAS 5197207924Srrs * listening responded to a INIT-ACK and then 5198163953Srrs * closed. We opened and bound.. and are now no 5199163953Srrs * longer listening. 5200163953Srrs */ 5201172703Srrs 5202172703Srrs if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) { 5203172703Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 5204179783Srrs (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) { 5205267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 5206237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, 5207237715Stuexen src, dst, sh, op_err, 5208281955Shiren mflowtype, mflowid, 5209237049Stuexen vrf_id, port); 5210163953Srrs } 5211172703Srrs *offset = length; 5212172703Srrs return (NULL); 5213172703Srrs } else { 5214163953Srrs struct mbuf *ret_buf; 5215165220Srrs struct sctp_inpcb *linp; 5216163953Srrs 5217169420Srrs if (stcb) { 5218165220Srrs linp = NULL; 5219169420Srrs } else { 5220165220Srrs linp = inp; 5221169420Srrs } 5222165220Srrs 5223169420Srrs if (linp) { 5224165220Srrs SCTP_ASOC_CREATE_LOCK(linp); 5225208878Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 5226208878Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 5227208878Srrs SCTP_ASOC_CREATE_UNLOCK(linp); 5228208878Srrs goto abend; 5229208878Srrs } 5230169420Srrs } 5231169420Srrs if (netp) { 5232169420Srrs ret_buf = 5233169420Srrs sctp_handle_cookie_echo(m, iphlen, 5234237715Stuexen *offset, 5235237715Stuexen src, dst, 5236237715Stuexen sh, 5237169420Srrs (struct sctp_cookie_echo_chunk *)ch, 5238169420Srrs &inp, &stcb, netp, 5239169420Srrs auth_skipped, 5240169420Srrs auth_offset, 5241169420Srrs auth_len, 5242169420Srrs &locked_tcb, 5243281955Shiren mflowtype, 5244237049Stuexen mflowid, 5245179157Srrs vrf_id, 5246179157Srrs port); 5247169420Srrs } else { 5248169420Srrs ret_buf = NULL; 5249169420Srrs } 5250169420Srrs if (linp) { 5251165220Srrs SCTP_ASOC_CREATE_UNLOCK(linp); 5252169420Srrs } 5253163953Srrs if (ret_buf == NULL) { 5254163953Srrs if (locked_tcb) { 5255163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5256163953Srrs } 5257169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 5258169420Srrs "GAK, null buffer\n"); 5259163953Srrs *offset = length; 5260163953Srrs return (NULL); 5261163953Srrs } 5262163953Srrs /* if AUTH skipped, see if it verified... */ 5263163953Srrs if (auth_skipped) { 5264163953Srrs got_auth = 1; 5265163953Srrs auth_skipped = 0; 5266163953Srrs } 5267163953Srrs if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) { 5268163953Srrs /* 5269163953Srrs * Restart the timer if we have 5270163953Srrs * pending data 5271163953Srrs */ 5272163953Srrs struct sctp_tmit_chunk *chk; 5273163953Srrs 5274163953Srrs chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 5275216822Stuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 5276163953Srrs } 5277163953Srrs } 5278163953Srrs break; 5279163953Srrs case SCTP_COOKIE_ACK: 5280240148Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", (void *)stcb); 5281169420Srrs if ((stcb == NULL) || chk_length != sizeof(struct sctp_cookie_ack_chunk)) { 5282169378Srrs if (locked_tcb) { 5283169352Srrs SCTP_TCB_UNLOCK(locked_tcb); 5284169378Srrs } 5285169352Srrs return (NULL); 5286169352Srrs } 5287163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5288163953Srrs /* We are not interested anymore */ 5289163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 5290163953Srrs ; 5291169420Srrs } else if (stcb) { 5292237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5293172090Srrs so = SCTP_INP_SO(inp); 5294172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5295172090Srrs SCTP_TCB_UNLOCK(stcb); 5296172090Srrs SCTP_SOCKET_LOCK(so, 1); 5297172090Srrs SCTP_TCB_LOCK(stcb); 5298172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 5299172090Srrs#endif 5300283822Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 5301283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_30); 5302237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5303172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 5304172090Srrs#endif 5305163953Srrs *offset = length; 5306163953Srrs return (NULL); 5307163953Srrs } 5308163953Srrs } 5309163953Srrs /* He's alive so give him credit */ 5310169420Srrs if ((stcb) && netp && *netp) { 5311179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5312171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5313171943Srrs stcb->asoc.overall_error_count, 5314171943Srrs 0, 5315171943Srrs SCTP_FROM_SCTP_INPUT, 5316171943Srrs __LINE__); 5317171943Srrs } 5318169378Srrs stcb->asoc.overall_error_count = 0; 5319169378Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, *netp); 5320169378Srrs } 5321163953Srrs break; 5322163953Srrs case SCTP_ECN_ECHO: 5323169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-ECHO\n"); 5324163953Srrs /* He's alive so give him credit */ 5325169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_ecne_chunk))) { 5326169208Srrs /* Its not ours */ 5327169378Srrs if (locked_tcb) { 5328169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5329169378Srrs } 5330169208Srrs *offset = length; 5331169208Srrs return (NULL); 5332169208Srrs } 5333169378Srrs if (stcb) { 5334270362Stuexen if (stcb->asoc.ecn_supported == 0) { 5335270362Stuexen goto unknown_chunk; 5336270362Stuexen } 5337179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5338171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5339171943Srrs stcb->asoc.overall_error_count, 5340171943Srrs 0, 5341171943Srrs SCTP_FROM_SCTP_INPUT, 5342171943Srrs __LINE__); 5343171943Srrs } 5344169378Srrs stcb->asoc.overall_error_count = 0; 5345169378Srrs sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch, 5346169378Srrs stcb); 5347218186Srrs ecne_seen = 1; 5348169378Srrs } 5349163953Srrs break; 5350163953Srrs case SCTP_ECN_CWR: 5351169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-CWR\n"); 5352163953Srrs /* He's alive so give him credit */ 5353169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_cwr_chunk))) { 5354169208Srrs /* Its not ours */ 5355169378Srrs if (locked_tcb) { 5356169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5357169378Srrs } 5358169208Srrs *offset = length; 5359169208Srrs return (NULL); 5360169208Srrs } 5361169378Srrs if (stcb) { 5362270362Stuexen if (stcb->asoc.ecn_supported == 0) { 5363270362Stuexen goto unknown_chunk; 5364270362Stuexen } 5365179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5366171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5367171943Srrs stcb->asoc.overall_error_count, 5368171943Srrs 0, 5369171943Srrs SCTP_FROM_SCTP_INPUT, 5370171943Srrs __LINE__); 5371171943Srrs } 5372169378Srrs stcb->asoc.overall_error_count = 0; 5373218072Srrs sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb, *netp); 5374169378Srrs } 5375163953Srrs break; 5376163953Srrs case SCTP_SHUTDOWN_COMPLETE: 5377240148Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", (void *)stcb); 5378163953Srrs /* must be first and only chunk */ 5379163953Srrs if ((num_chunks > 1) || 5380170140Srrs (length - *offset > (int)SCTP_SIZE32(chk_length))) { 5381163953Srrs *offset = length; 5382169378Srrs if (locked_tcb) { 5383163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5384169378Srrs } 5385163953Srrs return (NULL); 5386163953Srrs } 5387169420Srrs if ((stcb) && netp && *netp) { 5388169378Srrs sctp_handle_shutdown_complete((struct sctp_shutdown_complete_chunk *)ch, 5389169378Srrs stcb, *netp); 5390169378Srrs } 5391163953Srrs *offset = length; 5392163953Srrs return (NULL); 5393163953Srrs break; 5394163953Srrs case SCTP_ASCONF: 5395169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n"); 5396163953Srrs /* He's alive so give him credit */ 5397169378Srrs if (stcb) { 5398270362Stuexen if (stcb->asoc.asconf_supported == 0) { 5399270362Stuexen goto unknown_chunk; 5400270362Stuexen } 5401179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5402171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5403171943Srrs stcb->asoc.overall_error_count, 5404171943Srrs 0, 5405171943Srrs SCTP_FROM_SCTP_INPUT, 5406171943Srrs __LINE__); 5407171943Srrs } 5408169378Srrs stcb->asoc.overall_error_count = 0; 5409237715Stuexen sctp_handle_asconf(m, *offset, src, 5410171990Srrs (struct sctp_asconf_chunk *)ch, stcb, asconf_cnt == 0); 5411171990Srrs asconf_cnt++; 5412169378Srrs } 5413163953Srrs break; 5414163953Srrs case SCTP_ASCONF_ACK: 5415169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF-ACK\n"); 5416169208Srrs if (chk_length < sizeof(struct sctp_asconf_ack_chunk)) { 5417169208Srrs /* Its not ours */ 5418169378Srrs if (locked_tcb) { 5419169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5420169378Srrs } 5421169208Srrs *offset = length; 5422169208Srrs return (NULL); 5423169208Srrs } 5424169420Srrs if ((stcb) && netp && *netp) { 5425270362Stuexen if (stcb->asoc.asconf_supported == 0) { 5426270362Stuexen goto unknown_chunk; 5427270362Stuexen } 5428169378Srrs /* He's alive so give him credit */ 5429179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5430171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5431171943Srrs stcb->asoc.overall_error_count, 5432171943Srrs 0, 5433171943Srrs SCTP_FROM_SCTP_INPUT, 5434171943Srrs __LINE__); 5435171943Srrs } 5436169378Srrs stcb->asoc.overall_error_count = 0; 5437169378Srrs sctp_handle_asconf_ack(m, *offset, 5438172190Srrs (struct sctp_asconf_ack_chunk *)ch, stcb, *netp, &abort_no_unlock); 5439172190Srrs if (abort_no_unlock) 5440172190Srrs return (NULL); 5441169378Srrs } 5442163953Srrs break; 5443163953Srrs case SCTP_FORWARD_CUM_TSN: 5444169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_FWD-TSN\n"); 5445169208Srrs if (chk_length < sizeof(struct sctp_forward_tsn_chunk)) { 5446169208Srrs /* Its not ours */ 5447169378Srrs if (locked_tcb) { 5448169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5449169378Srrs } 5450169208Srrs *offset = length; 5451169208Srrs return (NULL); 5452169208Srrs } 5453163953Srrs /* He's alive so give him credit */ 5454169378Srrs if (stcb) { 5455163953Srrs int abort_flag = 0; 5456163953Srrs 5457270362Stuexen if (stcb->asoc.prsctp_supported == 0) { 5458270362Stuexen goto unknown_chunk; 5459270362Stuexen } 5460163953Srrs stcb->asoc.overall_error_count = 0; 5461179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5462171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5463171943Srrs stcb->asoc.overall_error_count, 5464171943Srrs 0, 5465171943Srrs SCTP_FROM_SCTP_INPUT, 5466171943Srrs __LINE__); 5467171943Srrs } 5468163953Srrs *fwd_tsn_seen = 1; 5469163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5470163953Srrs /* We are not interested anymore */ 5471237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5472172090Srrs so = SCTP_INP_SO(inp); 5473172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5474172090Srrs SCTP_TCB_UNLOCK(stcb); 5475172090Srrs SCTP_SOCKET_LOCK(so, 1); 5476172090Srrs SCTP_TCB_LOCK(stcb); 5477172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 5478172090Srrs#endif 5479283822Stuexen (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 5480283822Stuexen SCTP_FROM_SCTP_INPUT + SCTP_LOC_31); 5481237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5482172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 5483172090Srrs#endif 5484163953Srrs *offset = length; 5485163953Srrs return (NULL); 5486163953Srrs } 5487163953Srrs sctp_handle_forward_tsn(stcb, 5488170992Srrs (struct sctp_forward_tsn_chunk *)ch, &abort_flag, m, *offset); 5489163953Srrs if (abort_flag) { 5490163953Srrs *offset = length; 5491163953Srrs return (NULL); 5492163953Srrs } else { 5493179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5494171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5495171943Srrs stcb->asoc.overall_error_count, 5496171943Srrs 0, 5497171943Srrs SCTP_FROM_SCTP_INPUT, 5498171943Srrs __LINE__); 5499171943Srrs } 5500163953Srrs stcb->asoc.overall_error_count = 0; 5501163953Srrs } 5502163953Srrs 5503163953Srrs } 5504163953Srrs break; 5505163953Srrs case SCTP_STREAM_RESET: 5506169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_STREAM_RESET\n"); 5507169420Srrs if (((stcb == NULL) || (ch == NULL) || (chk_length < sizeof(struct sctp_stream_reset_tsn_req)))) { 5508169208Srrs /* Its not ours */ 5509169378Srrs if (locked_tcb) { 5510169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5511169378Srrs } 5512169208Srrs *offset = length; 5513169208Srrs return (NULL); 5514169208Srrs } 5515270361Stuexen if (stcb->asoc.reconfig_supported == 0) { 5516270362Stuexen goto unknown_chunk; 5517163953Srrs } 5518240198Stuexen if (sctp_handle_stream_reset(stcb, m, *offset, ch)) { 5519169420Srrs /* stop processing */ 5520169420Srrs *offset = length; 5521169420Srrs return (NULL); 5522169420Srrs } 5523163953Srrs break; 5524163953Srrs case SCTP_PACKET_DROPPED: 5525169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_PACKET_DROPPED\n"); 5526163953Srrs /* re-get it all please */ 5527169208Srrs if (chk_length < sizeof(struct sctp_pktdrop_chunk)) { 5528169208Srrs /* Its not ours */ 5529169378Srrs if (locked_tcb) { 5530169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5531169378Srrs } 5532169208Srrs *offset = length; 5533169208Srrs return (NULL); 5534169208Srrs } 5535169420Srrs if (ch && (stcb) && netp && (*netp)) { 5536270362Stuexen if (stcb->asoc.pktdrop_supported == 0) { 5537270362Stuexen goto unknown_chunk; 5538270362Stuexen } 5539169378Srrs sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch, 5540170781Srrs stcb, *netp, 5541170781Srrs min(chk_length, (sizeof(chunk_buf) - 4))); 5542170781Srrs 5543169378Srrs } 5544163953Srrs break; 5545163953Srrs case SCTP_AUTHENTICATION: 5546169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n"); 5547163953Srrs if (stcb == NULL) { 5548163953Srrs /* save the first AUTH for later processing */ 5549163953Srrs if (auth_skipped == 0) { 5550163953Srrs auth_offset = *offset; 5551163953Srrs auth_len = chk_length; 5552163953Srrs auth_skipped = 1; 5553163953Srrs } 5554163953Srrs /* skip this chunk (temporarily) */ 5555163953Srrs goto next_chunk; 5556163953Srrs } 5557270362Stuexen if (stcb->asoc.auth_supported == 0) { 5558270362Stuexen goto unknown_chunk; 5559270362Stuexen } 5560169208Srrs if ((chk_length < (sizeof(struct sctp_auth_chunk))) || 5561169420Srrs (chk_length > (sizeof(struct sctp_auth_chunk) + 5562169420Srrs SCTP_AUTH_DIGEST_LEN_MAX))) { 5563169208Srrs /* Its not ours */ 5564169378Srrs if (locked_tcb) { 5565169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5566169378Srrs } 5567169208Srrs *offset = length; 5568169208Srrs return (NULL); 5569169208Srrs } 5570163953Srrs if (got_auth == 1) { 5571163953Srrs /* skip this chunk... it's already auth'd */ 5572163953Srrs goto next_chunk; 5573163953Srrs } 5574163953Srrs got_auth = 1; 5575169420Srrs if ((ch == NULL) || sctp_handle_auth(stcb, (struct sctp_auth_chunk *)ch, 5576163953Srrs m, *offset)) { 5577163953Srrs /* auth HMAC failed so dump the packet */ 5578163953Srrs *offset = length; 5579163953Srrs return (stcb); 5580163953Srrs } else { 5581163953Srrs /* remaining chunks are HMAC checked */ 5582163953Srrs stcb->asoc.authenticated = 1; 5583163953Srrs } 5584163953Srrs break; 5585163953Srrs 5586163953Srrs default: 5587163953Srrs unknown_chunk: 5588163953Srrs /* it's an unknown chunk! */ 5589163953Srrs if ((ch->chunk_type & 0x40) && (stcb != NULL)) { 5590294158Stuexen struct sctp_gen_error_cause *cause; 5591283700Stuexen int len; 5592163953Srrs 5593294158Stuexen op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause), 5594243882Sglebius 0, M_NOWAIT, 1, MT_DATA); 5595294158Stuexen if (op_err != NULL) { 5596283700Stuexen len = min(SCTP_SIZE32(chk_length), (uint32_t) (length - *offset)); 5597294158Stuexen cause = mtod(op_err, struct sctp_gen_error_cause *); 5598294158Stuexen cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK); 5599294158Stuexen cause->length = htons(len + sizeof(struct sctp_gen_error_cause)); 5600294158Stuexen SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause); 5601294158Stuexen SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT); 5602294158Stuexen if (SCTP_BUF_NEXT(op_err) != NULL) { 5603178202Srrs#ifdef SCTP_MBUF_LOGGING 5604294157Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 5605294172Stuexen sctp_log_mbc(SCTP_BUF_NEXT(op_err), SCTP_MBUF_ICOPY); 5606294157Stuexen } 5607234459Stuexen#endif 5608294158Stuexen sctp_queue_op_err(stcb, op_err); 5609163953Srrs } else { 5610294158Stuexen sctp_m_freem(op_err); 5611163953Srrs } 5612163953Srrs } 5613163953Srrs } 5614163953Srrs if ((ch->chunk_type & 0x80) == 0) { 5615163953Srrs /* discard this packet */ 5616163953Srrs *offset = length; 5617163953Srrs return (stcb); 5618163953Srrs } /* else skip this bad chunk and continue... */ 5619163953Srrs break; 5620163953Srrs } /* switch (ch->chunk_type) */ 5621163953Srrs 5622163953Srrs 5623163953Srrsnext_chunk: 5624163953Srrs /* get the next chunk */ 5625163953Srrs *offset += SCTP_SIZE32(chk_length); 5626163953Srrs if (*offset >= length) { 5627163953Srrs /* no more data left in the mbuf chain */ 5628163953Srrs break; 5629163953Srrs } 5630163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 5631163953Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 5632163953Srrs if (ch == NULL) { 5633169378Srrs if (locked_tcb) { 5634163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5635169378Srrs } 5636163953Srrs *offset = length; 5637163953Srrs return (NULL); 5638163953Srrs } 5639163953Srrs } /* while */ 5640171990Srrs 5641171990Srrs if (asconf_cnt > 0 && stcb != NULL) { 5642171990Srrs sctp_send_asconf_ack(stcb); 5643171990Srrs } 5644163953Srrs return (stcb); 5645163953Srrs} 5646163953Srrs 5647163953Srrs 5648163953Srrs/* 5649163953Srrs * common input chunk processing (v4 and v6) 5650163953Srrs */ 5651169378Srrsvoid 5652237715Stuexensctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int length, 5653237715Stuexen struct sockaddr *src, struct sockaddr *dst, 5654237715Stuexen struct sctphdr *sh, struct sctp_chunkhdr *ch, 5655238003Stuexen#if !defined(SCTP_WITH_NO_CSUM) 5656238003Stuexen uint8_t compute_crc, 5657238003Stuexen#endif 5658238003Stuexen uint8_t ecn_bits, 5659284633Stuexen uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum, 5660237049Stuexen uint32_t vrf_id, uint16_t port) 5661163953Srrs{ 5662163953Srrs uint32_t high_tsn; 5663163953Srrs int fwd_tsn_seen = 0, data_processed = 0; 5664267723Stuexen struct mbuf *m = *mm, *op_err; 5665267723Stuexen char msg[SCTP_DIAG_INFO_LEN]; 5666163953Srrs int un_sent; 5667218129Srrs int cnt_ctrl_ready = 0; 5668239091Stuexen struct sctp_inpcb *inp = NULL, *inp_decr = NULL; 5669238003Stuexen struct sctp_tcb *stcb = NULL; 5670238087Stuexen struct sctp_nets *net = NULL; 5671163953Srrs 5672163953Srrs SCTP_STAT_INCR(sctps_recvdatagrams); 5673163953Srrs#ifdef SCTP_AUDITING_ENABLED 5674163953Srrs sctp_audit_log(0xE0, 1); 5675163953Srrs sctp_auditing(0, inp, stcb, net); 5676163953Srrs#endif 5677238003Stuexen#if !defined(SCTP_WITH_NO_CSUM) 5678238003Stuexen if (compute_crc != 0) { 5679238003Stuexen uint32_t check, calc_check; 5680163953Srrs 5681238003Stuexen check = sh->checksum; 5682238003Stuexen sh->checksum = 0; 5683238003Stuexen calc_check = sctp_calculate_cksum(m, iphlen); 5684238003Stuexen sh->checksum = check; 5685238003Stuexen if (calc_check != check) { 5686238003Stuexen SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n", 5687240148Stuexen calc_check, check, (void *)m, length, iphlen); 5688238003Stuexen stcb = sctp_findassociation_addr(m, offset, src, dst, 5689238003Stuexen sh, ch, &inp, &net, vrf_id); 5690270350Stuexen#if defined(INET) || defined(INET6) 5691295208Stuexen if ((ch->chunk_type != SCTP_INITIATION) && 5692295208Stuexen (net != NULL) && (net->port != port)) { 5693238003Stuexen if (net->port == 0) { 5694295208Stuexen /* UDP encapsulation turned on. */ 5695295208Stuexen net->mtu -= sizeof(struct udphdr); 5696295208Stuexen if (stcb->asoc.smallest_mtu > net->mtu) { 5697295208Stuexen sctp_pathmtu_adjustment(stcb, net->mtu); 5698295208Stuexen } 5699295208Stuexen } else if (port == 0) { 5700295208Stuexen /* UDP encapsulation turned off. */ 5701295208Stuexen net->mtu += sizeof(struct udphdr); 5702295208Stuexen /* XXX Update smallest_mtu */ 5703238003Stuexen } 5704238003Stuexen net->port = port; 5705238003Stuexen } 5706270350Stuexen#endif 5707284634Stuexen if (net != NULL) { 5708281955Shiren net->flowtype = mflowtype; 5709284634Stuexen net->flowid = mflowid; 5710238003Stuexen } 5711238003Stuexen if ((inp != NULL) && (stcb != NULL)) { 5712238003Stuexen sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1); 5713238003Stuexen sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED); 5714238003Stuexen } else if ((inp != NULL) && (stcb == NULL)) { 5715238003Stuexen inp_decr = inp; 5716238003Stuexen } 5717238003Stuexen SCTP_STAT_INCR(sctps_badsum); 5718238003Stuexen SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors); 5719238003Stuexen goto out; 5720238003Stuexen } 5721238003Stuexen } 5722238003Stuexen#endif 5723238003Stuexen /* Destination port of 0 is illegal, based on RFC4960. */ 5724238003Stuexen if (sh->dest_port == 0) { 5725238003Stuexen SCTP_STAT_INCR(sctps_hdrops); 5726238003Stuexen goto out; 5727238003Stuexen } 5728238003Stuexen stcb = sctp_findassociation_addr(m, offset, src, dst, 5729238003Stuexen sh, ch, &inp, &net, vrf_id); 5730270350Stuexen#if defined(INET) || defined(INET6) 5731295208Stuexen if ((ch->chunk_type != SCTP_INITIATION) && 5732295208Stuexen (net != NULL) && (net->port != port)) { 5733238003Stuexen if (net->port == 0) { 5734295208Stuexen /* UDP encapsulation turned on. */ 5735295208Stuexen net->mtu -= sizeof(struct udphdr); 5736295208Stuexen if (stcb->asoc.smallest_mtu > net->mtu) { 5737295208Stuexen sctp_pathmtu_adjustment(stcb, net->mtu); 5738295208Stuexen } 5739295208Stuexen } else if (port == 0) { 5740295208Stuexen /* UDP encapsulation turned off. */ 5741295208Stuexen net->mtu += sizeof(struct udphdr); 5742295208Stuexen /* XXX Update smallest_mtu */ 5743238003Stuexen } 5744238003Stuexen net->port = port; 5745238003Stuexen } 5746270350Stuexen#endif 5747284634Stuexen if (net != NULL) { 5748281955Shiren net->flowtype = mflowtype; 5749284634Stuexen net->flowid = mflowid; 5750238003Stuexen } 5751238003Stuexen if (inp == NULL) { 5752238003Stuexen SCTP_STAT_INCR(sctps_noport); 5753238003Stuexen if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) { 5754238003Stuexen goto out; 5755238003Stuexen } 5756238003Stuexen if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 5757238003Stuexen sctp_send_shutdown_complete2(src, dst, sh, 5758284633Stuexen mflowtype, mflowid, fibnum, 5759238003Stuexen vrf_id, port); 5760238003Stuexen goto out; 5761238003Stuexen } 5762238003Stuexen if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) { 5763238003Stuexen goto out; 5764238003Stuexen } 5765238003Stuexen if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) { 5766238003Stuexen if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || 5767238003Stuexen ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && 5768238003Stuexen (ch->chunk_type != SCTP_INIT))) { 5769267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5770267723Stuexen "Out of the blue"); 5771238003Stuexen sctp_send_abort(m, iphlen, src, dst, 5772267723Stuexen sh, 0, op_err, 5773284633Stuexen mflowtype, mflowid, fibnum, 5774238003Stuexen vrf_id, port); 5775238003Stuexen } 5776238003Stuexen } 5777238003Stuexen goto out; 5778238003Stuexen } else if (stcb == NULL) { 5779238003Stuexen inp_decr = inp; 5780238003Stuexen } 5781238003Stuexen#ifdef IPSEC 5782238003Stuexen /*- 5783238003Stuexen * I very much doubt any of the IPSEC stuff will work but I have no 5784238003Stuexen * idea, so I will leave it in place. 5785238003Stuexen */ 5786238003Stuexen if (inp != NULL) { 5787238003Stuexen switch (dst->sa_family) { 5788238003Stuexen#ifdef INET 5789238003Stuexen case AF_INET: 5790238003Stuexen if (ipsec4_in_reject(m, &inp->ip_inp.inp)) { 5791253571Sae IPSECSTAT_INC(ips_in_polvio); 5792238003Stuexen SCTP_STAT_INCR(sctps_hdrops); 5793238003Stuexen goto out; 5794238003Stuexen } 5795238003Stuexen break; 5796238003Stuexen#endif 5797238003Stuexen#ifdef INET6 5798238003Stuexen case AF_INET6: 5799238003Stuexen if (ipsec6_in_reject(m, &inp->ip_inp.inp)) { 5800253571Sae IPSEC6STAT_INC(ips_in_polvio); 5801238003Stuexen SCTP_STAT_INCR(sctps_hdrops); 5802238003Stuexen goto out; 5803238003Stuexen } 5804238003Stuexen break; 5805238003Stuexen#endif 5806238003Stuexen default: 5807238003Stuexen break; 5808238003Stuexen } 5809238003Stuexen } 5810238003Stuexen#endif 5811179783Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n", 5812240148Stuexen (void *)m, iphlen, offset, length, (void *)stcb); 5813163953Srrs if (stcb) { 5814163953Srrs /* always clear this before beginning a packet */ 5815163953Srrs stcb->asoc.authenticated = 0; 5816163953Srrs stcb->asoc.seen_a_sack_this_pkt = 0; 5817171990Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "stcb:%p state:%x\n", 5818240148Stuexen (void *)stcb, stcb->asoc.state); 5819171990Srrs 5820171943Srrs if ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) || 5821171943Srrs (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) { 5822171745Srrs /*- 5823171745Srrs * If we hit here, we had a ref count 5824171745Srrs * up when the assoc was aborted and the 5825171745Srrs * timer is clearing out the assoc, we should 5826171745Srrs * NOT respond to any packet.. its OOTB. 5827171745Srrs */ 5828171745Srrs SCTP_TCB_UNLOCK(stcb); 5829238003Stuexen stcb = NULL; 5830294174Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); 5831267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5832267723Stuexen msg); 5833267723Stuexen sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 5834284633Stuexen mflowtype, mflowid, inp->fibnum, 5835179157Srrs vrf_id, port); 5836238003Stuexen goto out; 5837171745Srrs } 5838163953Srrs } 5839163953Srrs if (IS_SCTP_CONTROL(ch)) { 5840163953Srrs /* process the control portion of the SCTP packet */ 5841169655Srrs /* sa_ignore NO_NULL_CHK */ 5842237715Stuexen stcb = sctp_process_control(m, iphlen, &offset, length, 5843237715Stuexen src, dst, sh, ch, 5844237049Stuexen inp, stcb, &net, &fwd_tsn_seen, 5845284633Stuexen mflowtype, mflowid, fibnum, 5846237049Stuexen vrf_id, port); 5847163953Srrs if (stcb) { 5848163953Srrs /* 5849163953Srrs * This covers us if the cookie-echo was there and 5850163953Srrs * it changes our INP. 5851163953Srrs */ 5852163953Srrs inp = stcb->sctp_ep; 5853270350Stuexen#if defined(INET) || defined(INET6) 5854295208Stuexen if ((ch->chunk_type != SCTP_INITIATION) && 5855295208Stuexen (net != NULL) && (net->port != port)) { 5856179783Srrs if (net->port == 0) { 5857295208Stuexen /* UDP encapsulation turned on. */ 5858295208Stuexen net->mtu -= sizeof(struct udphdr); 5859295208Stuexen if (stcb->asoc.smallest_mtu > net->mtu) { 5860295208Stuexen sctp_pathmtu_adjustment(stcb, net->mtu); 5861295208Stuexen } 5862295208Stuexen } else if (port == 0) { 5863295208Stuexen /* UDP encapsulation turned off. */ 5864295208Stuexen net->mtu += sizeof(struct udphdr); 5865295208Stuexen /* XXX Update smallest_mtu */ 5866179783Srrs } 5867179783Srrs net->port = port; 5868179783Srrs } 5869270350Stuexen#endif 5870163953Srrs } 5871163953Srrs } else { 5872163953Srrs /* 5873163953Srrs * no control chunks, so pre-process DATA chunks (these 5874163953Srrs * checks are taken care of by control processing) 5875163953Srrs */ 5876163953Srrs 5877163953Srrs /* 5878163953Srrs * if DATA only packet, and auth is required, then punt... 5879163953Srrs * can't have authenticated without any AUTH (control) 5880163953Srrs * chunks 5881163953Srrs */ 5882179783Srrs if ((stcb != NULL) && 5883270362Stuexen (stcb->asoc.auth_supported == 1) && 5884179783Srrs sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) { 5885163953Srrs /* "silently" ignore */ 5886163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 5887238003Stuexen goto out; 5888163953Srrs } 5889163953Srrs if (stcb == NULL) { 5890163953Srrs /* out of the blue DATA chunk */ 5891294174Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); 5892267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5893267723Stuexen msg); 5894267723Stuexen sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 5895284633Stuexen mflowtype, mflowid, fibnum, 5896179157Srrs vrf_id, port); 5897238003Stuexen goto out; 5898163953Srrs } 5899163953Srrs if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) { 5900163953Srrs /* v_tag mismatch! */ 5901163953Srrs SCTP_STAT_INCR(sctps_badvtag); 5902238003Stuexen goto out; 5903163953Srrs } 5904163953Srrs } 5905163953Srrs 5906163953Srrs if (stcb == NULL) { 5907163953Srrs /* 5908163953Srrs * no valid TCB for this packet, or we found it's a bad 5909163953Srrs * packet while processing control, or we're done with this 5910163953Srrs * packet (done or skip rest of data), so we drop it... 5911163953Srrs */ 5912238003Stuexen goto out; 5913163953Srrs } 5914163953Srrs /* 5915163953Srrs * DATA chunk processing 5916163953Srrs */ 5917163953Srrs /* plow through the data chunks while length > offset */ 5918163953Srrs 5919163953Srrs /* 5920163953Srrs * Rest should be DATA only. Check authentication state if AUTH for 5921163953Srrs * DATA is required. 5922163953Srrs */ 5923179783Srrs if ((length > offset) && 5924179783Srrs (stcb != NULL) && 5925270362Stuexen (stcb->asoc.auth_supported == 1) && 5926179783Srrs sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) && 5927163953Srrs !stcb->asoc.authenticated) { 5928163953Srrs /* "silently" ignore */ 5929163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 5930169420Srrs SCTPDBG(SCTP_DEBUG_AUTH1, 5931169420Srrs "Data chunk requires AUTH, skipped\n"); 5932165220Srrs goto trigger_send; 5933163953Srrs } 5934163953Srrs if (length > offset) { 5935163953Srrs int retval; 5936163953Srrs 5937163953Srrs /* 5938163953Srrs * First check to make sure our state is correct. We would 5939163953Srrs * not get here unless we really did have a tag, so we don't 5940163953Srrs * abort if this happens, just dump the chunk silently. 5941163953Srrs */ 5942163953Srrs switch (SCTP_GET_STATE(&stcb->asoc)) { 5943163953Srrs case SCTP_STATE_COOKIE_ECHOED: 5944163953Srrs /* 5945163953Srrs * we consider data with valid tags in this state 5946163953Srrs * shows us the cookie-ack was lost. Imply it was 5947163953Srrs * there. 5948163953Srrs */ 5949179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5950171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5951171943Srrs stcb->asoc.overall_error_count, 5952171943Srrs 0, 5953171943Srrs SCTP_FROM_SCTP_INPUT, 5954171943Srrs __LINE__); 5955171943Srrs } 5956163953Srrs stcb->asoc.overall_error_count = 0; 5957163953Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, net); 5958163953Srrs break; 5959163953Srrs case SCTP_STATE_COOKIE_WAIT: 5960163953Srrs /* 5961163953Srrs * We consider OOTB any data sent during asoc setup. 5962163953Srrs */ 5963294174Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__); 5964267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5965267723Stuexen msg); 5966267723Stuexen sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 5967284633Stuexen mflowtype, mflowid, inp->fibnum, 5968179157Srrs vrf_id, port); 5969238003Stuexen goto out; 5970171531Srrs /* sa_ignore NOTREACHED */ 5971163953Srrs break; 5972163953Srrs case SCTP_STATE_EMPTY: /* should not happen */ 5973163953Srrs case SCTP_STATE_INUSE: /* should not happen */ 5974163953Srrs case SCTP_STATE_SHUTDOWN_RECEIVED: /* This is a peer error */ 5975163953Srrs case SCTP_STATE_SHUTDOWN_ACK_SENT: 5976163953Srrs default: 5977238003Stuexen goto out; 5978171531Srrs /* sa_ignore NOTREACHED */ 5979163953Srrs break; 5980163953Srrs case SCTP_STATE_OPEN: 5981163953Srrs case SCTP_STATE_SHUTDOWN_SENT: 5982163953Srrs break; 5983163953Srrs } 5984163953Srrs /* plow through the data chunks while length > offset */ 5985237715Stuexen retval = sctp_process_data(mm, iphlen, &offset, length, 5986294147Stuexen inp, stcb, net, &high_tsn); 5987163953Srrs if (retval == 2) { 5988163953Srrs /* 5989163953Srrs * The association aborted, NO UNLOCK needed since 5990163953Srrs * the association is destroyed. 5991163953Srrs */ 5992238003Stuexen stcb = NULL; 5993238003Stuexen goto out; 5994163953Srrs } 5995163953Srrs data_processed = 1; 5996163953Srrs /* 5997163953Srrs * Anything important needs to have been m_copy'ed in 5998163953Srrs * process_data 5999163953Srrs */ 6000163953Srrs } 6001218129Srrs /* take care of ecn */ 6002228907Stuexen if ((data_processed == 1) && 6003270356Stuexen (stcb->asoc.ecn_supported == 1) && 6004218235Stuexen ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) { 6005218129Srrs /* Yep, we need to add a ECNE */ 6006218129Srrs sctp_send_ecn_echo(stcb, net, high_tsn); 6007218129Srrs } 6008163953Srrs if ((data_processed == 0) && (fwd_tsn_seen)) { 6009216495Stuexen int was_a_gap; 6010216495Stuexen uint32_t highest_tsn; 6011163953Srrs 6012216825Stuexen if (SCTP_TSN_GT(stcb->asoc.highest_tsn_inside_nr_map, stcb->asoc.highest_tsn_inside_map)) { 6013216495Stuexen highest_tsn = stcb->asoc.highest_tsn_inside_nr_map; 6014216495Stuexen } else { 6015216495Stuexen highest_tsn = stcb->asoc.highest_tsn_inside_map; 6016163953Srrs } 6017216825Stuexen was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn); 6018190689Srrs stcb->asoc.send_sack = 1; 6019228653Stuexen sctp_sack_check(stcb, was_a_gap); 6020190689Srrs } else if (fwd_tsn_seen) { 6021190689Srrs stcb->asoc.send_sack = 1; 6022163953Srrs } 6023163953Srrs /* trigger send of any chunks in queue... */ 6024165220Srrstrigger_send: 6025163953Srrs#ifdef SCTP_AUDITING_ENABLED 6026163953Srrs sctp_audit_log(0xE0, 2); 6027163953Srrs sctp_auditing(1, inp, stcb, net); 6028163953Srrs#endif 6029169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 6030169420Srrs "Check for chunk output prw:%d tqe:%d tf=%d\n", 6031169420Srrs stcb->asoc.peers_rwnd, 6032169420Srrs TAILQ_EMPTY(&stcb->asoc.control_send_queue), 6033169420Srrs stcb->asoc.total_flight); 6034163953Srrs un_sent = (stcb->asoc.total_output_queue_size - stcb->asoc.total_flight); 6035218129Srrs if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 6036218129Srrs cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq; 6037218129Srrs } 6038294210Stuexen if (cnt_ctrl_ready || stcb->asoc.trigger_reset || 6039163953Srrs ((un_sent) && 6040163953Srrs (stcb->asoc.peers_rwnd > 0 || 6041163953Srrs (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) { 6042169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "Calling chunk OUTPUT\n"); 6043172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 6044169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "chunk OUTPUT returns\n"); 6045163953Srrs } 6046163953Srrs#ifdef SCTP_AUDITING_ENABLED 6047163953Srrs sctp_audit_log(0xE0, 3); 6048163953Srrs sctp_auditing(2, inp, stcb, net); 6049163953Srrs#endif 6050238003Stuexenout: 6051238003Stuexen if (stcb != NULL) { 6052238003Stuexen SCTP_TCB_UNLOCK(stcb); 6053238003Stuexen } 6054238003Stuexen if (inp_decr != NULL) { 6055238003Stuexen /* reduce ref-count */ 6056238003Stuexen SCTP_INP_WLOCK(inp_decr); 6057238003Stuexen SCTP_INP_DECR_REF(inp_decr); 6058238003Stuexen SCTP_INP_WUNLOCK(inp_decr); 6059238003Stuexen } 6060169378Srrs return; 6061163953Srrs} 6062163953Srrs 6063185694Srrs#if 0 6064185694Srrsstatic void 6065185694Srrssctp_print_mbuf_chain(struct mbuf *m) 6066185694Srrs{ 6067185694Srrs for (; m; m = SCTP_BUF_NEXT(m)) { 6068240148Stuexen SCTP_PRINTF("%p: m_len = %ld\n", (void *)m, SCTP_BUF_LEN(m)); 6069185694Srrs if (SCTP_BUF_IS_EXTENDED(m)) 6070240148Stuexen SCTP_PRINTF("%p: extend_size = %d\n", (void *)m, SCTP_BUF_EXTEND_SIZE(m)); 6071185694Srrs } 6072185694Srrs} 6073163953Srrs 6074185694Srrs#endif 6075185694Srrs 6076221249Stuexen#ifdef INET 6077163953Srrsvoid 6078189004Srdivackysctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) 6079163953Srrs{ 6080165647Srrs struct mbuf *m; 6081163953Srrs int iphlen; 6082170181Srrs uint32_t vrf_id = 0; 6083163953Srrs uint8_t ecn_bits; 6084237715Stuexen struct sockaddr_in src, dst; 6085163953Srrs struct ip *ip; 6086163953Srrs struct sctphdr *sh; 6087237569Stuexen struct sctp_chunkhdr *ch; 6088237569Stuexen int length, offset; 6089163953Srrs 6090211969Stuexen#if !defined(SCTP_WITH_NO_CSUM) 6091238003Stuexen uint8_t compute_crc; 6092211969Stuexen 6093211969Stuexen#endif 6094238003Stuexen uint32_t mflowid; 6095281955Shiren uint8_t mflowtype; 6096284633Stuexen uint16_t fibnum; 6097211969Stuexen 6098237569Stuexen iphlen = off; 6099169352Srrs if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) { 6100169352Srrs SCTP_RELEASE_PKT(i_pak); 6101169352Srrs return; 6102169352Srrs } 6103165647Srrs m = SCTP_HEADER_TO_CHAIN(i_pak); 6104163953Srrs#ifdef SCTP_MBUF_LOGGING 6105163953Srrs /* Log in any input mbufs */ 6106179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 6107283708Stuexen sctp_log_mbc(m, SCTP_MBUF_INPUT); 6108163953Srrs } 6109163953Srrs#endif 6110237540Stuexen#ifdef SCTP_PACKET_LOGGING 6111237569Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { 6112237540Stuexen sctp_packet_log(m); 6113237569Stuexen } 6114170091Srrs#endif 6115238003Stuexen SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 6116254854Stuexen "sctp_input(): Packet of length %d received on %s with csum_flags 0x%b.\n", 6117238003Stuexen m->m_pkthdr.len, 6118238003Stuexen if_name(m->m_pkthdr.rcvif), 6119254854Stuexen (int)m->m_pkthdr.csum_flags, CSUM_BITS); 6120281955Shiren mflowid = m->m_pkthdr.flowid; 6121281955Shiren mflowtype = M_HASHTYPE_GET(m); 6122284633Stuexen fibnum = M_GETFIB(m); 6123237569Stuexen SCTP_STAT_INCR(sctps_recvpackets); 6124237569Stuexen SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 6125237569Stuexen /* Get IP, SCTP, and first chunk header together in the first mbuf. */ 6126237569Stuexen offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); 6127165647Srrs if (SCTP_BUF_LEN(m) < offset) { 6128237715Stuexen if ((m = m_pullup(m, offset)) == NULL) { 6129163953Srrs SCTP_STAT_INCR(sctps_hdrops); 6130163953Srrs return; 6131163953Srrs } 6132163953Srrs } 6133237715Stuexen ip = mtod(m, struct ip *); 6134237569Stuexen sh = (struct sctphdr *)((caddr_t)ip + iphlen); 6135237569Stuexen ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 6136237569Stuexen offset -= sizeof(struct sctp_chunkhdr); 6137237715Stuexen memset(&src, 0, sizeof(struct sockaddr_in)); 6138237715Stuexen src.sin_family = AF_INET; 6139237715Stuexen src.sin_len = sizeof(struct sockaddr_in); 6140237715Stuexen src.sin_port = sh->src_port; 6141237715Stuexen src.sin_addr = ip->ip_src; 6142237715Stuexen memset(&dst, 0, sizeof(struct sockaddr_in)); 6143237715Stuexen dst.sin_family = AF_INET; 6144237715Stuexen dst.sin_len = sizeof(struct sockaddr_in); 6145237715Stuexen dst.sin_port = sh->dest_port; 6146237715Stuexen dst.sin_addr = ip->ip_dst; 6147241923Sglebius length = ntohs(ip->ip_len); 6148237569Stuexen /* Validate mbuf chain length with IP payload length. */ 6149238003Stuexen if (SCTP_HEADER_LEN(m) != length) { 6150237569Stuexen SCTPDBG(SCTP_DEBUG_INPUT1, 6151238003Stuexen "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m)); 6152188067Srrs SCTP_STAT_INCR(sctps_hdrops); 6153238003Stuexen goto out; 6154188067Srrs } 6155163953Srrs /* SCTP does not allow broadcasts or multicasts */ 6156237715Stuexen if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { 6157238003Stuexen goto out; 6158163953Srrs } 6159237715Stuexen if (SCTP_IS_IT_BROADCAST(dst.sin_addr, m)) { 6160238003Stuexen goto out; 6161163953Srrs } 6162238003Stuexen ecn_bits = ip->ip_tos; 6163211969Stuexen#if defined(SCTP_WITH_NO_CSUM) 6164211969Stuexen SCTP_STAT_INCR(sctps_recvnocrc); 6165211969Stuexen#else 6166188067Srrs if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { 6167188067Srrs SCTP_STAT_INCR(sctps_recvhwcrc); 6168238003Stuexen compute_crc = 0; 6169238003Stuexen } else { 6170238003Stuexen SCTP_STAT_INCR(sctps_recvswcrc); 6171238003Stuexen compute_crc = 1; 6172188067Srrs } 6173218400Stuexen#endif 6174238003Stuexen sctp_common_input_processing(&m, iphlen, offset, length, 6175237715Stuexen (struct sockaddr *)&src, 6176237715Stuexen (struct sockaddr *)&dst, 6177238003Stuexen sh, ch, 6178238003Stuexen#if !defined(SCTP_WITH_NO_CSUM) 6179238003Stuexen compute_crc, 6180218400Stuexen#endif 6181238003Stuexen ecn_bits, 6182284633Stuexen mflowtype, mflowid, fibnum, 6183237049Stuexen vrf_id, port); 6184238003Stuexenout: 6185163953Srrs if (m) { 6186163953Srrs sctp_m_freem(m); 6187163953Srrs } 6188163953Srrs return; 6189163953Srrs} 6190218211Srrs 6191218269Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 6192218269Srrsextern int *sctp_cpuarry; 6193218211Srrs 6194218269Srrs#endif 6195218269Srrs 6196179157Srrsvoid 6197218211Srrssctp_input(struct mbuf *m, int off) 6198179157Srrs{ 6199218211Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 6200218211Srrs struct ip *ip; 6201218211Srrs struct sctphdr *sh; 6202218211Srrs int offset; 6203218211Srrs int cpu_to_use; 6204218371Srrs uint32_t flowid, tag; 6205218211Srrs 6206218269Srrs if (mp_ncpus > 1) { 6207281955Shiren if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) { 6208218371Srrs flowid = m->m_pkthdr.flowid; 6209218269Srrs } else { 6210218269Srrs /* 6211218371Srrs * No flow id built by lower layers fix it so we 6212218371Srrs * create one. 6213218269Srrs */ 6214237715Stuexen offset = off + sizeof(struct sctphdr); 6215218371Srrs if (SCTP_BUF_LEN(m) < offset) { 6216237715Stuexen if ((m = m_pullup(m, offset)) == NULL) { 6217218371Srrs SCTP_STAT_INCR(sctps_hdrops); 6218218371Srrs return; 6219218371Srrs } 6220218371Srrs } 6221237715Stuexen ip = mtod(m, struct ip *); 6222218371Srrs sh = (struct sctphdr *)((caddr_t)ip + off); 6223218371Srrs tag = htonl(sh->v_tag); 6224218371Srrs flowid = tag ^ ntohs(sh->dest_port) ^ ntohs(sh->src_port); 6225218371Srrs m->m_pkthdr.flowid = flowid; 6226281955Shiren M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE); 6227218269Srrs } 6228218371Srrs cpu_to_use = sctp_cpuarry[flowid % mp_ncpus]; 6229218211Srrs sctp_queue_to_mcore(m, off, cpu_to_use); 6230218211Srrs return; 6231218211Srrs } 6232218211Srrs#endif 6233218211Srrs sctp_input_with_port(m, off, 0); 6234179157Srrs} 6235221249Stuexen 6236221249Stuexen#endif 6237