sctp_input.c revision 270354
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: stable/10/sys/netinet/sctp_input.c 270354 2014-08-22 19:49:43Z 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, 88237049Stuexen struct sctp_tcb *stcb, int *abort_no_unlock, 89237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 90237049Stuexen uint32_t vrf_id, uint16_t port) 91163953Srrs{ 92163953Srrs struct sctp_init *init; 93163953Srrs struct mbuf *op_err; 94163953Srrs 95169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_init: handling INIT tcb:%p\n", 96240148Stuexen (void *)stcb); 97172396Srrs if (stcb == NULL) { 98172396Srrs SCTP_INP_RLOCK(inp); 99172396Srrs } 100229774Stuexen /* validate length */ 101163953Srrs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) { 102267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 103237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 104237049Stuexen use_mflowid, mflowid, 105179157Srrs vrf_id, port); 106168299Srrs if (stcb) 107168299Srrs *abort_no_unlock = 1; 108172396Srrs goto outnow; 109163953Srrs } 110163953Srrs /* validate parameters */ 111229774Stuexen init = &cp->init; 112163953Srrs if (init->initiate_tag == 0) { 113163953Srrs /* protocol error... send abort */ 114267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 115237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 116237049Stuexen use_mflowid, mflowid, 117179157Srrs vrf_id, port); 118168299Srrs if (stcb) 119168299Srrs *abort_no_unlock = 1; 120172396Srrs goto outnow; 121163953Srrs } 122163953Srrs if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) { 123163953Srrs /* invalid parameter... send abort */ 124267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 125237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 126237049Stuexen use_mflowid, mflowid, 127179157Srrs vrf_id, port); 128171440Srrs if (stcb) 129171440Srrs *abort_no_unlock = 1; 130172396Srrs goto outnow; 131163953Srrs } 132163953Srrs if (init->num_inbound_streams == 0) { 133163953Srrs /* protocol error... send abort */ 134267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 135237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 136237049Stuexen use_mflowid, mflowid, 137179157Srrs vrf_id, port); 138168299Srrs if (stcb) 139168299Srrs *abort_no_unlock = 1; 140172396Srrs goto outnow; 141163953Srrs } 142163953Srrs if (init->num_outbound_streams == 0) { 143163953Srrs /* protocol error... send abort */ 144267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 145237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 146237049Stuexen use_mflowid, mflowid, 147179157Srrs vrf_id, port); 148168299Srrs if (stcb) 149168299Srrs *abort_no_unlock = 1; 150172396Srrs goto outnow; 151163953Srrs } 152163953Srrs if (sctp_validate_init_auth_params(m, offset + sizeof(*cp), 153229774Stuexen offset + ntohs(cp->ch.chunk_length))) { 154163953Srrs /* auth parameter(s) error... send abort */ 155267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 156267723Stuexen "Problem with AUTH parameters"); 157267723Stuexen sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 158237049Stuexen use_mflowid, mflowid, 159237049Stuexen vrf_id, port); 160168299Srrs if (stcb) 161168299Srrs *abort_no_unlock = 1; 162172396Srrs goto outnow; 163163953Srrs } 164229774Stuexen /* 165229774Stuexen * We are only accepting if we have a socket with positive 166229774Stuexen * so_qlimit. 167229774Stuexen */ 168229774Stuexen if ((stcb == NULL) && 169229774Stuexen ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 170229774Stuexen (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 171229774Stuexen (inp->sctp_socket == NULL) || 172229774Stuexen (inp->sctp_socket->so_qlimit == 0))) { 173229774Stuexen /* 174229774Stuexen * FIX ME ?? What about TCP model and we have a 175229774Stuexen * match/restart case? Actually no fix is needed. the lookup 176229774Stuexen * will always find the existing assoc so stcb would not be 177229774Stuexen * NULL. It may be questionable to do this since we COULD 178229774Stuexen * just send back the INIT-ACK and hope that the app did 179229774Stuexen * accept()'s by the time the COOKIE was sent. But there is 180229774Stuexen * a price to pay for COOKIE generation and I don't want to 181229774Stuexen * pay it on the chance that the app will actually do some 182229774Stuexen * accepts(). The App just looses and should NOT be in this 183229774Stuexen * state :-) 184229774Stuexen */ 185229805Stuexen if (SCTP_BASE_SYSCTL(sctp_blackhole) == 0) { 186267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 187267723Stuexen "No listener"); 188267723Stuexen sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, 189237049Stuexen use_mflowid, mflowid, 190237049Stuexen vrf_id, port); 191229805Stuexen } 192229774Stuexen goto outnow; 193229774Stuexen } 194229774Stuexen if ((stcb != NULL) && 195229774Stuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT)) { 196229774Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending SHUTDOWN-ACK\n"); 197229774Stuexen sctp_send_shutdown_ack(stcb, NULL); 198229774Stuexen sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 199229774Stuexen } else { 200229774Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n"); 201237715Stuexen sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, src, dst, 202237715Stuexen sh, cp, 203237049Stuexen use_mflowid, mflowid, 204237049Stuexen vrf_id, port, 205229774Stuexen ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED)); 206229774Stuexen } 207172396Srrsoutnow: 208172396Srrs if (stcb == NULL) { 209172396Srrs SCTP_INP_RUNLOCK(inp); 210172396Srrs } 211163953Srrs} 212163953Srrs 213163953Srrs/* 214163953Srrs * process peer "INIT/INIT-ACK" chunk returns value < 0 on error 215163953Srrs */ 216171158Srrs 217171158Srrsint 218221627Stuexensctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked 219221627Stuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 220221627Stuexen SCTP_UNUSED 221221627Stuexen#endif 222221627Stuexen) 223171158Srrs{ 224171158Srrs int unsent_data = 0; 225217760Stuexen unsigned int i; 226217760Stuexen struct sctp_stream_queue_pending *sp; 227171158Srrs struct sctp_association *asoc; 228171158Srrs 229171158Srrs /* 230171158Srrs * This function returns the number of streams that have true unsent 231171158Srrs * data on them. Note that as it looks through it will clean up any 232171158Srrs * places that have old data that has been sent but left at top of 233171158Srrs * stream queue. 234171158Srrs */ 235171158Srrs asoc = &stcb->asoc; 236171158Srrs SCTP_TCB_SEND_LOCK(stcb); 237217760Stuexen if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 238217760Stuexen /* Check to see if some data queued */ 239217760Stuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 240217760Stuexen /* sa_ignore FREED_MEMORY */ 241217760Stuexen sp = TAILQ_FIRST(&stcb->asoc.strmout[i].outqueue); 242217760Stuexen if (sp == NULL) { 243217760Stuexen continue; 244217760Stuexen } 245171158Srrs if ((sp->msg_is_complete) && 246171158Srrs (sp->length == 0) && 247171158Srrs (sp->sender_all_done)) { 248171158Srrs /* 249171158Srrs * We are doing differed cleanup. Last time 250171158Srrs * through when we took all the data the 251171158Srrs * sender_all_done was not set. 252171158Srrs */ 253171158Srrs if (sp->put_last_out == 0) { 254171158Srrs SCTP_PRINTF("Gak, put out entire msg with NO end!-1\n"); 255171158Srrs SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d\n", 256171158Srrs sp->sender_all_done, 257171158Srrs sp->length, 258171158Srrs sp->msg_is_complete, 259171158Srrs sp->put_last_out); 260171158Srrs } 261217760Stuexen atomic_subtract_int(&stcb->asoc.stream_queue_cnt, 1); 262217760Stuexen TAILQ_REMOVE(&stcb->asoc.strmout[i].outqueue, sp, next); 263212712Stuexen if (sp->net) { 264212712Stuexen sctp_free_remote_addr(sp->net); 265212712Stuexen sp->net = NULL; 266212712Stuexen } 267171158Srrs if (sp->data) { 268171158Srrs sctp_m_freem(sp->data); 269171158Srrs sp->data = NULL; 270171158Srrs } 271221627Stuexen sctp_free_a_strmoq(stcb, sp, so_locked); 272171158Srrs } else { 273171158Srrs unsent_data++; 274216822Stuexen break; 275171158Srrs } 276171158Srrs } 277171158Srrs } 278171158Srrs SCTP_TCB_SEND_UNLOCK(stcb); 279171158Srrs return (unsent_data); 280171158Srrs} 281171158Srrs 282163953Srrsstatic int 283228653Stuexensctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) 284163953Srrs{ 285163953Srrs struct sctp_init *init; 286163953Srrs struct sctp_association *asoc; 287163953Srrs struct sctp_nets *lnet; 288163953Srrs unsigned int i; 289163953Srrs 290163953Srrs init = &cp->init; 291163953Srrs asoc = &stcb->asoc; 292163953Srrs /* save off parameters */ 293163953Srrs asoc->peer_vtag = ntohl(init->initiate_tag); 294163953Srrs asoc->peers_rwnd = ntohl(init->a_rwnd); 295218129Srrs /* init tsn's */ 296218129Srrs asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1; 297218129Srrs 298212712Stuexen if (!TAILQ_EMPTY(&asoc->nets)) { 299163953Srrs /* update any ssthresh's that may have a default */ 300163953Srrs TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) { 301163953Srrs lnet->ssthresh = asoc->peers_rwnd; 302179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) { 303170744Srrs sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_INITIALIZATION); 304170744Srrs } 305163953Srrs } 306163953Srrs } 307164181Srrs SCTP_TCB_SEND_LOCK(stcb); 308163953Srrs if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) { 309163953Srrs unsigned int newcnt; 310163953Srrs struct sctp_stream_out *outs; 311216822Stuexen struct sctp_stream_queue_pending *sp, *nsp; 312216822Stuexen struct sctp_tmit_chunk *chk, *nchk; 313163953Srrs 314196260Stuexen /* abandon the upper streams */ 315163953Srrs newcnt = ntohs(init->num_inbound_streams); 316216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { 317216822Stuexen if (chk->rec.data.stream_number >= newcnt) { 318216822Stuexen TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); 319216822Stuexen asoc->send_queue_cnt--; 320242714Stuexen if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 321242714Stuexen asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 322242714Stuexen#ifdef INVARIANTS 323242714Stuexen } else { 324242714Stuexen panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 325242714Stuexen#endif 326242714Stuexen } 327216822Stuexen if (chk->data != NULL) { 328216822Stuexen sctp_free_bufspace(stcb, asoc, chk, 1); 329235416Stuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 330235416Stuexen 0, chk, SCTP_SO_NOT_LOCKED); 331216822Stuexen if (chk->data) { 332216822Stuexen sctp_m_freem(chk->data); 333216822Stuexen chk->data = NULL; 334196260Stuexen } 335196260Stuexen } 336221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 337216822Stuexen /* sa_ignore FREED_MEMORY */ 338196260Stuexen } 339196260Stuexen } 340163953Srrs if (asoc->strmout) { 341163953Srrs for (i = newcnt; i < asoc->pre_open_streams; i++) { 342163953Srrs outs = &asoc->strmout[i]; 343216822Stuexen TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { 344196260Stuexen TAILQ_REMOVE(&outs->outqueue, sp, next); 345163953Srrs asoc->stream_queue_cnt--; 346163953Srrs sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, 347235416Stuexen stcb, 0, sp, SCTP_SO_NOT_LOCKED); 348163953Srrs if (sp->data) { 349163953Srrs sctp_m_freem(sp->data); 350163953Srrs sp->data = NULL; 351163953Srrs } 352212712Stuexen if (sp->net) { 353212712Stuexen sctp_free_remote_addr(sp->net); 354212712Stuexen sp->net = NULL; 355212712Stuexen } 356163953Srrs /* Free the chunk */ 357221627Stuexen sctp_free_a_strmoq(stcb, sp, SCTP_SO_NOT_LOCKED); 358169655Srrs /* sa_ignore FREED_MEMORY */ 359163953Srrs } 360163953Srrs } 361163953Srrs } 362196260Stuexen /* cut back the count */ 363163953Srrs asoc->pre_open_streams = newcnt; 364163953Srrs } 365164181Srrs SCTP_TCB_SEND_UNLOCK(stcb); 366188854Srrs asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams; 367218129Srrs 368185694Srrs /* EY - nr_sack: initialize highest tsn in nr_mapping_array */ 369185694Srrs asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 370179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 371170744Srrs sctp_log_map(0, 5, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 372170744Srrs } 373163953Srrs /* This is the next one we expect */ 374163953Srrs asoc->str_reset_seq_in = asoc->asconf_seq_in + 1; 375163953Srrs 376163953Srrs asoc->mapping_array_base_tsn = ntohl(init->initial_tsn); 377180955Srrs asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->asconf_seq_in; 378218129Srrs 379163953Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 380163953Srrs /* open the requested streams */ 381170091Srrs 382163953Srrs if (asoc->strmin != NULL) { 383163953Srrs /* Free the old ones */ 384216822Stuexen struct sctp_queued_to_read *ctl, *nctl; 385164181Srrs 386164181Srrs for (i = 0; i < asoc->streamincnt; i++) { 387216822Stuexen TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) { 388164181Srrs TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next); 389164181Srrs sctp_free_remote_addr(ctl->whoFrom); 390171158Srrs ctl->whoFrom = NULL; 391164181Srrs sctp_m_freem(ctl->data); 392164181Srrs ctl->data = NULL; 393164181Srrs sctp_free_a_readq(stcb, ctl); 394164181Srrs } 395164181Srrs } 396170091Srrs SCTP_FREE(asoc->strmin, SCTP_M_STRMI); 397163953Srrs } 398252779Stuexen if (asoc->max_inbound_streams > ntohs(init->num_outbound_streams)) { 399252779Stuexen asoc->streamincnt = ntohs(init->num_outbound_streams); 400252779Stuexen } else { 401252779Stuexen asoc->streamincnt = asoc->max_inbound_streams; 402164181Srrs } 403163953Srrs SCTP_MALLOC(asoc->strmin, struct sctp_stream_in *, asoc->streamincnt * 404170091Srrs sizeof(struct sctp_stream_in), SCTP_M_STRMI); 405163953Srrs if (asoc->strmin == NULL) { 406163953Srrs /* we didn't get memory for the streams! */ 407169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "process_init: couldn't get memory for the streams!\n"); 408163953Srrs return (-1); 409163953Srrs } 410163953Srrs for (i = 0; i < asoc->streamincnt; i++) { 411163953Srrs asoc->strmin[i].stream_no = i; 412163953Srrs asoc->strmin[i].last_sequence_delivered = 0xffff; 413163953Srrs TAILQ_INIT(&asoc->strmin[i].inqueue); 414168943Srrs asoc->strmin[i].delivery_started = 0; 415163953Srrs } 416163953Srrs /* 417163953Srrs * load_address_from_init will put the addresses into the 418163953Srrs * association when the COOKIE is processed or the INIT-ACK is 419163953Srrs * processed. Both types of COOKIE's existing and new call this 420163953Srrs * routine. It will remove addresses that are no longer in the 421163953Srrs * association (for the restarting case where addresses are 422163953Srrs * removed). Up front when the INIT arrives we will discard it if it 423163953Srrs * is a restart and new addresses have been added. 424163953Srrs */ 425169655Srrs /* sa_ignore MEMLEAK */ 426163953Srrs return (0); 427163953Srrs} 428163953Srrs 429163953Srrs/* 430163953Srrs * INIT-ACK message processing/consumption returns value < 0 on error 431163953Srrs */ 432163953Srrsstatic int 433237715Stuexensctp_process_init_ack(struct mbuf *m, int iphlen, int offset, 434237715Stuexen struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 435237049Stuexen struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 436237049Stuexen struct sctp_nets *net, int *abort_no_unlock, 437237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 438237049Stuexen uint32_t vrf_id) 439163953Srrs{ 440163953Srrs struct sctp_association *asoc; 441163953Srrs struct mbuf *op_err; 442163953Srrs int retval, abort_flag; 443163953Srrs uint32_t initack_limit; 444185694Srrs int nat_friendly = 0; 445163953Srrs 446163953Srrs /* First verify that we have no illegal param's */ 447163953Srrs abort_flag = 0; 448163953Srrs 449163953Srrs op_err = sctp_arethere_unrecognized_parameters(m, 450163953Srrs (offset + sizeof(struct sctp_init_chunk)), 451185694Srrs &abort_flag, (struct sctp_chunkhdr *)cp, &nat_friendly); 452163953Srrs if (abort_flag) { 453163953Srrs /* Send an abort and notify peer */ 454235360Stuexen sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 455170056Srrs *abort_no_unlock = 1; 456163953Srrs return (-1); 457163953Srrs } 458163953Srrs asoc = &stcb->asoc; 459185694Srrs asoc->peer_supports_nat = (uint8_t) nat_friendly; 460163953Srrs /* process the peer's parameters in the INIT-ACK */ 461228653Stuexen retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb); 462163953Srrs if (retval < 0) { 463163953Srrs return (retval); 464163953Srrs } 465163953Srrs initack_limit = offset + ntohs(cp->ch.chunk_length); 466163953Srrs /* load all addresses */ 467228653Stuexen if ((retval = sctp_load_addresses_from_init(stcb, m, 468237715Stuexen (offset + sizeof(struct sctp_init_chunk)), initack_limit, 469237715Stuexen src, dst, NULL))) { 470267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 471267723Stuexen "Problem with address parameters"); 472169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 473169420Srrs "Load addresses from INIT causes an abort %d\n", 474169420Srrs retval); 475237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 476267723Stuexen src, dst, sh, op_err, 477237049Stuexen use_mflowid, mflowid, 478237049Stuexen vrf_id, net->port); 479168299Srrs *abort_no_unlock = 1; 480163953Srrs return (-1); 481163953Srrs } 482171477Srrs /* if the peer doesn't support asconf, flush the asconf queue */ 483171477Srrs if (asoc->peer_supports_asconf == 0) { 484216822Stuexen struct sctp_asconf_addr *param, *nparam; 485171477Srrs 486216822Stuexen TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) { 487216822Stuexen TAILQ_REMOVE(&asoc->asconf_queue, param, next); 488216822Stuexen SCTP_FREE(param, SCTP_M_ASC_ADDR); 489171477Srrs } 490171477Srrs } 491163953Srrs stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs, 492163953Srrs stcb->asoc.local_hmacs); 493163953Srrs if (op_err) { 494163953Srrs sctp_queue_op_err(stcb, op_err); 495163953Srrs /* queuing will steal away the mbuf chain to the out queue */ 496163953Srrs op_err = NULL; 497163953Srrs } 498163953Srrs /* extract the cookie and queue it to "echo" it back... */ 499179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 500171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 501171943Srrs stcb->asoc.overall_error_count, 502171943Srrs 0, 503171943Srrs SCTP_FROM_SCTP_INPUT, 504171943Srrs __LINE__); 505171943Srrs } 506163953Srrs stcb->asoc.overall_error_count = 0; 507163953Srrs net->error_count = 0; 508163953Srrs 509163953Srrs /* 510163953Srrs * Cancel the INIT timer, We do this first before queueing the 511163953Srrs * cookie. We always cancel at the primary to assue that we are 512163953Srrs * canceling the timer started by the INIT which always goes to the 513163953Srrs * primary. 514163953Srrs */ 515163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb, 516165220Srrs asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4); 517163953Srrs 518165220Srrs /* calculate the RTO */ 519218186Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy, 520219397Srrs SCTP_RTT_FROM_NON_DATA); 521165220Srrs 522163953Srrs retval = sctp_send_cookie_echo(m, offset, stcb, net); 523163953Srrs if (retval < 0) { 524163953Srrs /* 525163953Srrs * No cookie, we probably should send a op error. But in any 526163953Srrs * case if there is no cookie in the INIT-ACK, we can 527163953Srrs * abandon the peer, its broke. 528163953Srrs */ 529163953Srrs if (retval == -3) { 530163953Srrs /* We abort with an error of missing mandatory param */ 531267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_MISSING_PARAM, ""); 532163953Srrs if (op_err) { 533163953Srrs /* 534163953Srrs * Expand beyond to include the mandatory 535163953Srrs * param cookie 536163953Srrs */ 537163953Srrs struct sctp_inv_mandatory_param *mp; 538163953Srrs 539165647Srrs SCTP_BUF_LEN(op_err) = 540163953Srrs sizeof(struct sctp_inv_mandatory_param); 541163953Srrs mp = mtod(op_err, 542163953Srrs struct sctp_inv_mandatory_param *); 543163953Srrs /* Subtract the reserved param */ 544163953Srrs mp->length = 545163953Srrs htons(sizeof(struct sctp_inv_mandatory_param) - 2); 546163953Srrs mp->num_param = htonl(1); 547163953Srrs mp->param = htons(SCTP_STATE_COOKIE); 548163953Srrs mp->resv = 0; 549163953Srrs } 550163953Srrs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 551237715Stuexen src, dst, sh, op_err, 552237049Stuexen use_mflowid, mflowid, 553237049Stuexen vrf_id, net->port); 554168299Srrs *abort_no_unlock = 1; 555163953Srrs } 556163953Srrs return (retval); 557163953Srrs } 558163953Srrs return (0); 559163953Srrs} 560163953Srrs 561163953Srrsstatic void 562163953Srrssctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, 563163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 564163953Srrs{ 565163953Srrs struct sockaddr_storage 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 571221249Stuexen#ifdef INET 572221249Stuexen struct sockaddr_in *sin; 573221249Stuexen 574221249Stuexen#endif 575221249Stuexen#ifdef INET6 576221249Stuexen struct sockaddr_in6 *sin6; 577221249Stuexen 578221249Stuexen#endif 579221249Stuexen 580163953Srrs if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) { 581163953Srrs /* Invalid length */ 582163953Srrs return; 583163953Srrs } 584163953Srrs memset(&store, 0, sizeof(store)); 585221249Stuexen switch (cp->heartbeat.hb_info.addr_family) { 586221249Stuexen#ifdef INET 587221249Stuexen case AF_INET: 588221249Stuexen if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) { 589221249Stuexen sin = (struct sockaddr_in *)&store; 590221249Stuexen sin->sin_family = cp->heartbeat.hb_info.addr_family; 591221249Stuexen sin->sin_len = cp->heartbeat.hb_info.addr_len; 592221249Stuexen sin->sin_port = stcb->rport; 593221249Stuexen memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address, 594221249Stuexen sizeof(sin->sin_addr)); 595221249Stuexen } else { 596221249Stuexen return; 597221249Stuexen } 598221249Stuexen break; 599221249Stuexen#endif 600221249Stuexen#ifdef INET6 601221249Stuexen case AF_INET6: 602221249Stuexen if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) { 603221249Stuexen sin6 = (struct sockaddr_in6 *)&store; 604221249Stuexen sin6->sin6_family = cp->heartbeat.hb_info.addr_family; 605221249Stuexen sin6->sin6_len = cp->heartbeat.hb_info.addr_len; 606221249Stuexen sin6->sin6_port = stcb->rport; 607221249Stuexen memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address, 608221249Stuexen sizeof(sin6->sin6_addr)); 609221249Stuexen } else { 610221249Stuexen return; 611221249Stuexen } 612221249Stuexen break; 613221249Stuexen#endif 614221249Stuexen default: 615163953Srrs return; 616163953Srrs } 617221249Stuexen r_net = sctp_findnet(stcb, (struct sockaddr *)&store); 618163953Srrs if (r_net == NULL) { 619169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n"); 620163953Srrs return; 621163953Srrs } 622163953Srrs if ((r_net && (r_net->dest_state & SCTP_ADDR_UNCONFIRMED)) && 623163953Srrs (r_net->heartbeat_random1 == cp->heartbeat.hb_info.random_value1) && 624163953Srrs (r_net->heartbeat_random2 == cp->heartbeat.hb_info.random_value2)) { 625163953Srrs /* 626163953Srrs * If the its a HB and it's random value is correct when can 627163953Srrs * confirm the destination. 628163953Srrs */ 629163953Srrs r_net->dest_state &= ~SCTP_ADDR_UNCONFIRMED; 630167598Srrs if (r_net->dest_state & SCTP_ADDR_REQ_PRIMARY) { 631167598Srrs stcb->asoc.primary_destination = r_net; 632167598Srrs r_net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY; 633212225Srrs f_net = TAILQ_FIRST(&stcb->asoc.nets); 634212225Srrs if (f_net != r_net) { 635167598Srrs /* 636167598Srrs * first one on the list is NOT the primary 637167598Srrs * sctp_cmpaddr() is much more efficent if 638167598Srrs * the primary is the first on the list, 639167598Srrs * make it so. 640167598Srrs */ 641212225Srrs TAILQ_REMOVE(&stcb->asoc.nets, r_net, sctp_next); 642212225Srrs TAILQ_INSERT_HEAD(&stcb->asoc.nets, r_net, sctp_next); 643167598Srrs } 644172396Srrs req_prim = 1; 645167598Srrs } 646163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 647172090Srrs stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED); 648224641Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 649224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 650163953Srrs } 651224641Stuexen old_error_counter = r_net->error_count; 652163953Srrs r_net->error_count = 0; 653163953Srrs r_net->hb_responded = 1; 654163953Srrs tv.tv_sec = cp->heartbeat.hb_info.time_value_1; 655163953Srrs tv.tv_usec = cp->heartbeat.hb_info.time_value_2; 656224641Stuexen /* Now lets do a RTO with this */ 657224641Stuexen r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy, 658224641Stuexen SCTP_RTT_FROM_NON_DATA); 659224641Stuexen if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) { 660163953Srrs r_net->dest_state |= SCTP_ADDR_REACHABLE; 661163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 662235414Stuexen 0, (void *)r_net, SCTP_SO_NOT_LOCKED); 663163953Srrs } 664224641Stuexen if (r_net->dest_state & SCTP_ADDR_PF) { 665224641Stuexen r_net->dest_state &= ~SCTP_ADDR_PF; 666224641Stuexen stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net); 667224641Stuexen } 668224641Stuexen if (old_error_counter > 0) { 669224641Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 670224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 671224641Stuexen } 672224641Stuexen if (r_net == stcb->asoc.primary_destination) { 673224641Stuexen if (stcb->asoc.alternate) { 674224641Stuexen /* release the alternate, primary is good */ 675224641Stuexen sctp_free_remote_addr(stcb->asoc.alternate); 676224641Stuexen stcb->asoc.alternate = NULL; 677171440Srrs } 678171440Srrs } 679172396Srrs /* Mobility adaptation */ 680172396Srrs if (req_prim) { 681172396Srrs if ((sctp_is_mobility_feature_on(stcb->sctp_ep, 682172396Srrs SCTP_MOBILITY_BASE) || 683172396Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 684172396Srrs SCTP_MOBILITY_FASTHANDOFF)) && 685172396Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 686172396Srrs SCTP_MOBILITY_PRIM_DELETED)) { 687172396Srrs 688172396Srrs sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7); 689172396Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 690172396Srrs SCTP_MOBILITY_FASTHANDOFF)) { 691172396Srrs sctp_assoc_immediate_retrans(stcb, 692172396Srrs stcb->asoc.primary_destination); 693172396Srrs } 694172396Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 695172396Srrs SCTP_MOBILITY_BASE)) { 696212712Stuexen sctp_move_chunks_from_net(stcb, 697212712Stuexen stcb->asoc.deleted_primary); 698172396Srrs } 699172396Srrs sctp_delete_prim_timer(stcb->sctp_ep, stcb, 700172396Srrs stcb->asoc.deleted_primary); 701172396Srrs } 702172396Srrs } 703163953Srrs} 704163953Srrs 705185694Srrsstatic int 706185694Srrssctp_handle_nat_colliding_state(struct sctp_tcb *stcb) 707185694Srrs{ 708185694Srrs /* 709185694Srrs * return 0 means we want you to proceed with the abort non-zero 710185694Srrs * means no abort processing 711185694Srrs */ 712185694Srrs struct sctpasochead *head; 713185694Srrs 714185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) { 715185694Srrs /* generate a new vtag and send init */ 716185694Srrs LIST_REMOVE(stcb, sctp_asocs); 717185694Srrs stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 718185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 719185694Srrs /* 720185694Srrs * put it in the bucket in the vtag hash of assoc's for the 721185694Srrs * system 722185694Srrs */ 723185694Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 724185694Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 725185694Srrs return (1); 726185694Srrs } 727185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 728185694Srrs /* 729185694Srrs * treat like a case where the cookie expired i.e.: - dump 730185694Srrs * current cookie. - generate a new vtag. - resend init. 731185694Srrs */ 732185694Srrs /* generate a new vtag and send init */ 733185694Srrs LIST_REMOVE(stcb, sctp_asocs); 734185694Srrs stcb->asoc.state &= ~SCTP_STATE_COOKIE_ECHOED; 735185694Srrs stcb->asoc.state |= SCTP_STATE_COOKIE_WAIT; 736185694Srrs sctp_stop_all_cookie_timers(stcb); 737185694Srrs sctp_toss_old_cookies(stcb, &stcb->asoc); 738185694Srrs stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 739185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 740185694Srrs /* 741185694Srrs * put it in the bucket in the vtag hash of assoc's for the 742185694Srrs * system 743185694Srrs */ 744185694Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 745185694Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 746185694Srrs return (1); 747185694Srrs } 748185694Srrs return (0); 749185694Srrs} 750185694Srrs 751185694Srrsstatic int 752185694Srrssctp_handle_nat_missing_state(struct sctp_tcb *stcb, 753185694Srrs struct sctp_nets *net) 754185694Srrs{ 755185694Srrs /* 756185694Srrs * return 0 means we want you to proceed with the abort non-zero 757185694Srrs * means no abort processing 758185694Srrs */ 759185694Srrs if (stcb->asoc.peer_supports_auth == 0) { 760185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n"); 761185694Srrs return (0); 762185694Srrs } 763185694Srrs sctp_asconf_send_nat_state_update(stcb, net); 764185694Srrs return (1); 765185694Srrs} 766185694Srrs 767185694Srrs 768163953Srrsstatic void 769235360Stuexensctp_handle_abort(struct sctp_abort_chunk *abort, 770163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 771163953Srrs{ 772237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 773172090Srrs struct socket *so; 774172090Srrs 775172090Srrs#endif 776185694Srrs uint16_t len; 777235360Stuexen uint16_t error; 778172090Srrs 779169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n"); 780163953Srrs if (stcb == NULL) 781163953Srrs return; 782163953Srrs 783235360Stuexen len = ntohs(abort->ch.chunk_length); 784185694Srrs if (len > sizeof(struct sctp_chunkhdr)) { 785185694Srrs /* 786185694Srrs * Need to check the cause codes for our two magic nat 787185694Srrs * aborts which don't kill the assoc necessarily. 788185694Srrs */ 789185694Srrs struct sctp_missing_nat_state *natc; 790185694Srrs 791235360Stuexen natc = (struct sctp_missing_nat_state *)(abort + 1); 792235360Stuexen error = ntohs(natc->cause); 793235360Stuexen if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) { 794185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 795235360Stuexen abort->ch.chunk_flags); 796185694Srrs if (sctp_handle_nat_colliding_state(stcb)) { 797185694Srrs return; 798185694Srrs } 799235360Stuexen } else if (error == SCTP_CAUSE_NAT_MISSING_STATE) { 800185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 801235360Stuexen abort->ch.chunk_flags); 802185694Srrs if (sctp_handle_nat_missing_state(stcb, net)) { 803185694Srrs return; 804185694Srrs } 805185694Srrs } 806235360Stuexen } else { 807235360Stuexen error = 0; 808185694Srrs } 809163953Srrs /* stop any receive timers */ 810171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_6); 811163953Srrs /* notify user of the abort and clean up... */ 812235403Stuexen sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED); 813163953Srrs /* free the tcb */ 814163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_aborted); 815163953Srrs if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 816163953Srrs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 817163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 818163953Srrs } 819168859Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 820168859Srrs sctp_print_out_track_log(stcb); 821168859Srrs#endif 822237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 823172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 824172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 825172090Srrs SCTP_TCB_UNLOCK(stcb); 826172090Srrs SCTP_SOCKET_LOCK(so, 1); 827172090Srrs SCTP_TCB_LOCK(stcb); 828172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 829172090Srrs#endif 830171990Srrs stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 831171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 832171943Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_6); 833237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 834172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 835172090Srrs#endif 836169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n"); 837163953Srrs} 838163953Srrs 839163953Srrsstatic void 840224641Stuexensctp_start_net_timers(struct sctp_tcb *stcb) 841224641Stuexen{ 842224641Stuexen uint32_t cnt_hb_sent; 843224641Stuexen struct sctp_nets *net; 844224641Stuexen 845224641Stuexen cnt_hb_sent = 0; 846224641Stuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 847224641Stuexen /* 848224641Stuexen * For each network start: 1) A pmtu timer. 2) A HB timer 3) 849224641Stuexen * If the dest in unconfirmed send a hb as well if under 850224641Stuexen * max_hb_burst have been sent. 851224641Stuexen */ 852224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net); 853224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 854224641Stuexen if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) && 855224641Stuexen (cnt_hb_sent < SCTP_BASE_SYSCTL(sctp_hb_maxburst))) { 856224641Stuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 857224641Stuexen cnt_hb_sent++; 858224641Stuexen } 859224641Stuexen } 860224641Stuexen if (cnt_hb_sent) { 861224641Stuexen sctp_chunk_output(stcb->sctp_ep, stcb, 862224641Stuexen SCTP_OUTPUT_FROM_COOKIE_ACK, 863224641Stuexen SCTP_SO_NOT_LOCKED); 864224641Stuexen } 865224641Stuexen} 866224641Stuexen 867224641Stuexen 868224641Stuexenstatic void 869163953Srrssctp_handle_shutdown(struct sctp_shutdown_chunk *cp, 870163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag) 871163953Srrs{ 872163953Srrs struct sctp_association *asoc; 873163953Srrs int some_on_streamwheel; 874163953Srrs 875237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 876172090Srrs struct socket *so; 877172090Srrs 878172090Srrs#endif 879172090Srrs 880169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 881169420Srrs "sctp_handle_shutdown: handling SHUTDOWN\n"); 882163953Srrs if (stcb == NULL) 883163953Srrs return; 884165220Srrs asoc = &stcb->asoc; 885165220Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 886165220Srrs (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 887163953Srrs return; 888163953Srrs } 889163953Srrs if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) { 890163953Srrs /* Shutdown NOT the expected size */ 891163953Srrs return; 892163953Srrs } else { 893228653Stuexen sctp_update_acked(stcb, cp, abort_flag); 894199477Stuexen if (*abort_flag) { 895199477Stuexen return; 896199477Stuexen } 897163953Srrs } 898165220Srrs if (asoc->control_pdapi) { 899163953Srrs /* 900163953Srrs * With a normal shutdown we assume the end of last record. 901163953Srrs */ 902163953Srrs SCTP_INP_READ_LOCK(stcb->sctp_ep); 903165220Srrs asoc->control_pdapi->end_added = 1; 904165220Srrs asoc->control_pdapi->pdapi_aborted = 1; 905165220Srrs asoc->control_pdapi = NULL; 906163953Srrs SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 907237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 908172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 909172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 910172090Srrs SCTP_TCB_UNLOCK(stcb); 911172090Srrs SCTP_SOCKET_LOCK(so, 1); 912172090Srrs SCTP_TCB_LOCK(stcb); 913172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 914172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 915172090Srrs /* assoc was freed while we were unlocked */ 916172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 917172090Srrs return; 918172090Srrs } 919172090Srrs#endif 920163996Srrs sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 921237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 922172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 923172090Srrs#endif 924163953Srrs } 925163953Srrs /* goto SHUTDOWN_RECEIVED state to block new requests */ 926163953Srrs if (stcb->sctp_socket) { 927163953Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 928170056Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) && 929163953Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 930171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_RECEIVED); 931172703Srrs SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 932163953Srrs /* 933163953Srrs * notify upper layer that peer has initiated a 934163953Srrs * shutdown 935163953Srrs */ 936172090Srrs sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 937163953Srrs 938163953Srrs /* reset time */ 939169378Srrs (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 940163953Srrs } 941163953Srrs } 942163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) { 943163953Srrs /* 944163953Srrs * stop the shutdown timer, since we WILL move to 945163953Srrs * SHUTDOWN-ACK-SENT. 946163953Srrs */ 947171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_8); 948163953Srrs } 949171158Srrs /* Now is there unsent data on a stream somewhere? */ 950221627Stuexen some_on_streamwheel = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED); 951163953Srrs 952163953Srrs if (!TAILQ_EMPTY(&asoc->send_queue) || 953163953Srrs !TAILQ_EMPTY(&asoc->sent_queue) || 954163953Srrs some_on_streamwheel) { 955163953Srrs /* By returning we will push more data out */ 956163953Srrs return; 957163953Srrs } else { 958163953Srrs /* no outstanding data to send, so move on... */ 959163953Srrs /* send SHUTDOWN-ACK */ 960163953Srrs /* move to SHUTDOWN-ACK-SENT state */ 961166675Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 962166675Srrs (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 963163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 964163953Srrs } 965171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); 966172703Srrs SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 967214918Stuexen sctp_stop_timers_for_shutdown(stcb); 968246588Stuexen sctp_send_shutdown_ack(stcb, net); 969163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, 970163953Srrs stcb, net); 971163953Srrs } 972163953Srrs} 973163953Srrs 974163953Srrsstatic void 975228653Stuexensctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, 976204141Stuexen struct sctp_tcb *stcb, 977204141Stuexen struct sctp_nets *net) 978163953Srrs{ 979163953Srrs struct sctp_association *asoc; 980163953Srrs 981237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 982172090Srrs struct socket *so; 983172090Srrs 984172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 985172090Srrs#endif 986169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 987169420Srrs "sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n"); 988163953Srrs if (stcb == NULL) 989163953Srrs return; 990163953Srrs 991163953Srrs asoc = &stcb->asoc; 992163953Srrs /* process according to association state */ 993204141Stuexen if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 994204141Stuexen (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 995204141Stuexen /* unexpected SHUTDOWN-ACK... do OOTB handling... */ 996204141Stuexen sctp_send_shutdown_complete(stcb, net, 1); 997204141Stuexen SCTP_TCB_UNLOCK(stcb); 998204141Stuexen return; 999204141Stuexen } 1000163953Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) && 1001163953Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { 1002163953Srrs /* unexpected SHUTDOWN-ACK... so ignore... */ 1003163953Srrs SCTP_TCB_UNLOCK(stcb); 1004163953Srrs return; 1005163953Srrs } 1006165220Srrs if (asoc->control_pdapi) { 1007163953Srrs /* 1008163953Srrs * With a normal shutdown we assume the end of last record. 1009163953Srrs */ 1010163953Srrs SCTP_INP_READ_LOCK(stcb->sctp_ep); 1011165220Srrs asoc->control_pdapi->end_added = 1; 1012165220Srrs asoc->control_pdapi->pdapi_aborted = 1; 1013165220Srrs asoc->control_pdapi = NULL; 1014163953Srrs SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 1015237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1016172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1017172090Srrs SCTP_TCB_UNLOCK(stcb); 1018172090Srrs SCTP_SOCKET_LOCK(so, 1); 1019172090Srrs SCTP_TCB_LOCK(stcb); 1020172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1021172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1022172090Srrs /* assoc was freed while we were unlocked */ 1023172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1024172090Srrs return; 1025172090Srrs } 1026172090Srrs#endif 1027163996Srrs sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 1028237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1029172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1030172090Srrs#endif 1031163953Srrs } 1032252585Stuexen#ifdef INVARIANTS 1033163953Srrs if (!TAILQ_EMPTY(&asoc->send_queue) || 1034163953Srrs !TAILQ_EMPTY(&asoc->sent_queue) || 1035217760Stuexen !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 1036252585Stuexen panic("Queues are not empty when handling SHUTDOWN-ACK"); 1037163953Srrs } 1038252585Stuexen#endif 1039163953Srrs /* stop the timer */ 1040171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9); 1041163953Srrs /* send SHUTDOWN-COMPLETE */ 1042204141Stuexen sctp_send_shutdown_complete(stcb, net, 0); 1043163953Srrs /* notify upper layer protocol */ 1044163953Srrs if (stcb->sctp_socket) { 1045163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1046163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 1047229774Stuexen stcb->sctp_socket->so_snd.sb_cc = 0; 1048163953Srrs } 1049230379Stuexen sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1050163953Srrs } 1051163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 1052163953Srrs /* free the TCB but first save off the ep */ 1053237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1054172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1055172090Srrs SCTP_TCB_UNLOCK(stcb); 1056172090Srrs SCTP_SOCKET_LOCK(so, 1); 1057172090Srrs SCTP_TCB_LOCK(stcb); 1058172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1059172090Srrs#endif 1060171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 1061171440Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_10); 1062237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1063172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1064172090Srrs#endif 1065163953Srrs} 1066163953Srrs 1067163953Srrs/* 1068163953Srrs * Skip past the param header and then we will find the chunk that caused the 1069163953Srrs * problem. There are two possiblities ASCONF or FWD-TSN other than that and 1070163953Srrs * our peer must be broken. 1071163953Srrs */ 1072163953Srrsstatic void 1073163953Srrssctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr, 1074163953Srrs struct sctp_nets *net) 1075163953Srrs{ 1076163953Srrs struct sctp_chunkhdr *chk; 1077163953Srrs 1078163953Srrs chk = (struct sctp_chunkhdr *)((caddr_t)phdr + sizeof(*phdr)); 1079163953Srrs switch (chk->chunk_type) { 1080163953Srrs case SCTP_ASCONF_ACK: 1081163953Srrs case SCTP_ASCONF: 1082163953Srrs sctp_asconf_cleanup(stcb, net); 1083163953Srrs break; 1084163953Srrs case SCTP_FORWARD_CUM_TSN: 1085163953Srrs stcb->asoc.peer_supports_prsctp = 0; 1086163953Srrs break; 1087163953Srrs default: 1088169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1089169420Srrs "Peer does not support chunk type %d(%x)??\n", 1090169420Srrs chk->chunk_type, (uint32_t) chk->chunk_type); 1091163953Srrs break; 1092163953Srrs } 1093163953Srrs} 1094163953Srrs 1095163953Srrs/* 1096163953Srrs * Skip past the param header and then we will find the param that caused the 1097163953Srrs * problem. There are a number of param's in a ASCONF OR the prsctp param 1098163953Srrs * these will turn of specific features. 1099163953Srrs */ 1100163953Srrsstatic void 1101163953Srrssctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr) 1102163953Srrs{ 1103163953Srrs struct sctp_paramhdr *pbad; 1104163953Srrs 1105163953Srrs pbad = phdr + 1; 1106163953Srrs switch (ntohs(pbad->param_type)) { 1107163953Srrs /* pr-sctp draft */ 1108163953Srrs case SCTP_PRSCTP_SUPPORTED: 1109163953Srrs stcb->asoc.peer_supports_prsctp = 0; 1110163953Srrs break; 1111163953Srrs case SCTP_SUPPORTED_CHUNK_EXT: 1112163953Srrs break; 1113163953Srrs /* draft-ietf-tsvwg-addip-sctp */ 1114185694Srrs case SCTP_HAS_NAT_SUPPORT: 1115185694Srrs stcb->asoc.peer_supports_nat = 0; 1116185694Srrs break; 1117163953Srrs case SCTP_ADD_IP_ADDRESS: 1118163953Srrs case SCTP_DEL_IP_ADDRESS: 1119163953Srrs case SCTP_SET_PRIM_ADDR: 1120163953Srrs stcb->asoc.peer_supports_asconf = 0; 1121163953Srrs break; 1122163953Srrs case SCTP_SUCCESS_REPORT: 1123163953Srrs case SCTP_ERROR_CAUSE_IND: 1124169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support success? or error cause?\n"); 1125169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1126169420Srrs "Turning off ASCONF to this strange peer\n"); 1127163953Srrs stcb->asoc.peer_supports_asconf = 0; 1128163953Srrs break; 1129163953Srrs default: 1130169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1131169420Srrs "Peer does not support param type %d(%x)??\n", 1132169420Srrs pbad->param_type, (uint32_t) pbad->param_type); 1133163953Srrs break; 1134163953Srrs } 1135163953Srrs} 1136163953Srrs 1137163953Srrsstatic int 1138163953Srrssctp_handle_error(struct sctp_chunkhdr *ch, 1139163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 1140163953Srrs{ 1141163953Srrs int chklen; 1142163953Srrs struct sctp_paramhdr *phdr; 1143235418Stuexen uint16_t error, error_type; 1144163953Srrs uint16_t error_len; 1145163953Srrs struct sctp_association *asoc; 1146163953Srrs int adjust; 1147163953Srrs 1148237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1149172090Srrs struct socket *so; 1150172090Srrs 1151172090Srrs#endif 1152172090Srrs 1153163953Srrs /* parse through all of the errors and process */ 1154163953Srrs asoc = &stcb->asoc; 1155163953Srrs phdr = (struct sctp_paramhdr *)((caddr_t)ch + 1156163953Srrs sizeof(struct sctp_chunkhdr)); 1157163953Srrs chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr); 1158235418Stuexen error = 0; 1159163953Srrs while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) { 1160163953Srrs /* Process an Error Cause */ 1161163953Srrs error_type = ntohs(phdr->param_type); 1162163953Srrs error_len = ntohs(phdr->param_length); 1163163953Srrs if ((error_len > chklen) || (error_len == 0)) { 1164163953Srrs /* invalid param length for this param */ 1165169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Bogus length in error param- chunk left:%d errorlen:%d\n", 1166169420Srrs chklen, error_len); 1167163953Srrs return (0); 1168163953Srrs } 1169235418Stuexen if (error == 0) { 1170235418Stuexen /* report the first error cause */ 1171235418Stuexen error = error_type; 1172235418Stuexen } 1173163953Srrs switch (error_type) { 1174163953Srrs case SCTP_CAUSE_INVALID_STREAM: 1175163953Srrs case SCTP_CAUSE_MISSING_PARAM: 1176163953Srrs case SCTP_CAUSE_INVALID_PARAM: 1177163953Srrs case SCTP_CAUSE_NO_USER_DATA: 1178169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Software error we got a %d back? We have a bug :/ (or do they?)\n", 1179169420Srrs error_type); 1180163953Srrs break; 1181185694Srrs case SCTP_CAUSE_NAT_COLLIDING_STATE: 1182185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 1183185694Srrs ch->chunk_flags); 1184185694Srrs if (sctp_handle_nat_colliding_state(stcb)) { 1185185694Srrs return (0); 1186185694Srrs } 1187185694Srrs break; 1188185694Srrs case SCTP_CAUSE_NAT_MISSING_STATE: 1189185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 1190185694Srrs ch->chunk_flags); 1191185694Srrs if (sctp_handle_nat_missing_state(stcb, net)) { 1192185694Srrs return (0); 1193185694Srrs } 1194185694Srrs break; 1195163953Srrs case SCTP_CAUSE_STALE_COOKIE: 1196163953Srrs /* 1197163953Srrs * We only act if we have echoed a cookie and are 1198163953Srrs * waiting. 1199163953Srrs */ 1200163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 1201163953Srrs int *p; 1202163953Srrs 1203163953Srrs p = (int *)((caddr_t)phdr + sizeof(*phdr)); 1204163953Srrs /* Save the time doubled */ 1205163953Srrs asoc->cookie_preserve_req = ntohl(*p) << 1; 1206163953Srrs asoc->stale_cookie_count++; 1207163953Srrs if (asoc->stale_cookie_count > 1208163953Srrs asoc->max_init_times) { 1209235403Stuexen sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); 1210163953Srrs /* now free the asoc */ 1211237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1212172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1213172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1214172090Srrs SCTP_TCB_UNLOCK(stcb); 1215172090Srrs SCTP_SOCKET_LOCK(so, 1); 1216172090Srrs SCTP_TCB_LOCK(stcb); 1217172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1218172090Srrs#endif 1219171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 1220171943Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_11); 1221237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1222172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1223172090Srrs#endif 1224163953Srrs return (-1); 1225163953Srrs } 1226163953Srrs /* blast back to INIT state */ 1227185694Srrs sctp_toss_old_cookies(stcb, &stcb->asoc); 1228163953Srrs asoc->state &= ~SCTP_STATE_COOKIE_ECHOED; 1229163953Srrs asoc->state |= SCTP_STATE_COOKIE_WAIT; 1230163953Srrs sctp_stop_all_cookie_timers(stcb); 1231172090Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 1232163953Srrs } 1233163953Srrs break; 1234163953Srrs case SCTP_CAUSE_UNRESOLVABLE_ADDR: 1235163953Srrs /* 1236163953Srrs * Nothing we can do here, we don't do hostname 1237163953Srrs * addresses so if the peer does not like my IPv6 1238163953Srrs * (or IPv4 for that matter) it does not matter. If 1239163953Srrs * they don't support that type of address, they can 1240163953Srrs * NOT possibly get that packet type... i.e. with no 1241163953Srrs * IPv6 you can't recieve a IPv6 packet. so we can 1242163953Srrs * safely ignore this one. If we ever added support 1243163953Srrs * for HOSTNAME Addresses, then we would need to do 1244163953Srrs * something here. 1245163953Srrs */ 1246163953Srrs break; 1247163953Srrs case SCTP_CAUSE_UNRECOG_CHUNK: 1248163953Srrs sctp_process_unrecog_chunk(stcb, phdr, net); 1249163953Srrs break; 1250163953Srrs case SCTP_CAUSE_UNRECOG_PARAM: 1251163953Srrs sctp_process_unrecog_param(stcb, phdr); 1252163953Srrs break; 1253163953Srrs case SCTP_CAUSE_COOKIE_IN_SHUTDOWN: 1254163953Srrs /* 1255163953Srrs * We ignore this since the timer will drive out a 1256163953Srrs * new cookie anyway and there timer will drive us 1257163953Srrs * to send a SHUTDOWN_COMPLETE. We can't send one 1258163953Srrs * here since we don't have their tag. 1259163953Srrs */ 1260163953Srrs break; 1261163953Srrs case SCTP_CAUSE_DELETING_LAST_ADDR: 1262163953Srrs case SCTP_CAUSE_RESOURCE_SHORTAGE: 1263163953Srrs case SCTP_CAUSE_DELETING_SRC_ADDR: 1264163953Srrs /* 1265163953Srrs * We should NOT get these here, but in a 1266166086Srrs * ASCONF-ACK. 1267163953Srrs */ 1268169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Peer sends ASCONF errors in a Operational Error?<%d>?\n", 1269169420Srrs error_type); 1270163953Srrs break; 1271163953Srrs case SCTP_CAUSE_OUT_OF_RESC: 1272163953Srrs /* 1273163953Srrs * And what, pray tell do we do with the fact that 1274163953Srrs * the peer is out of resources? Not really sure we 1275166086Srrs * could do anything but abort. I suspect this 1276163953Srrs * should have came WITH an abort instead of in a 1277163953Srrs * OP-ERROR. 1278163953Srrs */ 1279163953Srrs break; 1280163953Srrs default: 1281169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_handle_error: unknown error type = 0x%xh\n", 1282169420Srrs error_type); 1283163953Srrs break; 1284163953Srrs } 1285163953Srrs adjust = SCTP_SIZE32(error_len); 1286163953Srrs chklen -= adjust; 1287163953Srrs phdr = (struct sctp_paramhdr *)((caddr_t)phdr + adjust); 1288163953Srrs } 1289235418Stuexen sctp_ulp_notify(SCTP_NOTIFY_REMOTE_ERROR, stcb, error, ch, SCTP_SO_NOT_LOCKED); 1290163953Srrs return (0); 1291163953Srrs} 1292163953Srrs 1293163953Srrsstatic int 1294237715Stuexensctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, 1295237715Stuexen struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 1296237049Stuexen struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 1297237049Stuexen struct sctp_nets *net, int *abort_no_unlock, 1298237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 1299237049Stuexen uint32_t vrf_id) 1300163953Srrs{ 1301163953Srrs struct sctp_init_ack *init_ack; 1302163953Srrs struct mbuf *op_err; 1303163953Srrs 1304169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1305169420Srrs "sctp_handle_init_ack: handling INIT-ACK\n"); 1306169420Srrs 1307163953Srrs if (stcb == NULL) { 1308169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1309169420Srrs "sctp_handle_init_ack: TCB is null\n"); 1310163953Srrs return (-1); 1311163953Srrs } 1312163953Srrs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) { 1313163953Srrs /* Invalid length */ 1314267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1315237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1316237715Stuexen src, dst, sh, op_err, 1317237049Stuexen use_mflowid, mflowid, 1318237049Stuexen vrf_id, net->port); 1319168299Srrs *abort_no_unlock = 1; 1320163953Srrs return (-1); 1321163953Srrs } 1322163953Srrs init_ack = &cp->init; 1323163953Srrs /* validate parameters */ 1324163953Srrs if (init_ack->initiate_tag == 0) { 1325163953Srrs /* protocol error... send an abort */ 1326267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1327237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1328237715Stuexen src, dst, sh, op_err, 1329237049Stuexen use_mflowid, mflowid, 1330237049Stuexen vrf_id, net->port); 1331168299Srrs *abort_no_unlock = 1; 1332163953Srrs return (-1); 1333163953Srrs } 1334163953Srrs if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) { 1335163953Srrs /* protocol error... send an abort */ 1336267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1337237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1338237715Stuexen src, dst, sh, op_err, 1339237049Stuexen use_mflowid, mflowid, 1340237049Stuexen vrf_id, net->port); 1341168299Srrs *abort_no_unlock = 1; 1342163953Srrs return (-1); 1343163953Srrs } 1344163953Srrs if (init_ack->num_inbound_streams == 0) { 1345163953Srrs /* protocol error... send an abort */ 1346267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1347237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1348237715Stuexen src, dst, sh, op_err, 1349237049Stuexen use_mflowid, mflowid, 1350237049Stuexen vrf_id, net->port); 1351168299Srrs *abort_no_unlock = 1; 1352163953Srrs return (-1); 1353163953Srrs } 1354163953Srrs if (init_ack->num_outbound_streams == 0) { 1355163953Srrs /* protocol error... send an abort */ 1356267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); 1357237715Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1358237715Stuexen src, dst, sh, op_err, 1359237049Stuexen use_mflowid, mflowid, 1360237049Stuexen vrf_id, net->port); 1361168299Srrs *abort_no_unlock = 1; 1362163953Srrs return (-1); 1363163953Srrs } 1364163953Srrs /* process according to association state... */ 1365171943Srrs switch (stcb->asoc.state & SCTP_STATE_MASK) { 1366163953Srrs case SCTP_STATE_COOKIE_WAIT: 1367163953Srrs /* this is the expected state for this chunk */ 1368163953Srrs /* process the INIT-ACK parameters */ 1369163953Srrs if (stcb->asoc.primary_destination->dest_state & 1370163953Srrs SCTP_ADDR_UNCONFIRMED) { 1371163953Srrs /* 1372163953Srrs * The primary is where we sent the INIT, we can 1373163953Srrs * always consider it confirmed when the INIT-ACK is 1374163953Srrs * returned. Do this before we load addresses 1375163953Srrs * though. 1376163953Srrs */ 1377163953Srrs stcb->asoc.primary_destination->dest_state &= 1378163953Srrs ~SCTP_ADDR_UNCONFIRMED; 1379163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 1380172090Srrs stcb, 0, (void *)stcb->asoc.primary_destination, SCTP_SO_NOT_LOCKED); 1381163953Srrs } 1382237715Stuexen if (sctp_process_init_ack(m, iphlen, offset, src, dst, sh, cp, stcb, 1383237049Stuexen net, abort_no_unlock, 1384237049Stuexen use_mflowid, mflowid, 1385237049Stuexen vrf_id) < 0) { 1386163953Srrs /* error in parsing parameters */ 1387163953Srrs return (-1); 1388163953Srrs } 1389163953Srrs /* update our state */ 1390169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to COOKIE-ECHOED state\n"); 1391171943Srrs SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_ECHOED); 1392163953Srrs 1393163953Srrs /* reset the RTO calc */ 1394179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1395171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1396171943Srrs stcb->asoc.overall_error_count, 1397171943Srrs 0, 1398171943Srrs SCTP_FROM_SCTP_INPUT, 1399171943Srrs __LINE__); 1400171943Srrs } 1401163953Srrs stcb->asoc.overall_error_count = 0; 1402169378Srrs (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 1403163953Srrs /* 1404163953Srrs * collapse the init timer back in case of a exponential 1405165220Srrs * backoff 1406163953Srrs */ 1407163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep, 1408163953Srrs stcb, net); 1409163953Srrs /* 1410163953Srrs * the send at the end of the inbound data processing will 1411163953Srrs * cause the cookie to be sent 1412163953Srrs */ 1413163953Srrs break; 1414163953Srrs case SCTP_STATE_SHUTDOWN_SENT: 1415163953Srrs /* incorrect state... discard */ 1416163953Srrs break; 1417163953Srrs case SCTP_STATE_COOKIE_ECHOED: 1418163953Srrs /* incorrect state... discard */ 1419163953Srrs break; 1420163953Srrs case SCTP_STATE_OPEN: 1421163953Srrs /* incorrect state... discard */ 1422163953Srrs break; 1423163953Srrs case SCTP_STATE_EMPTY: 1424163953Srrs case SCTP_STATE_INUSE: 1425163953Srrs default: 1426163953Srrs /* incorrect state... discard */ 1427163953Srrs return (-1); 1428163953Srrs break; 1429163953Srrs } 1430169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Leaving handle-init-ack end\n"); 1431163953Srrs return (0); 1432163953Srrs} 1433163953Srrs 1434185694Srrsstatic struct sctp_tcb * 1435185694Srrssctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 1436237715Stuexen struct sockaddr *src, struct sockaddr *dst, 1437185694Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 1438185694Srrs struct sctp_inpcb *inp, struct sctp_nets **netp, 1439185694Srrs struct sockaddr *init_src, int *notification, 1440185694Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1441237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 1442185694Srrs uint32_t vrf_id, uint16_t port); 1443163953Srrs 1444185694Srrs 1445163953Srrs/* 1446163953Srrs * handle a state cookie for an existing association m: input packet mbuf 1447163953Srrs * chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a 1448163953Srrs * "split" mbuf and the cookie signature does not exist offset: offset into 1449163953Srrs * mbuf to the cookie-echo chunk 1450163953Srrs */ 1451163953Srrsstatic struct sctp_tcb * 1452163953Srrssctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, 1453237715Stuexen struct sockaddr *src, struct sockaddr *dst, 1454163953Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 1455185694Srrs struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp, 1456228653Stuexen struct sockaddr *init_src, int *notification, 1457237049Stuexen int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1458237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 1459237049Stuexen uint32_t vrf_id, uint16_t port) 1460163953Srrs{ 1461163953Srrs struct sctp_association *asoc; 1462163953Srrs struct sctp_init_chunk *init_cp, init_buf; 1463163953Srrs struct sctp_init_ack_chunk *initack_cp, initack_buf; 1464185694Srrs struct sctp_nets *net; 1465185694Srrs struct mbuf *op_err; 1466165220Srrs int init_offset, initack_offset, i; 1467163953Srrs int retval; 1468164205Srrs int spec_flag = 0; 1469170140Srrs uint32_t how_indx; 1470163953Srrs 1471185694Srrs net = *netp; 1472163953Srrs /* I know that the TCB is non-NULL from the caller */ 1473163953Srrs asoc = &stcb->asoc; 1474166675Srrs for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); how_indx++) { 1475166023Srrs if (asoc->cookie_how[how_indx] == 0) 1476166023Srrs break; 1477166023Srrs } 1478166023Srrs if (how_indx < sizeof(asoc->cookie_how)) { 1479166023Srrs asoc->cookie_how[how_indx] = 1; 1480166023Srrs } 1481163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 1482163953Srrs /* SHUTDOWN came in after sending INIT-ACK */ 1483163953Srrs sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination); 1484267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, ""); 1485237715Stuexen sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, 1486237049Stuexen use_mflowid, mflowid, 1487179157Srrs vrf_id, net->port); 1488166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1489166023Srrs asoc->cookie_how[how_indx] = 2; 1490163953Srrs return (NULL); 1491163953Srrs } 1492163953Srrs /* 1493163953Srrs * find and validate the INIT chunk in the cookie (peer's info) the 1494163953Srrs * INIT should start after the cookie-echo header struct (chunk 1495163953Srrs * header, state cookie header struct) 1496163953Srrs */ 1497163953Srrs init_offset = offset += sizeof(struct sctp_cookie_echo_chunk); 1498163953Srrs 1499163953Srrs init_cp = (struct sctp_init_chunk *) 1500163953Srrs sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 1501163953Srrs (uint8_t *) & init_buf); 1502163953Srrs if (init_cp == NULL) { 1503163953Srrs /* could not pull a INIT chunk in cookie */ 1504163953Srrs return (NULL); 1505163953Srrs } 1506163953Srrs if (init_cp->ch.chunk_type != SCTP_INITIATION) { 1507163953Srrs return (NULL); 1508163953Srrs } 1509163953Srrs /* 1510163953Srrs * find and validate the INIT-ACK chunk in the cookie (my info) the 1511163953Srrs * INIT-ACK follows the INIT chunk 1512163953Srrs */ 1513228907Stuexen initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 1514163953Srrs initack_cp = (struct sctp_init_ack_chunk *) 1515163953Srrs sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 1516163953Srrs (uint8_t *) & initack_buf); 1517163953Srrs if (initack_cp == NULL) { 1518163953Srrs /* could not pull INIT-ACK chunk in cookie */ 1519163953Srrs return (NULL); 1520163953Srrs } 1521163953Srrs if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 1522163953Srrs return (NULL); 1523163953Srrs } 1524163953Srrs if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1525163953Srrs (ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag)) { 1526163953Srrs /* 1527163953Srrs * case D in Section 5.2.4 Table 2: MMAA process accordingly 1528163953Srrs * to get into the OPEN state 1529163953Srrs */ 1530166023Srrs if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 1531172091Srrs /*- 1532172091Srrs * Opps, this means that we somehow generated two vtag's 1533172091Srrs * the same. I.e. we did: 1534172091Srrs * Us Peer 1535172091Srrs * <---INIT(tag=a)------ 1536172091Srrs * ----INIT-ACK(tag=t)--> 1537172091Srrs * ----INIT(tag=t)------> *1 1538172091Srrs * <---INIT-ACK(tag=a)--- 1539172091Srrs * <----CE(tag=t)------------- *2 1540172091Srrs * 1541172091Srrs * At point *1 we should be generating a different 1542172091Srrs * tag t'. Which means we would throw away the CE and send 1543172091Srrs * ours instead. Basically this is case C (throw away side). 1544172091Srrs */ 1545172091Srrs if (how_indx < sizeof(asoc->cookie_how)) 1546172091Srrs asoc->cookie_how[how_indx] = 17; 1547172091Srrs return (NULL); 1548172091Srrs 1549166023Srrs } 1550267720Stuexen switch (SCTP_GET_STATE(asoc)) { 1551163953Srrs case SCTP_STATE_COOKIE_WAIT: 1552166023Srrs case SCTP_STATE_COOKIE_ECHOED: 1553163953Srrs /* 1554169352Srrs * INIT was sent but got a COOKIE_ECHO with the 1555166023Srrs * correct tags... just accept it...but we must 1556166023Srrs * process the init so that we can make sure we have 1557166023Srrs * the right seq no's. 1558163953Srrs */ 1559163953Srrs /* First we must process the INIT !! */ 1560228653Stuexen retval = sctp_process_init(init_cp, stcb); 1561163953Srrs if (retval < 0) { 1562166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1563166023Srrs asoc->cookie_how[how_indx] = 3; 1564163953Srrs return (NULL); 1565163953Srrs } 1566163953Srrs /* we have already processed the INIT so no problem */ 1567163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, 1568171440Srrs net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_12); 1569171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_13); 1570163953Srrs /* update current state */ 1571166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 1572166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 1573166675Srrs else 1574166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1575171943Srrs 1576171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1577163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1578163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1579163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1580163953Srrs } 1581166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1582165220Srrs sctp_stop_all_cookie_timers(stcb); 1583163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1584163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1585163953Srrs (inp->sctp_socket->so_qlimit == 0) 1586163953Srrs ) { 1587237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1588172090Srrs struct socket *so; 1589172090Srrs 1590172090Srrs#endif 1591163953Srrs /* 1592163953Srrs * Here is where collision would go if we 1593163953Srrs * did a connect() and instead got a 1594163953Srrs * init/init-ack/cookie done before the 1595163953Srrs * init-ack came back.. 1596163953Srrs */ 1597163953Srrs stcb->sctp_ep->sctp_flags |= 1598163953Srrs SCTP_PCB_FLAGS_CONNECTED; 1599237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1600172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1601172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1602172090Srrs SCTP_TCB_UNLOCK(stcb); 1603172090Srrs SCTP_SOCKET_LOCK(so, 1); 1604172090Srrs SCTP_TCB_LOCK(stcb); 1605172090Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1606172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1607172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1608172090Srrs return (NULL); 1609172090Srrs } 1610172090Srrs#endif 1611172090Srrs soisconnected(stcb->sctp_socket); 1612237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1613172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1614172090Srrs#endif 1615163953Srrs } 1616163953Srrs /* notify upper layer */ 1617163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 1618163953Srrs /* 1619163953Srrs * since we did not send a HB make sure we don't 1620163953Srrs * double things 1621163953Srrs */ 1622163953Srrs net->hb_responded = 1; 1623170642Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, 1624218186Srrs &cookie->time_entered, 1625218186Srrs sctp_align_unsafe_makecopy, 1626219397Srrs SCTP_RTT_FROM_NON_DATA); 1627163953Srrs 1628163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 1629163953Srrs (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) { 1630163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 1631163953Srrs inp, stcb, NULL); 1632163953Srrs } 1633163953Srrs break; 1634163953Srrs default: 1635163953Srrs /* 1636163953Srrs * we're in the OPEN state (or beyond), so peer must 1637163953Srrs * have simply lost the COOKIE-ACK 1638163953Srrs */ 1639163953Srrs break; 1640267720Stuexen } /* end switch */ 1641165220Srrs sctp_stop_all_cookie_timers(stcb); 1642163953Srrs /* 1643163953Srrs * We ignore the return code here.. not sure if we should 1644163953Srrs * somehow abort.. but we do have an existing asoc. This 1645163953Srrs * really should not fail. 1646163953Srrs */ 1647228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1648163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1649237715Stuexen initack_offset, src, dst, init_src)) { 1650166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1651166023Srrs asoc->cookie_how[how_indx] = 4; 1652163953Srrs return (NULL); 1653163953Srrs } 1654163953Srrs /* respond with a COOKIE-ACK */ 1655165220Srrs sctp_toss_old_cookies(stcb, asoc); 1656163953Srrs sctp_send_cookie_ack(stcb); 1657166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1658166023Srrs asoc->cookie_how[how_indx] = 5; 1659163953Srrs return (stcb); 1660169352Srrs } 1661163953Srrs if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 1662163953Srrs ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag && 1663163953Srrs cookie->tie_tag_my_vtag == 0 && 1664163953Srrs cookie->tie_tag_peer_vtag == 0) { 1665163953Srrs /* 1666163953Srrs * case C in Section 5.2.4 Table 2: XMOO silently discard 1667163953Srrs */ 1668166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1669166023Srrs asoc->cookie_how[how_indx] = 6; 1670163953Srrs return (NULL); 1671163953Srrs } 1672185694Srrs /* 1673185694Srrs * If nat support, and the below and stcb is established, send back 1674185694Srrs * a ABORT(colliding state) if we are established. 1675185694Srrs */ 1676185694Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) && 1677185694Srrs (asoc->peer_supports_nat) && 1678185694Srrs ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1679185694Srrs ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 1680185694Srrs (asoc->peer_vtag == 0)))) { 1681163953Srrs /* 1682185694Srrs * Special case - Peer's support nat. We may have two init's 1683185694Srrs * that we gave out the same tag on since one was not 1684185694Srrs * established.. i.e. we get INIT from host-1 behind the nat 1685185694Srrs * and we respond tag-a, we get a INIT from host-2 behind 1686185694Srrs * the nat and we get tag-a again. Then we bring up host-1 1687185694Srrs * (or 2's) assoc, Then comes the cookie from hsot-2 (or 1). 1688185694Srrs * Now we have colliding state. We must send an abort here 1689185694Srrs * with colliding state indication. 1690185694Srrs */ 1691267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_NAT_COLLIDING_STATE, ""); 1692237715Stuexen sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, 1693237049Stuexen use_mflowid, mflowid, 1694237049Stuexen vrf_id, port); 1695185694Srrs return (NULL); 1696185694Srrs } 1697185694Srrs if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1698185694Srrs ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 1699185694Srrs (asoc->peer_vtag == 0))) { 1700185694Srrs /* 1701163953Srrs * case B in Section 5.2.4 Table 2: MXAA or MOAA my info 1702163953Srrs * should be ok, re-accept peer info 1703163953Srrs */ 1704166023Srrs if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 1705166023Srrs /* 1706166023Srrs * Extension of case C. If we hit this, then the 1707166023Srrs * random number generator returned the same vtag 1708166023Srrs * when we first sent our INIT-ACK and when we later 1709166023Srrs * sent our INIT. The side with the seq numbers that 1710166023Srrs * are different will be the one that normnally 1711166023Srrs * would have hit case C. This in effect "extends" 1712166023Srrs * our vtags in this collision case to be 64 bits. 1713166023Srrs * The same collision could occur aka you get both 1714166023Srrs * vtag and seq number the same twice in a row.. but 1715166023Srrs * is much less likely. If it did happen then we 1716166023Srrs * would proceed through and bring up the assoc.. we 1717166023Srrs * may end up with the wrong stream setup however.. 1718166023Srrs * which would be bad.. but there is no way to 1719166023Srrs * tell.. until we send on a stream that does not 1720166023Srrs * exist :-) 1721166023Srrs */ 1722166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1723166023Srrs asoc->cookie_how[how_indx] = 7; 1724166023Srrs 1725166023Srrs return (NULL); 1726166023Srrs } 1727166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1728166023Srrs asoc->cookie_how[how_indx] = 8; 1729171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_14); 1730163953Srrs sctp_stop_all_cookie_timers(stcb); 1731163953Srrs /* 1732163953Srrs * since we did not send a HB make sure we don't double 1733163953Srrs * things 1734163953Srrs */ 1735163953Srrs net->hb_responded = 1; 1736163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 1737163953Srrs sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 1738163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, 1739163953Srrs NULL); 1740163953Srrs } 1741163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 1742164205Srrs asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 1743164205Srrs 1744164205Srrs if (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) { 1745164205Srrs /* 1746164205Srrs * Ok the peer probably discarded our data (if we 1747164205Srrs * echoed a cookie+data). So anything on the 1748164205Srrs * sent_queue should be marked for retransmit, we 1749164205Srrs * may not get something to kick us so it COULD 1750164205Srrs * still take a timeout to move these.. but it can't 1751164205Srrs * hurt to mark them. 1752164205Srrs */ 1753164205Srrs struct sctp_tmit_chunk *chk; 1754163953Srrs 1755164205Srrs TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 1756164205Srrs if (chk->sent < SCTP_DATAGRAM_RESEND) { 1757164205Srrs chk->sent = SCTP_DATAGRAM_RESEND; 1758171440Srrs sctp_flight_size_decrease(chk); 1759171440Srrs sctp_total_flight_decrease(stcb, chk); 1760168124Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1761164205Srrs spec_flag++; 1762164205Srrs } 1763164205Srrs } 1764164205Srrs 1765164205Srrs } 1766163953Srrs /* process the INIT info (peer's info) */ 1767228653Stuexen retval = sctp_process_init(init_cp, stcb); 1768163953Srrs if (retval < 0) { 1769166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1770166023Srrs asoc->cookie_how[how_indx] = 9; 1771163953Srrs return (NULL); 1772163953Srrs } 1773228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1774163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1775237715Stuexen initack_offset, src, dst, init_src)) { 1776166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1777166023Srrs asoc->cookie_how[how_indx] = 10; 1778163953Srrs return (NULL); 1779163953Srrs } 1780163953Srrs if ((asoc->state & SCTP_STATE_COOKIE_WAIT) || 1781163953Srrs (asoc->state & SCTP_STATE_COOKIE_ECHOED)) { 1782163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 1783163953Srrs 1784163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1785163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1786163953Srrs (inp->sctp_socket->so_qlimit == 0)) { 1787237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1788172090Srrs struct socket *so; 1789172090Srrs 1790172090Srrs#endif 1791163953Srrs stcb->sctp_ep->sctp_flags |= 1792163953Srrs SCTP_PCB_FLAGS_CONNECTED; 1793237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1794172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1795172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1796172090Srrs SCTP_TCB_UNLOCK(stcb); 1797172090Srrs SCTP_SOCKET_LOCK(so, 1); 1798172090Srrs SCTP_TCB_LOCK(stcb); 1799172090Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1800172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1801172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1802172090Srrs return (NULL); 1803172090Srrs } 1804172090Srrs#endif 1805172090Srrs soisconnected(stcb->sctp_socket); 1806237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1807172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1808172090Srrs#endif 1809163953Srrs } 1810166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 1811166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 1812166675Srrs else 1813166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1814166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1815166675Srrs } else if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 1816166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_restartestab); 1817166675Srrs } else { 1818166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1819163953Srrs } 1820171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1821163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1822163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1823163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1824163953Srrs } 1825163953Srrs sctp_stop_all_cookie_timers(stcb); 1826165220Srrs sctp_toss_old_cookies(stcb, asoc); 1827163953Srrs sctp_send_cookie_ack(stcb); 1828164205Srrs if (spec_flag) { 1829164205Srrs /* 1830164205Srrs * only if we have retrans set do we do this. What 1831164205Srrs * this call does is get only the COOKIE-ACK out and 1832164205Srrs * then when we return the normal call to 1833164205Srrs * sctp_chunk_output will get the retrans out behind 1834164205Srrs * this. 1835164205Srrs */ 1836172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_COOKIE_ACK, SCTP_SO_NOT_LOCKED); 1837164205Srrs } 1838166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1839166023Srrs asoc->cookie_how[how_indx] = 11; 1840166023Srrs 1841163953Srrs return (stcb); 1842163953Srrs } 1843163953Srrs if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 1844163953Srrs ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) && 1845163953Srrs cookie->tie_tag_my_vtag == asoc->my_vtag_nonce && 1846163953Srrs cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce && 1847163953Srrs cookie->tie_tag_peer_vtag != 0) { 1848163953Srrs struct sctpasochead *head; 1849163953Srrs 1850252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1851252585Stuexen struct socket *so; 1852252585Stuexen 1853252585Stuexen#endif 1854252585Stuexen 1855185694Srrs if (asoc->peer_supports_nat) { 1856185694Srrs /* 1857252585Stuexen * This is a gross gross hack. Just call the 1858185694Srrs * cookie_new code since we are allowing a duplicate 1859185694Srrs * association. I hope this works... 1860185694Srrs */ 1861237715Stuexen return (sctp_process_cookie_new(m, iphlen, offset, src, dst, 1862237715Stuexen sh, cookie, cookie_len, 1863185694Srrs inp, netp, init_src, notification, 1864185694Srrs auth_skipped, auth_offset, auth_len, 1865237049Stuexen use_mflowid, mflowid, 1866185694Srrs vrf_id, port)); 1867185694Srrs } 1868163953Srrs /* 1869163953Srrs * case A in Section 5.2.4 Table 2: XXMM (peer restarted) 1870163953Srrs */ 1871165220Srrs /* temp code */ 1872166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1873166023Srrs asoc->cookie_how[how_indx] = 12; 1874171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_15); 1875171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); 1876165647Srrs 1877163953Srrs /* notify upper layer */ 1878163953Srrs *notification = SCTP_NOTIFY_ASSOC_RESTART; 1879165220Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1880166675Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN) && 1881166675Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 1882166675Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 1883166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1884166675Srrs } 1885166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 1886166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_restartestab); 1887166675Srrs } else if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { 1888166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_collisionestab); 1889166675Srrs } 1890165647Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1891171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1892165647Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1893165647Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1894165647Srrs 1895165647Srrs } else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) { 1896165647Srrs /* move to OPEN state, if not in SHUTDOWN_SENT */ 1897171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1898165647Srrs } 1899165647Srrs asoc->pre_open_streams = 1900165647Srrs ntohs(initack_cp->init.num_outbound_streams); 1901165647Srrs asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 1902165647Srrs asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 1903179157Srrs asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 1904165647Srrs 1905165647Srrs asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 1906165647Srrs 1907165647Srrs asoc->str_reset_seq_in = asoc->init_seq_number; 1908165647Srrs 1909165647Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 1910170138Srrs if (asoc->mapping_array) { 1911165647Srrs memset(asoc->mapping_array, 0, 1912165647Srrs asoc->mapping_array_size); 1913170138Srrs } 1914205627Srrs if (asoc->nr_mapping_array) { 1915185694Srrs memset(asoc->nr_mapping_array, 0, 1916206137Stuexen asoc->mapping_array_size); 1917185694Srrs } 1918165220Srrs SCTP_TCB_UNLOCK(stcb); 1919252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1920252585Stuexen so = SCTP_INP_SO(stcb->sctp_ep); 1921252585Stuexen SCTP_SOCKET_LOCK(so, 1); 1922252585Stuexen#endif 1923165220Srrs SCTP_INP_INFO_WLOCK(); 1924165220Srrs SCTP_INP_WLOCK(stcb->sctp_ep); 1925165220Srrs SCTP_TCB_LOCK(stcb); 1926165220Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1927163953Srrs /* send up all the data */ 1928164205Srrs SCTP_TCB_SEND_LOCK(stcb); 1929165220Srrs 1930252585Stuexen sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED); 1931165220Srrs for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 1932243157Stuexen stcb->asoc.strmout[i].chunks_on_queues = 0; 1933165220Srrs stcb->asoc.strmout[i].stream_no = i; 1934242627Stuexen stcb->asoc.strmout[i].next_sequence_send = 0; 1935165220Srrs stcb->asoc.strmout[i].last_msg_incomplete = 0; 1936165220Srrs } 1937163953Srrs /* process the INIT-ACK info (my info) */ 1938163953Srrs asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 1939163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 1940163953Srrs 1941163953Srrs /* pull from vtag hash */ 1942163953Srrs LIST_REMOVE(stcb, sctp_asocs); 1943163953Srrs /* re-insert to new vtag position */ 1944179783Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, 1945179783Srrs SCTP_BASE_INFO(hashasocmark))]; 1946163953Srrs /* 1947163953Srrs * put it in the bucket in the vtag hash of assoc's for the 1948163953Srrs * system 1949163953Srrs */ 1950163953Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 1951163953Srrs 1952164205Srrs SCTP_TCB_SEND_UNLOCK(stcb); 1953165220Srrs SCTP_INP_WUNLOCK(stcb->sctp_ep); 1954165220Srrs SCTP_INP_INFO_WUNLOCK(); 1955252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1956252585Stuexen SCTP_SOCKET_UNLOCK(so, 1); 1957252585Stuexen#endif 1958252585Stuexen asoc->total_flight = 0; 1959252585Stuexen asoc->total_flight_count = 0; 1960252585Stuexen /* process the INIT info (peer's info) */ 1961228653Stuexen retval = sctp_process_init(init_cp, stcb); 1962163953Srrs if (retval < 0) { 1963166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1964166023Srrs asoc->cookie_how[how_indx] = 13; 1965166023Srrs 1966163953Srrs return (NULL); 1967163953Srrs } 1968163953Srrs /* 1969163953Srrs * since we did not send a HB make sure we don't double 1970163953Srrs * things 1971163953Srrs */ 1972163953Srrs net->hb_responded = 1; 1973163953Srrs 1974228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1975163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1976237715Stuexen initack_offset, src, dst, init_src)) { 1977166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1978166023Srrs asoc->cookie_how[how_indx] = 14; 1979166023Srrs 1980163953Srrs return (NULL); 1981163953Srrs } 1982163953Srrs /* respond with a COOKIE-ACK */ 1983163953Srrs sctp_stop_all_cookie_timers(stcb); 1984165220Srrs sctp_toss_old_cookies(stcb, asoc); 1985163953Srrs sctp_send_cookie_ack(stcb); 1986166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1987166023Srrs asoc->cookie_how[how_indx] = 15; 1988163953Srrs 1989163953Srrs return (stcb); 1990163953Srrs } 1991166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1992166023Srrs asoc->cookie_how[how_indx] = 16; 1993163953Srrs /* all other cases... */ 1994163953Srrs return (NULL); 1995163953Srrs} 1996163953Srrs 1997166086Srrs 1998163953Srrs/* 1999163953Srrs * handle a state cookie for a new association m: input packet mbuf chain-- 2000163953Srrs * assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a "split" mbuf 2001163953Srrs * and the cookie signature does not exist offset: offset into mbuf to the 2002163953Srrs * cookie-echo chunk length: length of the cookie chunk to: where the init 2003163953Srrs * was from returns a new TCB 2004163953Srrs */ 2005237049Stuexenstatic struct sctp_tcb * 2006163953Srrssctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 2007237715Stuexen struct sockaddr *src, struct sockaddr *dst, 2008163953Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 2009163953Srrs struct sctp_inpcb *inp, struct sctp_nets **netp, 2010163953Srrs struct sockaddr *init_src, int *notification, 2011169352Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 2012237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 2013179157Srrs uint32_t vrf_id, uint16_t port) 2014163953Srrs{ 2015163953Srrs struct sctp_tcb *stcb; 2016163953Srrs struct sctp_init_chunk *init_cp, init_buf; 2017163953Srrs struct sctp_init_ack_chunk *initack_cp, initack_buf; 2018163953Srrs struct sockaddr_storage sa_store; 2019163953Srrs struct sockaddr *initack_src = (struct sockaddr *)&sa_store; 2020163953Srrs struct sctp_association *asoc; 2021163953Srrs int init_offset, initack_offset, initack_limit; 2022163953Srrs int retval; 2023163953Srrs int error = 0; 2024166675Srrs uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE]; 2025163953Srrs 2026221249Stuexen#ifdef INET 2027221249Stuexen struct sockaddr_in *sin; 2028221249Stuexen 2029221249Stuexen#endif 2030221249Stuexen#ifdef INET6 2031221249Stuexen struct sockaddr_in6 *sin6; 2032221249Stuexen 2033221249Stuexen#endif 2034237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2035172090Srrs struct socket *so; 2036172090Srrs 2037172090Srrs so = SCTP_INP_SO(inp); 2038172090Srrs#endif 2039172090Srrs 2040163953Srrs /* 2041163953Srrs * find and validate the INIT chunk in the cookie (peer's info) the 2042163953Srrs * INIT should start after the cookie-echo header struct (chunk 2043163953Srrs * header, state cookie header struct) 2044163953Srrs */ 2045163953Srrs init_offset = offset + sizeof(struct sctp_cookie_echo_chunk); 2046163953Srrs init_cp = (struct sctp_init_chunk *) 2047163953Srrs sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 2048163953Srrs (uint8_t *) & init_buf); 2049163953Srrs if (init_cp == NULL) { 2050163953Srrs /* could not pull a INIT chunk in cookie */ 2051169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 2052169420Srrs "process_cookie_new: could not pull INIT chunk hdr\n"); 2053163953Srrs return (NULL); 2054163953Srrs } 2055163953Srrs if (init_cp->ch.chunk_type != SCTP_INITIATION) { 2056169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "HUH? process_cookie_new: could not find INIT chunk!\n"); 2057163953Srrs return (NULL); 2058163953Srrs } 2059228907Stuexen initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 2060163953Srrs /* 2061163953Srrs * find and validate the INIT-ACK chunk in the cookie (my info) the 2062163953Srrs * INIT-ACK follows the INIT chunk 2063163953Srrs */ 2064163953Srrs initack_cp = (struct sctp_init_ack_chunk *) 2065163953Srrs sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 2066163953Srrs (uint8_t *) & initack_buf); 2067163953Srrs if (initack_cp == NULL) { 2068163953Srrs /* could not pull INIT-ACK chunk in cookie */ 2069169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: could not pull INIT-ACK chunk hdr\n"); 2070163953Srrs return (NULL); 2071163953Srrs } 2072163953Srrs if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 2073163953Srrs return (NULL); 2074163953Srrs } 2075163953Srrs /* 2076163953Srrs * NOTE: We can't use the INIT_ACK's chk_length to determine the 2077163953Srrs * "initack_limit" value. This is because the chk_length field 2078163953Srrs * includes the length of the cookie, but the cookie is omitted when 2079163953Srrs * the INIT and INIT_ACK are tacked onto the cookie... 2080163953Srrs */ 2081163953Srrs initack_limit = offset + cookie_len; 2082163953Srrs 2083163953Srrs /* 2084163953Srrs * now that we know the INIT/INIT-ACK are in place, create a new TCB 2085163953Srrs * and popluate 2086163953Srrs */ 2087171531Srrs 2088171531Srrs /* 2089171531Srrs * Here we do a trick, we set in NULL for the proc/thread argument. 2090171531Srrs * We do this since in effect we only use the p argument when the 2091171531Srrs * socket is unbound and we must do an implicit bind. Since we are 2092171531Srrs * getting a cookie, we cannot be unbound. 2093171531Srrs */ 2094206137Stuexen stcb = sctp_aloc_assoc(inp, init_src, &error, 2095171531Srrs ntohl(initack_cp->init.initiate_tag), vrf_id, 2096171531Srrs (struct thread *)NULL 2097171531Srrs ); 2098163953Srrs if (stcb == NULL) { 2099163953Srrs struct mbuf *op_err; 2100163953Srrs 2101163953Srrs /* memory problem? */ 2102169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 2103169420Srrs "process_cookie_new: no room for another TCB!\n"); 2104267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 2105163953Srrs sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 2106237715Stuexen src, dst, sh, op_err, 2107237049Stuexen use_mflowid, mflowid, 2108237049Stuexen vrf_id, port); 2109163953Srrs return (NULL); 2110163953Srrs } 2111163953Srrs /* get the correct sctp_nets */ 2112169420Srrs if (netp) 2113169420Srrs *netp = sctp_findnet(stcb, init_src); 2114169420Srrs 2115163953Srrs asoc = &stcb->asoc; 2116163953Srrs /* get scope variables out of cookie */ 2117246595Stuexen asoc->scope.ipv4_local_scope = cookie->ipv4_scope; 2118246595Stuexen asoc->scope.site_scope = cookie->site_scope; 2119246595Stuexen asoc->scope.local_scope = cookie->local_scope; 2120246595Stuexen asoc->scope.loopback_scope = cookie->loopback_scope; 2121163953Srrs 2122246595Stuexen if ((asoc->scope.ipv4_addr_legal != cookie->ipv4_addr_legal) || 2123246595Stuexen (asoc->scope.ipv6_addr_legal != cookie->ipv6_addr_legal)) { 2124163953Srrs struct mbuf *op_err; 2125163953Srrs 2126163953Srrs /* 2127163953Srrs * Houston we have a problem. The EP changed while the 2128163953Srrs * cookie was in flight. Only recourse is to abort the 2129163953Srrs * association. 2130163953Srrs */ 2131170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2132267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 2133163953Srrs sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 2134237715Stuexen src, dst, sh, op_err, 2135237049Stuexen use_mflowid, mflowid, 2136237049Stuexen vrf_id, port); 2137237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2138172090Srrs SCTP_TCB_UNLOCK(stcb); 2139172090Srrs SCTP_SOCKET_LOCK(so, 1); 2140172090Srrs SCTP_TCB_LOCK(stcb); 2141172090Srrs#endif 2142171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 2143171440Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); 2144237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2145172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2146172090Srrs#endif 2147172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2148163953Srrs return (NULL); 2149163953Srrs } 2150163953Srrs /* process the INIT-ACK info (my info) */ 2151185694Srrs asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 2152163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 2153163953Srrs asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 2154163953Srrs asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 2155163953Srrs asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 2156179157Srrs asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 2157163953Srrs asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 2158163953Srrs asoc->str_reset_seq_in = asoc->init_seq_number; 2159163953Srrs 2160163953Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 2161163953Srrs 2162163953Srrs /* process the INIT info (peer's info) */ 2163169420Srrs if (netp) 2164228653Stuexen retval = sctp_process_init(init_cp, stcb); 2165169420Srrs else 2166169420Srrs retval = 0; 2167163953Srrs if (retval < 0) { 2168170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2169237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2170172090Srrs SCTP_TCB_UNLOCK(stcb); 2171172090Srrs SCTP_SOCKET_LOCK(so, 1); 2172172090Srrs SCTP_TCB_LOCK(stcb); 2173172090Srrs#endif 2174171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); 2175237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2176172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2177172090Srrs#endif 2178172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2179163953Srrs return (NULL); 2180163953Srrs } 2181163953Srrs /* load all addresses */ 2182228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 2183237715Stuexen init_offset + sizeof(struct sctp_init_chunk), initack_offset, 2184237715Stuexen src, dst, init_src)) { 2185170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2186237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2187172090Srrs SCTP_TCB_UNLOCK(stcb); 2188172090Srrs SCTP_SOCKET_LOCK(so, 1); 2189172090Srrs SCTP_TCB_LOCK(stcb); 2190172090Srrs#endif 2191171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_17); 2192237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2193172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2194172090Srrs#endif 2195172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2196163953Srrs return (NULL); 2197163953Srrs } 2198163953Srrs /* 2199163953Srrs * verify any preceding AUTH chunk that was skipped 2200163953Srrs */ 2201163953Srrs /* pull the local authentication parameters from the cookie/init-ack */ 2202163953Srrs sctp_auth_get_cookie_params(stcb, m, 2203163953Srrs initack_offset + sizeof(struct sctp_init_ack_chunk), 2204163953Srrs initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk))); 2205163953Srrs if (auth_skipped) { 2206163953Srrs struct sctp_auth_chunk *auth; 2207163953Srrs 2208163953Srrs auth = (struct sctp_auth_chunk *) 2209166675Srrs sctp_m_getptr(m, auth_offset, auth_len, auth_chunk_buf); 2210169420Srrs if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, auth_offset)) { 2211163953Srrs /* auth HMAC failed, dump the assoc and packet */ 2212169420Srrs SCTPDBG(SCTP_DEBUG_AUTH1, 2213169420Srrs "COOKIE-ECHO: AUTH failed\n"); 2214171440Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2215237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2216172090Srrs SCTP_TCB_UNLOCK(stcb); 2217172090Srrs SCTP_SOCKET_LOCK(so, 1); 2218172090Srrs SCTP_TCB_LOCK(stcb); 2219172090Srrs#endif 2220171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_18); 2221237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2222172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2223172090Srrs#endif 2224172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2225163953Srrs return (NULL); 2226163953Srrs } else { 2227163953Srrs /* remaining chunks checked... good to go */ 2228163953Srrs stcb->asoc.authenticated = 1; 2229163953Srrs } 2230163953Srrs } 2231163953Srrs /* update current state */ 2232169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 2233171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 2234163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 2235163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 2236163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 2237163953Srrs } 2238165220Srrs sctp_stop_all_cookie_timers(stcb); 2239163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_passiveestab); 2240163953Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 2241163953Srrs 2242163953Srrs /* 2243163953Srrs * if we're doing ASCONFs, check to see if we have any new local 2244163953Srrs * addresses that need to get added to the peer (eg. addresses 2245163953Srrs * changed while cookie echo in flight). This needs to be done 2246163953Srrs * after we go to the OPEN state to do the correct asconf 2247163953Srrs * processing. else, make sure we have the correct addresses in our 2248163953Srrs * lists 2249163953Srrs */ 2250163953Srrs 2251163953Srrs /* warning, we re-use sin, sin6, sa_store here! */ 2252163953Srrs /* pull in local_address (our "from" address) */ 2253221249Stuexen switch (cookie->laddr_type) { 2254221249Stuexen#ifdef INET 2255221249Stuexen case SCTP_IPV4_ADDRESS: 2256163953Srrs /* source addr is IPv4 */ 2257163953Srrs sin = (struct sockaddr_in *)initack_src; 2258163953Srrs memset(sin, 0, sizeof(*sin)); 2259163953Srrs sin->sin_family = AF_INET; 2260163953Srrs sin->sin_len = sizeof(struct sockaddr_in); 2261163953Srrs sin->sin_addr.s_addr = cookie->laddress[0]; 2262221249Stuexen break; 2263221249Stuexen#endif 2264221249Stuexen#ifdef INET6 2265221249Stuexen case SCTP_IPV6_ADDRESS: 2266163953Srrs /* source addr is IPv6 */ 2267163953Srrs sin6 = (struct sockaddr_in6 *)initack_src; 2268163953Srrs memset(sin6, 0, sizeof(*sin6)); 2269163953Srrs sin6->sin6_family = AF_INET6; 2270163953Srrs sin6->sin6_len = sizeof(struct sockaddr_in6); 2271163953Srrs sin6->sin6_scope_id = cookie->scope_id; 2272163953Srrs memcpy(&sin6->sin6_addr, cookie->laddress, 2273163953Srrs sizeof(sin6->sin6_addr)); 2274221249Stuexen break; 2275221249Stuexen#endif 2276221249Stuexen default: 2277170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2278237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2279172090Srrs SCTP_TCB_UNLOCK(stcb); 2280172090Srrs SCTP_SOCKET_LOCK(so, 1); 2281172090Srrs SCTP_TCB_LOCK(stcb); 2282172090Srrs#endif 2283171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_19); 2284237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2285172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2286172090Srrs#endif 2287172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2288163953Srrs return (NULL); 2289163953Srrs } 2290163953Srrs 2291163953Srrs /* set up to notify upper layer */ 2292163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 2293163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2294163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 2295163953Srrs (inp->sctp_socket->so_qlimit == 0)) { 2296163953Srrs /* 2297163953Srrs * This is an endpoint that called connect() how it got a 2298163953Srrs * cookie that is NEW is a bit of a mystery. It must be that 2299163953Srrs * the INIT was sent, but before it got there.. a complete 2300163953Srrs * INIT/INIT-ACK/COOKIE arrived. But of course then it 2301163953Srrs * should have went to the other code.. not here.. oh well.. 2302163953Srrs * a bit of protection is worth having.. 2303163953Srrs */ 2304163953Srrs stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 2305237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2306172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2307172090Srrs SCTP_TCB_UNLOCK(stcb); 2308172090Srrs SCTP_SOCKET_LOCK(so, 1); 2309172090Srrs SCTP_TCB_LOCK(stcb); 2310172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2311172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 2312172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2313172090Srrs return (NULL); 2314172090Srrs } 2315172090Srrs#endif 2316172090Srrs soisconnected(stcb->sctp_socket); 2317237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2318172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2319172090Srrs#endif 2320163953Srrs } else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 2321163953Srrs (inp->sctp_socket->so_qlimit)) { 2322163953Srrs /* 2323163953Srrs * We don't want to do anything with this one. Since it is 2324163953Srrs * the listening guy. The timer will get started for 2325163953Srrs * accepted connections in the caller. 2326163953Srrs */ 2327163953Srrs ; 2328163953Srrs } 2329163953Srrs /* since we did not send a HB make sure we don't double things */ 2330169420Srrs if ((netp) && (*netp)) 2331169420Srrs (*netp)->hb_responded = 1; 2332163953Srrs 2333163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 2334163953Srrs sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 2335163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL); 2336163953Srrs } 2337165220Srrs /* calculate the RTT */ 2338171440Srrs (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 2339170642Srrs if ((netp) && (*netp)) { 2340169420Srrs (*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp, 2341218186Srrs &cookie->time_entered, sctp_align_unsafe_makecopy, 2342219397Srrs SCTP_RTT_FROM_NON_DATA); 2343170642Srrs } 2344172190Srrs /* respond with a COOKIE-ACK */ 2345163953Srrs sctp_send_cookie_ack(stcb); 2346172190Srrs 2347172190Srrs /* 2348172190Srrs * check the address lists for any ASCONFs that need to be sent 2349172190Srrs * AFTER the cookie-ack is sent 2350172190Srrs */ 2351172190Srrs sctp_check_address_list(stcb, m, 2352172190Srrs initack_offset + sizeof(struct sctp_init_ack_chunk), 2353172190Srrs initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)), 2354172190Srrs initack_src, cookie->local_scope, cookie->site_scope, 2355172190Srrs cookie->ipv4_scope, cookie->loopback_scope); 2356172190Srrs 2357172190Srrs 2358163953Srrs return (stcb); 2359163953Srrs} 2360163953Srrs 2361185694Srrs/* 2362185694Srrs * CODE LIKE THIS NEEDS TO RUN IF the peer supports the NAT extension, i.e 2363185694Srrs * we NEED to make sure we are not already using the vtag. If so we 2364185694Srrs * need to send back an ABORT-TRY-AGAIN-WITH-NEW-TAG No middle box bit! 2365185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag, 2366185694Srrs SCTP_BASE_INFO(hashasocmark))]; 2367185694Srrs LIST_FOREACH(stcb, head, sctp_asocs) { 2368185694Srrs if ((stcb->asoc.my_vtag == tag) && (stcb->rport == rport) && (inp == stcb->sctp_ep)) { 2369185694Srrs -- SEND ABORT - TRY AGAIN -- 2370185694Srrs } 2371185694Srrs } 2372185694Srrs*/ 2373163953Srrs 2374163953Srrs/* 2375163953Srrs * handles a COOKIE-ECHO message stcb: modified to either a new or left as 2376163953Srrs * existing (non-NULL) TCB 2377163953Srrs */ 2378163953Srrsstatic struct mbuf * 2379163953Srrssctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, 2380237715Stuexen struct sockaddr *src, struct sockaddr *dst, 2381163953Srrs struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp, 2382163953Srrs struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp, 2383169352Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 2384237049Stuexen struct sctp_tcb **locked_tcb, 2385237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 2386237049Stuexen uint32_t vrf_id, uint16_t port) 2387163953Srrs{ 2388163953Srrs struct sctp_state_cookie *cookie; 2389163953Srrs struct sctp_tcb *l_stcb = *stcb; 2390163953Srrs struct sctp_inpcb *l_inp; 2391163953Srrs struct sockaddr *to; 2392163953Srrs struct sctp_pcb *ep; 2393163953Srrs struct mbuf *m_sig; 2394163953Srrs uint8_t calc_sig[SCTP_SIGNATURE_SIZE], tmp_sig[SCTP_SIGNATURE_SIZE]; 2395163953Srrs uint8_t *sig; 2396163953Srrs uint8_t cookie_ok = 0; 2397237541Stuexen unsigned int sig_offset, cookie_offset; 2398163953Srrs unsigned int cookie_len; 2399163953Srrs struct timeval now; 2400163953Srrs struct timeval time_expires; 2401163953Srrs int notification = 0; 2402163953Srrs struct sctp_nets *netl; 2403163953Srrs int had_a_existing_tcb = 0; 2404216887Stuexen int send_int_conf = 0; 2405163953Srrs 2406221249Stuexen#ifdef INET 2407221249Stuexen struct sockaddr_in sin; 2408221249Stuexen 2409221249Stuexen#endif 2410221249Stuexen#ifdef INET6 2411221249Stuexen struct sockaddr_in6 sin6; 2412221249Stuexen 2413221249Stuexen#endif 2414221249Stuexen 2415169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2416169420Srrs "sctp_handle_cookie: handling COOKIE-ECHO\n"); 2417163953Srrs 2418163953Srrs if (inp_p == NULL) { 2419163953Srrs return (NULL); 2420163953Srrs } 2421163953Srrs cookie = &cp->cookie; 2422163953Srrs cookie_offset = offset + sizeof(struct sctp_chunkhdr); 2423163953Srrs cookie_len = ntohs(cp->ch.chunk_length); 2424163953Srrs 2425163953Srrs if ((cookie->peerport != sh->src_port) && 2426163953Srrs (cookie->myport != sh->dest_port) && 2427163953Srrs (cookie->my_vtag != sh->v_tag)) { 2428163953Srrs /* 2429163953Srrs * invalid ports or bad tag. Note that we always leave the 2430163953Srrs * v_tag in the header in network order and when we stored 2431163953Srrs * it in the my_vtag slot we also left it in network order. 2432169352Srrs * This maintains the match even though it may be in the 2433163953Srrs * opposite byte order of the machine :-> 2434163953Srrs */ 2435163953Srrs return (NULL); 2436163953Srrs } 2437237541Stuexen if (cookie_len < sizeof(struct sctp_cookie_echo_chunk) + 2438163953Srrs sizeof(struct sctp_init_chunk) + 2439163953Srrs sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) { 2440237541Stuexen /* cookie too small */ 2441163953Srrs return (NULL); 2442163953Srrs } 2443163953Srrs /* 2444163953Srrs * split off the signature into its own mbuf (since it should not be 2445163953Srrs * calculated in the sctp_hmac_m() call). 2446163953Srrs */ 2447163953Srrs sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE; 2448243882Sglebius m_sig = m_split(m, sig_offset, M_NOWAIT); 2449163953Srrs if (m_sig == NULL) { 2450163953Srrs /* out of memory or ?? */ 2451163953Srrs return (NULL); 2452163953Srrs } 2453178202Srrs#ifdef SCTP_MBUF_LOGGING 2454179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 2455178202Srrs struct mbuf *mat; 2456178202Srrs 2457234461Stuexen for (mat = m_sig; mat; mat = SCTP_BUF_NEXT(mat)) { 2458178202Srrs if (SCTP_BUF_IS_EXTENDED(mat)) { 2459178202Srrs sctp_log_mb(mat, SCTP_MBUF_SPLIT); 2460178202Srrs } 2461178202Srrs } 2462178202Srrs } 2463178202Srrs#endif 2464178202Srrs 2465163953Srrs /* 2466163953Srrs * compute the signature/digest for the cookie 2467163953Srrs */ 2468163953Srrs ep = &(*inp_p)->sctp_ep; 2469163953Srrs l_inp = *inp_p; 2470163953Srrs if (l_stcb) { 2471163953Srrs SCTP_TCB_UNLOCK(l_stcb); 2472163953Srrs } 2473163953Srrs SCTP_INP_RLOCK(l_inp); 2474163953Srrs if (l_stcb) { 2475163953Srrs SCTP_TCB_LOCK(l_stcb); 2476163953Srrs } 2477163953Srrs /* which cookie is it? */ 2478163953Srrs if ((cookie->time_entered.tv_sec < (long)ep->time_of_secret_change) && 2479163953Srrs (ep->current_secret_number != ep->last_secret_number)) { 2480163953Srrs /* it's the old cookie */ 2481169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2482163953Srrs (uint8_t *) ep->secret_key[(int)ep->last_secret_number], 2483170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2484163953Srrs } else { 2485163953Srrs /* it's the current cookie */ 2486169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2487163953Srrs (uint8_t *) ep->secret_key[(int)ep->current_secret_number], 2488170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2489163953Srrs } 2490163953Srrs /* get the signature */ 2491163953Srrs SCTP_INP_RUNLOCK(l_inp); 2492163953Srrs sig = (uint8_t *) sctp_m_getptr(m_sig, 0, SCTP_SIGNATURE_SIZE, (uint8_t *) & tmp_sig); 2493163953Srrs if (sig == NULL) { 2494163953Srrs /* couldn't find signature */ 2495164085Srrs sctp_m_freem(m_sig); 2496163953Srrs return (NULL); 2497163953Srrs } 2498163953Srrs /* compare the received digest with the computed digest */ 2499163953Srrs if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) != 0) { 2500163953Srrs /* try the old cookie? */ 2501163953Srrs if ((cookie->time_entered.tv_sec == (long)ep->time_of_secret_change) && 2502163953Srrs (ep->current_secret_number != ep->last_secret_number)) { 2503163953Srrs /* compute digest with old */ 2504169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2505163953Srrs (uint8_t *) ep->secret_key[(int)ep->last_secret_number], 2506170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2507163953Srrs /* compare */ 2508163953Srrs if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) == 0) 2509163953Srrs cookie_ok = 1; 2510163953Srrs } 2511163953Srrs } else { 2512163953Srrs cookie_ok = 1; 2513163953Srrs } 2514163953Srrs 2515163953Srrs /* 2516163953Srrs * Now before we continue we must reconstruct our mbuf so that 2517163953Srrs * normal processing of any other chunks will work. 2518163953Srrs */ 2519163953Srrs { 2520163953Srrs struct mbuf *m_at; 2521163953Srrs 2522163953Srrs m_at = m; 2523165647Srrs while (SCTP_BUF_NEXT(m_at) != NULL) { 2524165647Srrs m_at = SCTP_BUF_NEXT(m_at); 2525163953Srrs } 2526165647Srrs SCTP_BUF_NEXT(m_at) = m_sig; 2527163953Srrs } 2528163953Srrs 2529163953Srrs if (cookie_ok == 0) { 2530169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "handle_cookie_echo: cookie signature validation failed!\n"); 2531169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2532169420Srrs "offset = %u, cookie_offset = %u, sig_offset = %u\n", 2533169420Srrs (uint32_t) offset, cookie_offset, sig_offset); 2534163953Srrs return (NULL); 2535163953Srrs } 2536163953Srrs /* 2537163953Srrs * check the cookie timestamps to be sure it's not stale 2538163953Srrs */ 2539169378Srrs (void)SCTP_GETTIME_TIMEVAL(&now); 2540163953Srrs /* Expire time is in Ticks, so we convert to seconds */ 2541169655Srrs time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life); 2542163953Srrs time_expires.tv_usec = cookie->time_entered.tv_usec; 2543180387Srrs /* 2544180387Srrs * TODO sctp_constants.h needs alternative time macros when _KERNEL 2545180387Srrs * is undefined. 2546180387Srrs */ 2547163953Srrs if (timevalcmp(&now, &time_expires, >)) { 2548163953Srrs /* cookie is stale! */ 2549163953Srrs struct mbuf *op_err; 2550163953Srrs struct sctp_stale_cookie_msg *scm; 2551163953Srrs uint32_t tim; 2552163953Srrs 2553163953Srrs op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg), 2554243882Sglebius 0, M_NOWAIT, 1, MT_DATA); 2555163953Srrs if (op_err == NULL) { 2556163953Srrs /* FOOBAR */ 2557163953Srrs return (NULL); 2558163953Srrs } 2559163953Srrs /* Set the len */ 2560165647Srrs SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg); 2561163953Srrs scm = mtod(op_err, struct sctp_stale_cookie_msg *); 2562163953Srrs scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE); 2563163953Srrs scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) + 2564163953Srrs (sizeof(uint32_t)))); 2565163953Srrs /* seconds to usec */ 2566163953Srrs tim = (now.tv_sec - time_expires.tv_sec) * 1000000; 2567163953Srrs /* add in usec */ 2568163953Srrs if (tim == 0) 2569163953Srrs tim = now.tv_usec - cookie->time_entered.tv_usec; 2570163953Srrs scm->time_usec = htonl(tim); 2571237715Stuexen sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, 2572237049Stuexen use_mflowid, mflowid, 2573179157Srrs vrf_id, port); 2574163953Srrs return (NULL); 2575163953Srrs } 2576163953Srrs /* 2577163953Srrs * Now we must see with the lookup address if we have an existing 2578163953Srrs * asoc. This will only happen if we were in the COOKIE-WAIT state 2579163953Srrs * and a INIT collided with us and somewhere the peer sent the 2580163953Srrs * cookie on another address besides the single address our assoc 2581163953Srrs * had for him. In this case we will have one of the tie-tags set at 2582163953Srrs * least AND the address field in the cookie can be used to look it 2583163953Srrs * up. 2584163953Srrs */ 2585163953Srrs to = NULL; 2586221249Stuexen switch (cookie->addr_type) { 2587221249Stuexen#ifdef INET6 2588221249Stuexen case SCTP_IPV6_ADDRESS: 2589163953Srrs memset(&sin6, 0, sizeof(sin6)); 2590163953Srrs sin6.sin6_family = AF_INET6; 2591163953Srrs sin6.sin6_len = sizeof(sin6); 2592163953Srrs sin6.sin6_port = sh->src_port; 2593163953Srrs sin6.sin6_scope_id = cookie->scope_id; 2594163953Srrs memcpy(&sin6.sin6_addr.s6_addr, cookie->address, 2595163953Srrs sizeof(sin6.sin6_addr.s6_addr)); 2596163953Srrs to = (struct sockaddr *)&sin6; 2597221249Stuexen break; 2598221249Stuexen#endif 2599221249Stuexen#ifdef INET 2600221249Stuexen case SCTP_IPV4_ADDRESS: 2601163953Srrs memset(&sin, 0, sizeof(sin)); 2602163953Srrs sin.sin_family = AF_INET; 2603163953Srrs sin.sin_len = sizeof(sin); 2604163953Srrs sin.sin_port = sh->src_port; 2605163953Srrs sin.sin_addr.s_addr = cookie->address[0]; 2606163953Srrs to = (struct sockaddr *)&sin; 2607221249Stuexen break; 2608221249Stuexen#endif 2609221249Stuexen default: 2610169420Srrs /* This should not happen */ 2611169420Srrs return (NULL); 2612163953Srrs } 2613163953Srrs if ((*stcb == NULL) && to) { 2614163953Srrs /* Yep, lets check */ 2615237715Stuexen *stcb = sctp_findassociation_ep_addr(inp_p, to, netp, dst, NULL); 2616163953Srrs if (*stcb == NULL) { 2617163953Srrs /* 2618163953Srrs * We should have only got back the same inp. If we 2619163953Srrs * got back a different ep we have a problem. The 2620163953Srrs * original findep got back l_inp and now 2621163953Srrs */ 2622163953Srrs if (l_inp != *inp_p) { 2623169420Srrs SCTP_PRINTF("Bad problem find_ep got a diff inp then special_locate?\n"); 2624163953Srrs } 2625165220Srrs } else { 2626165220Srrs if (*locked_tcb == NULL) { 2627165220Srrs /* 2628165220Srrs * In this case we found the assoc only 2629165220Srrs * after we locked the create lock. This 2630165220Srrs * means we are in a colliding case and we 2631165220Srrs * must make sure that we unlock the tcb if 2632165220Srrs * its one of the cases where we throw away 2633165220Srrs * the incoming packets. 2634165220Srrs */ 2635165220Srrs *locked_tcb = *stcb; 2636165220Srrs 2637165220Srrs /* 2638165220Srrs * We must also increment the inp ref count 2639165220Srrs * since the ref_count flags was set when we 2640165220Srrs * did not find the TCB, now we found it 2641165220Srrs * which reduces the refcount.. we must 2642165220Srrs * raise it back out to balance it all :-) 2643165220Srrs */ 2644165220Srrs SCTP_INP_INCR_REF((*stcb)->sctp_ep); 2645165220Srrs if ((*stcb)->sctp_ep != l_inp) { 2646169420Srrs SCTP_PRINTF("Huh? ep:%p diff then l_inp:%p?\n", 2647240148Stuexen (void *)(*stcb)->sctp_ep, (void *)l_inp); 2648165220Srrs } 2649165220Srrs } 2650163953Srrs } 2651163953Srrs } 2652188067Srrs if (to == NULL) { 2653169420Srrs return (NULL); 2654188067Srrs } 2655163953Srrs cookie_len -= SCTP_SIGNATURE_SIZE; 2656163953Srrs if (*stcb == NULL) { 2657163953Srrs /* this is the "normal" case... get a new TCB */ 2658237715Stuexen *stcb = sctp_process_cookie_new(m, iphlen, offset, src, dst, sh, 2659237715Stuexen cookie, cookie_len, *inp_p, 2660237715Stuexen netp, to, ¬ification, 2661237049Stuexen auth_skipped, auth_offset, auth_len, 2662237049Stuexen use_mflowid, mflowid, 2663237049Stuexen vrf_id, port); 2664163953Srrs } else { 2665163953Srrs /* this is abnormal... cookie-echo on existing TCB */ 2666163953Srrs had_a_existing_tcb = 1; 2667237715Stuexen *stcb = sctp_process_cookie_existing(m, iphlen, offset, 2668237715Stuexen src, dst, sh, 2669185694Srrs cookie, cookie_len, *inp_p, *stcb, netp, to, 2670237049Stuexen ¬ification, auth_skipped, auth_offset, auth_len, 2671237049Stuexen use_mflowid, mflowid, 2672237049Stuexen vrf_id, port); 2673163953Srrs } 2674163953Srrs 2675163953Srrs if (*stcb == NULL) { 2676163953Srrs /* still no TCB... must be bad cookie-echo */ 2677163953Srrs return (NULL); 2678163953Srrs } 2679237049Stuexen if ((*netp != NULL) && (use_mflowid != 0)) { 2680237049Stuexen (*netp)->flowid = mflowid; 2681218400Stuexen#ifdef INVARIANTS 2682218392Srrs (*netp)->flowidset = 1; 2683218400Stuexen#endif 2684218335Stuexen } 2685163953Srrs /* 2686163953Srrs * Ok, we built an association so confirm the address we sent the 2687163953Srrs * INIT-ACK to. 2688163953Srrs */ 2689163953Srrs netl = sctp_findnet(*stcb, to); 2690163953Srrs /* 2691163953Srrs * This code should in theory NOT run but 2692163953Srrs */ 2693163953Srrs if (netl == NULL) { 2694163953Srrs /* TSNH! Huh, why do I need to add this address here? */ 2695228907Stuexen if (sctp_add_remote_addr(*stcb, to, NULL, SCTP_DONOT_SETSCOPE, SCTP_IN_COOKIE_PROC)) { 2696228907Stuexen return (NULL); 2697228907Stuexen } 2698163953Srrs netl = sctp_findnet(*stcb, to); 2699163953Srrs } 2700163953Srrs if (netl) { 2701163953Srrs if (netl->dest_state & SCTP_ADDR_UNCONFIRMED) { 2702163953Srrs netl->dest_state &= ~SCTP_ADDR_UNCONFIRMED; 2703169420Srrs (void)sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL, 2704163953Srrs netl); 2705216887Stuexen send_int_conf = 1; 2706163953Srrs } 2707163953Srrs } 2708224641Stuexen sctp_start_net_timers(*stcb); 2709163953Srrs if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) { 2710163953Srrs if (!had_a_existing_tcb || 2711163953Srrs (((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) { 2712163953Srrs /* 2713163953Srrs * If we have a NEW cookie or the connect never 2714163953Srrs * reached the connected state during collision we 2715163953Srrs * must do the TCP accept thing. 2716163953Srrs */ 2717163953Srrs struct socket *so, *oso; 2718163953Srrs struct sctp_inpcb *inp; 2719163953Srrs 2720163953Srrs if (notification == SCTP_NOTIFY_ASSOC_RESTART) { 2721163953Srrs /* 2722163953Srrs * For a restart we will keep the same 2723163953Srrs * socket, no need to do anything. I THINK!! 2724163953Srrs */ 2725228653Stuexen sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2726216887Stuexen if (send_int_conf) { 2727216887Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2728216887Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2729216887Stuexen } 2730163953Srrs return (m); 2731163953Srrs } 2732163953Srrs oso = (*inp_p)->sctp_socket; 2733171858Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2734163953Srrs SCTP_TCB_UNLOCK((*stcb)); 2735218757Sbz CURVNET_SET(oso->so_vnet); 2736166086Srrs so = sonewconn(oso, 0 2737163953Srrs ); 2738218757Sbz CURVNET_RESTORE(); 2739163953Srrs SCTP_TCB_LOCK((*stcb)); 2740171858Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2741171858Srrs 2742163953Srrs if (so == NULL) { 2743163953Srrs struct mbuf *op_err; 2744163953Srrs 2745237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2746172090Srrs struct socket *pcb_so; 2747172090Srrs 2748172090Srrs#endif 2749163953Srrs /* Too many sockets */ 2750169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n"); 2751267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 2752163953Srrs sctp_abort_association(*inp_p, NULL, m, iphlen, 2753237715Stuexen src, dst, sh, op_err, 2754237049Stuexen use_mflowid, mflowid, 2755237049Stuexen vrf_id, port); 2756237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2757172090Srrs pcb_so = SCTP_INP_SO(*inp_p); 2758172090Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2759172090Srrs SCTP_TCB_UNLOCK((*stcb)); 2760172090Srrs SCTP_SOCKET_LOCK(pcb_so, 1); 2761172090Srrs SCTP_TCB_LOCK((*stcb)); 2762172090Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2763172090Srrs#endif 2764171943Srrs (void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_20); 2765237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2766172090Srrs SCTP_SOCKET_UNLOCK(pcb_so, 1); 2767172090Srrs#endif 2768163953Srrs return (NULL); 2769163953Srrs } 2770163953Srrs inp = (struct sctp_inpcb *)so->so_pcb; 2771166086Srrs SCTP_INP_INCR_REF(inp); 2772166086Srrs /* 2773166086Srrs * We add the unbound flag here so that if we get an 2774166086Srrs * soabort() before we get the move_pcb done, we 2775166086Srrs * will properly cleanup. 2776166086Srrs */ 2777163953Srrs inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | 2778163953Srrs SCTP_PCB_FLAGS_CONNECTED | 2779163953Srrs SCTP_PCB_FLAGS_IN_TCPPOOL | 2780166086Srrs SCTP_PCB_FLAGS_UNBOUND | 2781163953Srrs (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) | 2782163953Srrs SCTP_PCB_FLAGS_DONT_WAKE); 2783163953Srrs inp->sctp_features = (*inp_p)->sctp_features; 2784172091Srrs inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features; 2785163953Srrs inp->sctp_socket = so; 2786163953Srrs inp->sctp_frag_point = (*inp_p)->sctp_frag_point; 2787211944Stuexen inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off; 2788218235Stuexen inp->sctp_ecn_enable = (*inp_p)->sctp_ecn_enable; 2789163953Srrs inp->partial_delivery_point = (*inp_p)->partial_delivery_point; 2790163953Srrs inp->sctp_context = (*inp_p)->sctp_context; 2791233660Srrs inp->local_strreset_support = (*inp_p)->local_strreset_support; 2792163953Srrs inp->inp_starting_point_for_iterator = NULL; 2793163953Srrs /* 2794163953Srrs * copy in the authentication parameters from the 2795163953Srrs * original endpoint 2796163953Srrs */ 2797163953Srrs if (inp->sctp_ep.local_hmacs) 2798163953Srrs sctp_free_hmaclist(inp->sctp_ep.local_hmacs); 2799163953Srrs inp->sctp_ep.local_hmacs = 2800163953Srrs sctp_copy_hmaclist((*inp_p)->sctp_ep.local_hmacs); 2801163953Srrs if (inp->sctp_ep.local_auth_chunks) 2802163953Srrs sctp_free_chunklist(inp->sctp_ep.local_auth_chunks); 2803163953Srrs inp->sctp_ep.local_auth_chunks = 2804163953Srrs sctp_copy_chunklist((*inp_p)->sctp_ep.local_auth_chunks); 2805163953Srrs 2806163953Srrs /* 2807163953Srrs * Now we must move it from one hash table to 2808163953Srrs * another and get the tcb in the right place. 2809163953Srrs */ 2810207924Srrs 2811207924Srrs /* 2812207924Srrs * This is where the one-2-one socket is put into 2813207924Srrs * the accept state waiting for the accept! 2814207924Srrs */ 2815207924Srrs if (*stcb) { 2816207924Srrs (*stcb)->asoc.state |= SCTP_STATE_IN_ACCEPT_QUEUE; 2817207924Srrs } 2818163953Srrs sctp_move_pcb_and_assoc(*inp_p, inp, *stcb); 2819170056Srrs 2820170056Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2821170056Srrs SCTP_TCB_UNLOCK((*stcb)); 2822170056Srrs 2823175845Srwatson sctp_pull_off_control_to_new_inp((*inp_p), inp, *stcb, 2824175845Srwatson 0); 2825170056Srrs SCTP_TCB_LOCK((*stcb)); 2826170056Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2827163953Srrs 2828170056Srrs 2829166086Srrs /* 2830166086Srrs * now we must check to see if we were aborted while 2831166086Srrs * the move was going on and the lock/unlock 2832166086Srrs * happened. 2833166086Srrs */ 2834166086Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 2835166086Srrs /* 2836166086Srrs * yep it was, we leave the assoc attached 2837166086Srrs * to the socket since the sctp_inpcb_free() 2838166086Srrs * call will send an abort for us. 2839166086Srrs */ 2840166086Srrs SCTP_INP_DECR_REF(inp); 2841166086Srrs return (NULL); 2842166086Srrs } 2843166086Srrs SCTP_INP_DECR_REF(inp); 2844163953Srrs /* Switch over to the new guy */ 2845163953Srrs *inp_p = inp; 2846172090Srrs sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2847216887Stuexen if (send_int_conf) { 2848216887Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2849216887Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2850216887Stuexen } 2851166086Srrs /* 2852166086Srrs * Pull it from the incomplete queue and wake the 2853166086Srrs * guy 2854166086Srrs */ 2855237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2856172090Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2857172090Srrs SCTP_TCB_UNLOCK((*stcb)); 2858172090Srrs SCTP_SOCKET_LOCK(so, 1); 2859172090Srrs#endif 2860166086Srrs soisconnected(so); 2861237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2862172118Srrs SCTP_TCB_LOCK((*stcb)); 2863172118Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2864172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2865172090Srrs#endif 2866163953Srrs return (m); 2867163953Srrs } 2868163953Srrs } 2869238454Stuexen if (notification) { 2870238454Stuexen sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2871163953Srrs } 2872238454Stuexen if (send_int_conf) { 2873238454Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2874238454Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2875238454Stuexen } 2876163953Srrs return (m); 2877163953Srrs} 2878163953Srrs 2879163953Srrsstatic void 2880228653Stuexensctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED, 2881163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 2882163953Srrs{ 2883163953Srrs /* cp must not be used, others call this without a c-ack :-) */ 2884163953Srrs struct sctp_association *asoc; 2885163953Srrs 2886169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2887169420Srrs "sctp_handle_cookie_ack: handling COOKIE-ACK\n"); 2888163953Srrs if (stcb == NULL) 2889163953Srrs return; 2890163953Srrs 2891163953Srrs asoc = &stcb->asoc; 2892163953Srrs 2893163953Srrs sctp_stop_all_cookie_timers(stcb); 2894163953Srrs /* process according to association state */ 2895163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 2896163953Srrs /* state change only needed when I am in right state */ 2897169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 2898171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 2899224641Stuexen sctp_start_net_timers(stcb); 2900163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 2901163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 2902163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 2903163953Srrs 2904163953Srrs } 2905163953Srrs /* update RTO */ 2906163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 2907163953Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 2908163953Srrs if (asoc->overall_error_count == 0) { 2909163953Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, 2910218186Srrs &asoc->time_entered, sctp_align_safe_nocopy, 2911219397Srrs SCTP_RTT_FROM_NON_DATA); 2912163953Srrs } 2913169378Srrs (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 2914172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2915163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2916163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 2917237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2918172090Srrs struct socket *so; 2919172090Srrs 2920172090Srrs#endif 2921163953Srrs stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 2922237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2923172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 2924172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2925172090Srrs SCTP_TCB_UNLOCK(stcb); 2926172090Srrs SCTP_SOCKET_LOCK(so, 1); 2927172090Srrs SCTP_TCB_LOCK(stcb); 2928172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2929218641Srrs#endif 2930218641Srrs if ((stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) == 0) { 2931218641Srrs soisconnected(stcb->sctp_socket); 2932172090Srrs } 2933237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2934172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2935172090Srrs#endif 2936163953Srrs } 2937163953Srrs /* 2938163953Srrs * since we did not send a HB make sure we don't double 2939163953Srrs * things 2940163953Srrs */ 2941163953Srrs net->hb_responded = 1; 2942163953Srrs 2943218641Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 2944218641Srrs /* 2945218641Srrs * We don't need to do the asconf thing, nor hb or 2946218641Srrs * autoclose if the socket is closed. 2947218641Srrs */ 2948218641Srrs goto closed_socket; 2949218641Srrs } 2950218641Srrs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, 2951218641Srrs stcb, net); 2952218641Srrs 2953218641Srrs 2954163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 2955163953Srrs sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTOCLOSE)) { 2956163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 2957163953Srrs stcb->sctp_ep, stcb, NULL); 2958163953Srrs } 2959163953Srrs /* 2960171572Srrs * send ASCONF if parameters are pending and ASCONFs are 2961171572Srrs * allowed (eg. addresses changed when init/cookie echo were 2962171572Srrs * in flight) 2963163953Srrs */ 2964163953Srrs if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) && 2965163953Srrs (stcb->asoc.peer_supports_asconf) && 2966163953Srrs (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) { 2967171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 2968163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 2969163953Srrs stcb->sctp_ep, stcb, 2970163953Srrs stcb->asoc.primary_destination); 2971171572Srrs#else 2972172190Srrs sctp_send_asconf(stcb, stcb->asoc.primary_destination, 2973172190Srrs SCTP_ADDR_NOT_LOCKED); 2974171572Srrs#endif 2975163953Srrs } 2976163953Srrs } 2977218641Srrsclosed_socket: 2978163953Srrs /* Toss the cookie if I can */ 2979163953Srrs sctp_toss_old_cookies(stcb, asoc); 2980163953Srrs if (!TAILQ_EMPTY(&asoc->sent_queue)) { 2981163953Srrs /* Restart the timer if we have pending data */ 2982163953Srrs struct sctp_tmit_chunk *chk; 2983163953Srrs 2984163953Srrs chk = TAILQ_FIRST(&asoc->sent_queue); 2985216822Stuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 2986163953Srrs } 2987163953Srrs} 2988163953Srrs 2989163953Srrsstatic void 2990163953Srrssctp_handle_ecn_echo(struct sctp_ecne_chunk *cp, 2991163953Srrs struct sctp_tcb *stcb) 2992163953Srrs{ 2993163953Srrs struct sctp_nets *net; 2994163953Srrs struct sctp_tmit_chunk *lchk; 2995218072Srrs struct sctp_ecne_chunk bkup; 2996228907Stuexen uint8_t override_bit; 2997218072Srrs uint32_t tsn, window_data_tsn; 2998218072Srrs int len; 2999218232Srrs unsigned int pkt_cnt; 3000163953Srrs 3001218072Srrs len = ntohs(cp->ch.chunk_length); 3002218072Srrs if ((len != sizeof(struct sctp_ecne_chunk)) && 3003218072Srrs (len != sizeof(struct old_sctp_ecne_chunk))) { 3004163953Srrs return; 3005163953Srrs } 3006218072Srrs if (len == sizeof(struct old_sctp_ecne_chunk)) { 3007218072Srrs /* Its the old format */ 3008218072Srrs memcpy(&bkup, cp, sizeof(struct old_sctp_ecne_chunk)); 3009218072Srrs bkup.num_pkts_since_cwr = htonl(1); 3010218072Srrs cp = &bkup; 3011218072Srrs } 3012163953Srrs SCTP_STAT_INCR(sctps_recvecne); 3013163953Srrs tsn = ntohl(cp->tsn); 3014218072Srrs pkt_cnt = ntohl(cp->num_pkts_since_cwr); 3015218072Srrs lchk = TAILQ_LAST(&stcb->asoc.send_queue, sctpchunk_listhead); 3016163953Srrs if (lchk == NULL) { 3017218129Srrs window_data_tsn = stcb->asoc.sending_seq - 1; 3018163953Srrs } else { 3019218129Srrs window_data_tsn = lchk->rec.data.TSN_seq; 3020163953Srrs } 3021163953Srrs 3022218072Srrs /* Find where it was sent to if possible. */ 3023163953Srrs net = NULL; 3024216822Stuexen TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) { 3025163953Srrs if (lchk->rec.data.TSN_seq == tsn) { 3026163953Srrs net = lchk->whoTo; 3027218186Srrs net->ecn_prev_cwnd = lchk->rec.data.cwnd_at_send; 3028163953Srrs break; 3029163953Srrs } 3030216825Stuexen if (SCTP_TSN_GT(lchk->rec.data.TSN_seq, tsn)) { 3031163953Srrs break; 3032216825Stuexen } 3033163953Srrs } 3034218072Srrs if (net == NULL) { 3035163953Srrs /* 3036218072Srrs * What to do. A previous send of a CWR was possibly lost. 3037218072Srrs * See how old it is, we may have it marked on the actual 3038218072Srrs * net. 3039218072Srrs */ 3040218072Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 3041218072Srrs if (tsn == net->last_cwr_tsn) { 3042218072Srrs /* Found him, send it off */ 3043228907Stuexen break; 3044218072Srrs } 3045218072Srrs } 3046228907Stuexen if (net == NULL) { 3047228907Stuexen /* 3048228907Stuexen * If we reach here, we need to send a special CWR 3049228907Stuexen * that says hey, we did this a long time ago and 3050228907Stuexen * you lost the response. 3051228907Stuexen */ 3052228907Stuexen net = TAILQ_FIRST(&stcb->asoc.nets); 3053228907Stuexen if (net == NULL) { 3054228907Stuexen /* TSNH */ 3055228907Stuexen return; 3056228907Stuexen } 3057228907Stuexen override_bit = SCTP_CWR_REDUCE_OVERRIDE; 3058228907Stuexen } else { 3059228907Stuexen override_bit = 0; 3060228907Stuexen } 3061228907Stuexen } else { 3062228907Stuexen override_bit = 0; 3063218072Srrs } 3064218129Srrs if (SCTP_TSN_GT(tsn, net->cwr_window_tsn) && 3065218129Srrs ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 3066218072Srrs /* 3067171440Srrs * JRS - Use the congestion control given in the pluggable 3068171440Srrs * CC module 3069171440Srrs */ 3070218129Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 0, pkt_cnt); 3071171440Srrs /* 3072218072Srrs * We reduce once every RTT. So we will only lower cwnd at 3073218072Srrs * the next sending seq i.e. the window_data_tsn 3074163953Srrs */ 3075218072Srrs net->cwr_window_tsn = window_data_tsn; 3076218072Srrs net->ecn_ce_pkt_cnt += pkt_cnt; 3077218072Srrs net->lost_cnt = pkt_cnt; 3078218072Srrs net->last_cwr_tsn = tsn; 3079218072Srrs } else { 3080218072Srrs override_bit |= SCTP_CWR_IN_SAME_WINDOW; 3081218129Srrs if (SCTP_TSN_GT(tsn, net->last_cwr_tsn) && 3082218129Srrs ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 3083218072Srrs /* 3084218129Srrs * Another loss in the same window update how many 3085218129Srrs * marks/packets lost we have had. 3086218072Srrs */ 3087218129Srrs int cnt = 1; 3088218072Srrs 3089218072Srrs if (pkt_cnt > net->lost_cnt) { 3090218072Srrs /* Should be the case */ 3091218129Srrs cnt = (pkt_cnt - net->lost_cnt); 3092218129Srrs net->ecn_ce_pkt_cnt += cnt; 3093218072Srrs } 3094218129Srrs net->lost_cnt = pkt_cnt; 3095218072Srrs net->last_cwr_tsn = tsn; 3096218129Srrs /* 3097218129Srrs * Most CC functions will ignore this call, since we 3098218129Srrs * are in-window yet of the initial CE the peer saw. 3099218129Srrs */ 3100218129Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 1, cnt); 3101218072Srrs } 3102163953Srrs } 3103163953Srrs /* 3104163953Srrs * We always send a CWR this way if our previous one was lost our 3105163953Srrs * peer will get an update, or if it is not time again to reduce we 3106218072Srrs * still get the cwr to the peer. Note we set the override when we 3107218072Srrs * could not find the TSN on the chunk or the destination network. 3108163953Srrs */ 3109218072Srrs sctp_send_cwr(stcb, net, net->last_cwr_tsn, override_bit); 3110163953Srrs} 3111163953Srrs 3112163953Srrsstatic void 3113218072Srrssctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sctp_nets *net) 3114163953Srrs{ 3115163953Srrs /* 3116163953Srrs * Here we get a CWR from the peer. We must look in the outqueue and 3117240520Seadler * make sure that we have a covered ECNE in the control chunk part. 3118163953Srrs * If so remove it. 3119163953Srrs */ 3120163953Srrs struct sctp_tmit_chunk *chk; 3121163953Srrs struct sctp_ecne_chunk *ecne; 3122218072Srrs int override; 3123218072Srrs uint32_t cwr_tsn; 3124163953Srrs 3125218072Srrs cwr_tsn = ntohl(cp->tsn); 3126218072Srrs 3127218072Srrs override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE; 3128163953Srrs TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 3129163953Srrs if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) { 3130163953Srrs continue; 3131163953Srrs } 3132218072Srrs if ((override == 0) && (chk->whoTo != net)) { 3133218072Srrs /* Must be from the right src unless override is set */ 3134218072Srrs continue; 3135218072Srrs } 3136163953Srrs ecne = mtod(chk->data, struct sctp_ecne_chunk *); 3137218072Srrs if (SCTP_TSN_GE(cwr_tsn, ntohl(ecne->tsn))) { 3138163953Srrs /* this covers this ECNE, we can remove it */ 3139163953Srrs stcb->asoc.ecn_echo_cnt_onq--; 3140163953Srrs TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk, 3141163953Srrs sctp_next); 3142163953Srrs if (chk->data) { 3143163953Srrs sctp_m_freem(chk->data); 3144163953Srrs chk->data = NULL; 3145163953Srrs } 3146163953Srrs stcb->asoc.ctrl_queue_cnt--; 3147221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 3148218072Srrs if (override == 0) { 3149218072Srrs break; 3150218072Srrs } 3151163953Srrs } 3152163953Srrs } 3153163953Srrs} 3154163953Srrs 3155163953Srrsstatic void 3156228653Stuexensctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSED, 3157163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 3158163953Srrs{ 3159163953Srrs struct sctp_association *asoc; 3160163953Srrs 3161237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3162172090Srrs struct socket *so; 3163172090Srrs 3164172090Srrs#endif 3165172090Srrs 3166169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3167169420Srrs "sctp_handle_shutdown_complete: handling SHUTDOWN-COMPLETE\n"); 3168163953Srrs if (stcb == NULL) 3169163953Srrs return; 3170163953Srrs 3171163953Srrs asoc = &stcb->asoc; 3172163953Srrs /* process according to association state */ 3173163953Srrs if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) { 3174163953Srrs /* unexpected SHUTDOWN-COMPLETE... so ignore... */ 3175171990Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3176171990Srrs "sctp_handle_shutdown_complete: not in SCTP_STATE_SHUTDOWN_ACK_SENT --- ignore\n"); 3177163953Srrs SCTP_TCB_UNLOCK(stcb); 3178163953Srrs return; 3179163953Srrs } 3180163953Srrs /* notify upper layer protocol */ 3181163953Srrs if (stcb->sctp_socket) { 3182172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 3183163953Srrs } 3184252585Stuexen#ifdef INVARIANTS 3185252585Stuexen if (!TAILQ_EMPTY(&asoc->send_queue) || 3186252585Stuexen !TAILQ_EMPTY(&asoc->sent_queue) || 3187252585Stuexen !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 3188252585Stuexen panic("Queues are not empty when handling SHUTDOWN-COMPLETE"); 3189252585Stuexen } 3190252585Stuexen#endif 3191163953Srrs /* stop the timer */ 3192178202Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_22); 3193163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 3194163953Srrs /* free the TCB */ 3195171990Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3196171990Srrs "sctp_handle_shutdown_complete: calls free-asoc\n"); 3197237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3198172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 3199172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 3200172090Srrs SCTP_TCB_UNLOCK(stcb); 3201172090Srrs SCTP_SOCKET_LOCK(so, 1); 3202172090Srrs SCTP_TCB_LOCK(stcb); 3203172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 3204172090Srrs#endif 3205171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_23); 3206237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3207172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 3208172090Srrs#endif 3209163953Srrs return; 3210163953Srrs} 3211163953Srrs 3212163953Srrsstatic int 3213163953Srrsprocess_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, 3214163953Srrs struct sctp_nets *net, uint8_t flg) 3215163953Srrs{ 3216163953Srrs switch (desc->chunk_type) { 3217211969Stuexen case SCTP_DATA: 3218163953Srrs /* find the tsn to resend (possibly */ 3219163953Srrs { 3220163953Srrs uint32_t tsn; 3221163953Srrs struct sctp_tmit_chunk *tp1; 3222163953Srrs 3223163953Srrs tsn = ntohl(desc->tsn_ifany); 3224216822Stuexen TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3225163953Srrs if (tp1->rec.data.TSN_seq == tsn) { 3226163953Srrs /* found it */ 3227163953Srrs break; 3228163953Srrs } 3229216825Stuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, tsn)) { 3230163953Srrs /* not found */ 3231163953Srrs tp1 = NULL; 3232163953Srrs break; 3233163953Srrs } 3234163953Srrs } 3235163953Srrs if (tp1 == NULL) { 3236163953Srrs /* 3237163953Srrs * Do it the other way , aka without paying 3238163953Srrs * attention to queue seq order. 3239163953Srrs */ 3240163953Srrs SCTP_STAT_INCR(sctps_pdrpdnfnd); 3241216822Stuexen TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3242163953Srrs if (tp1->rec.data.TSN_seq == tsn) { 3243163953Srrs /* found it */ 3244163953Srrs break; 3245163953Srrs } 3246163953Srrs } 3247163953Srrs } 3248163953Srrs if (tp1 == NULL) { 3249163953Srrs SCTP_STAT_INCR(sctps_pdrptsnnf); 3250163953Srrs } 3251163953Srrs if ((tp1) && (tp1->sent < SCTP_DATAGRAM_ACKED)) { 3252163953Srrs uint8_t *ddp; 3253163953Srrs 3254214877Stuexen if (((flg & SCTP_BADCRC) == 0) && 3255214877Stuexen ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 3256214877Stuexen return (0); 3257214877Stuexen } 3258163953Srrs if ((stcb->asoc.peers_rwnd == 0) && 3259163953Srrs ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 3260163953Srrs SCTP_STAT_INCR(sctps_pdrpdiwnp); 3261163953Srrs return (0); 3262163953Srrs } 3263163953Srrs if (stcb->asoc.peers_rwnd == 0 && 3264163953Srrs (flg & SCTP_FROM_MIDDLE_BOX)) { 3265163953Srrs SCTP_STAT_INCR(sctps_pdrpdizrw); 3266163953Srrs return (0); 3267163953Srrs } 3268163953Srrs ddp = (uint8_t *) (mtod(tp1->data, caddr_t)+ 3269163953Srrs sizeof(struct sctp_data_chunk)); 3270163953Srrs { 3271163953Srrs unsigned int iii; 3272163953Srrs 3273163953Srrs for (iii = 0; iii < sizeof(desc->data_bytes); 3274163953Srrs iii++) { 3275163953Srrs if (ddp[iii] != desc->data_bytes[iii]) { 3276163953Srrs SCTP_STAT_INCR(sctps_pdrpbadd); 3277163953Srrs return (-1); 3278163953Srrs } 3279163953Srrs } 3280163953Srrs } 3281163953Srrs 3282163953Srrs if (tp1->do_rtt) { 3283163953Srrs /* 3284163953Srrs * this guy had a RTO calculation 3285163953Srrs * pending on it, cancel it 3286163953Srrs */ 3287219397Srrs if (tp1->whoTo->rto_needed == 0) { 3288219397Srrs tp1->whoTo->rto_needed = 1; 3289219397Srrs } 3290163953Srrs tp1->do_rtt = 0; 3291163953Srrs } 3292163953Srrs SCTP_STAT_INCR(sctps_pdrpmark); 3293163953Srrs if (tp1->sent != SCTP_DATAGRAM_RESEND) 3294163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3295163953Srrs /* 3296163953Srrs * mark it as if we were doing a FR, since 3297163953Srrs * we will be getting gap ack reports behind 3298163953Srrs * the info from the router. 3299163953Srrs */ 3300163953Srrs tp1->rec.data.doing_fast_retransmit = 1; 3301163953Srrs /* 3302163953Srrs * mark the tsn with what sequences can 3303163953Srrs * cause a new FR. 3304163953Srrs */ 3305163953Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue)) { 3306163953Srrs tp1->rec.data.fast_retran_tsn = stcb->asoc.sending_seq; 3307163953Srrs } else { 3308163953Srrs tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq; 3309163953Srrs } 3310163953Srrs 3311163953Srrs /* restart the timer */ 3312163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 3313171440Srrs stcb, tp1->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_24); 3314163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 3315163953Srrs stcb, tp1->whoTo); 3316163953Srrs 3317163953Srrs /* fix counts and things */ 3318179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 3319170744Srrs sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP, 3320170744Srrs tp1->whoTo->flight_size, 3321170744Srrs tp1->book_size, 3322170744Srrs (uintptr_t) stcb, 3323170744Srrs tp1->rec.data.TSN_seq); 3324170744Srrs } 3325190689Srrs if (tp1->sent < SCTP_DATAGRAM_RESEND) { 3326190689Srrs sctp_flight_size_decrease(tp1); 3327190689Srrs sctp_total_flight_decrease(stcb, tp1); 3328190689Srrs } 3329216502Stuexen tp1->sent = SCTP_DATAGRAM_RESEND; 3330163953Srrs } { 3331163953Srrs /* audit code */ 3332163953Srrs unsigned int audit; 3333163953Srrs 3334163953Srrs audit = 0; 3335163953Srrs TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3336163953Srrs if (tp1->sent == SCTP_DATAGRAM_RESEND) 3337163953Srrs audit++; 3338163953Srrs } 3339163953Srrs TAILQ_FOREACH(tp1, &stcb->asoc.control_send_queue, 3340163953Srrs sctp_next) { 3341163953Srrs if (tp1->sent == SCTP_DATAGRAM_RESEND) 3342163953Srrs audit++; 3343163953Srrs } 3344163953Srrs if (audit != stcb->asoc.sent_queue_retran_cnt) { 3345169420Srrs SCTP_PRINTF("**Local Audit finds cnt:%d asoc cnt:%d\n", 3346163953Srrs audit, stcb->asoc.sent_queue_retran_cnt); 3347163953Srrs#ifndef SCTP_AUDITING_ENABLED 3348163953Srrs stcb->asoc.sent_queue_retran_cnt = audit; 3349163953Srrs#endif 3350163953Srrs } 3351163953Srrs } 3352163953Srrs } 3353163953Srrs break; 3354163953Srrs case SCTP_ASCONF: 3355163953Srrs { 3356163953Srrs struct sctp_tmit_chunk *asconf; 3357163953Srrs 3358163953Srrs TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue, 3359163953Srrs sctp_next) { 3360163953Srrs if (asconf->rec.chunk_id.id == SCTP_ASCONF) { 3361163953Srrs break; 3362163953Srrs } 3363163953Srrs } 3364163953Srrs if (asconf) { 3365163953Srrs if (asconf->sent != SCTP_DATAGRAM_RESEND) 3366163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3367163953Srrs asconf->sent = SCTP_DATAGRAM_RESEND; 3368163953Srrs asconf->snd_count--; 3369163953Srrs } 3370163953Srrs } 3371163953Srrs break; 3372163953Srrs case SCTP_INITIATION: 3373163953Srrs /* resend the INIT */ 3374163953Srrs stcb->asoc.dropped_special_cnt++; 3375163953Srrs if (stcb->asoc.dropped_special_cnt < SCTP_RETRY_DROPPED_THRESH) { 3376163953Srrs /* 3377163953Srrs * If we can get it in, in a few attempts we do 3378163953Srrs * this, otherwise we let the timer fire. 3379163953Srrs */ 3380163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, 3381171440Srrs stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_25); 3382172090Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 3383163953Srrs } 3384163953Srrs break; 3385163953Srrs case SCTP_SELECTIVE_ACK: 3386206137Stuexen case SCTP_NR_SELECTIVE_ACK: 3387163953Srrs /* resend the sack */ 3388221627Stuexen sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 3389163953Srrs break; 3390163953Srrs case SCTP_HEARTBEAT_REQUEST: 3391163953Srrs /* resend a demand HB */ 3392171440Srrs if ((stcb->asoc.overall_error_count + 3) < stcb->asoc.max_send_times) { 3393171440Srrs /* 3394171440Srrs * Only retransmit if we KNOW we wont destroy the 3395171440Srrs * tcb 3396171440Srrs */ 3397224641Stuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 3398171440Srrs } 3399163953Srrs break; 3400163953Srrs case SCTP_SHUTDOWN: 3401163953Srrs sctp_send_shutdown(stcb, net); 3402163953Srrs break; 3403163953Srrs case SCTP_SHUTDOWN_ACK: 3404163953Srrs sctp_send_shutdown_ack(stcb, net); 3405163953Srrs break; 3406163953Srrs case SCTP_COOKIE_ECHO: 3407163953Srrs { 3408163953Srrs struct sctp_tmit_chunk *cookie; 3409163953Srrs 3410163953Srrs cookie = NULL; 3411163953Srrs TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, 3412163953Srrs sctp_next) { 3413163953Srrs if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) { 3414163953Srrs break; 3415163953Srrs } 3416163953Srrs } 3417163953Srrs if (cookie) { 3418163953Srrs if (cookie->sent != SCTP_DATAGRAM_RESEND) 3419163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3420163953Srrs cookie->sent = SCTP_DATAGRAM_RESEND; 3421163953Srrs sctp_stop_all_cookie_timers(stcb); 3422163953Srrs } 3423163953Srrs } 3424163953Srrs break; 3425163953Srrs case SCTP_COOKIE_ACK: 3426163953Srrs sctp_send_cookie_ack(stcb); 3427163953Srrs break; 3428163953Srrs case SCTP_ASCONF_ACK: 3429163953Srrs /* resend last asconf ack */ 3430171990Srrs sctp_send_asconf_ack(stcb); 3431163953Srrs break; 3432163953Srrs case SCTP_FORWARD_CUM_TSN: 3433163953Srrs send_forward_tsn(stcb, &stcb->asoc); 3434163953Srrs break; 3435163953Srrs /* can't do anything with these */ 3436163953Srrs case SCTP_PACKET_DROPPED: 3437163953Srrs case SCTP_INITIATION_ACK: /* this should not happen */ 3438163953Srrs case SCTP_HEARTBEAT_ACK: 3439163953Srrs case SCTP_ABORT_ASSOCIATION: 3440163953Srrs case SCTP_OPERATION_ERROR: 3441163953Srrs case SCTP_SHUTDOWN_COMPLETE: 3442163953Srrs case SCTP_ECN_ECHO: 3443163953Srrs case SCTP_ECN_CWR: 3444163953Srrs default: 3445163953Srrs break; 3446163953Srrs } 3447163953Srrs return (0); 3448163953Srrs} 3449163953Srrs 3450163953Srrsvoid 3451240198Stuexensctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list) 3452163953Srrs{ 3453240198Stuexen uint32_t i; 3454163953Srrs uint16_t temp; 3455163953Srrs 3456163953Srrs /* 3457163953Srrs * We set things to 0xffff since this is the last delivered sequence 3458163953Srrs * and we will be sending in 0 after the reset. 3459163953Srrs */ 3460163953Srrs 3461163953Srrs if (number_entries) { 3462163953Srrs for (i = 0; i < number_entries; i++) { 3463163953Srrs temp = ntohs(list[i]); 3464163953Srrs if (temp >= stcb->asoc.streamincnt) { 3465163953Srrs continue; 3466163953Srrs } 3467163953Srrs stcb->asoc.strmin[temp].last_sequence_delivered = 0xffff; 3468163953Srrs } 3469163953Srrs } else { 3470163953Srrs list = NULL; 3471163953Srrs for (i = 0; i < stcb->asoc.streamincnt; i++) { 3472163953Srrs stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 3473163953Srrs } 3474163953Srrs } 3475172090Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 3476163953Srrs} 3477163953Srrs 3478163953Srrsstatic void 3479252585Stuexensctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list) 3480163953Srrs{ 3481252585Stuexen uint32_t i; 3482252585Stuexen uint16_t temp; 3483163953Srrs 3484252585Stuexen if (number_entries > 0) { 3485163953Srrs for (i = 0; i < number_entries; i++) { 3486163953Srrs temp = ntohs(list[i]); 3487163953Srrs if (temp >= stcb->asoc.streamoutcnt) { 3488163953Srrs /* no such stream */ 3489163953Srrs continue; 3490163953Srrs } 3491242627Stuexen stcb->asoc.strmout[temp].next_sequence_send = 0; 3492163953Srrs } 3493252585Stuexen } else { 3494252585Stuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 3495252585Stuexen stcb->asoc.strmout[i].next_sequence_send = 0; 3496252585Stuexen } 3497163953Srrs } 3498172090Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 3499163953Srrs} 3500163953Srrs 3501163953Srrs 3502163953Srrsstruct sctp_stream_reset_out_request * 3503163953Srrssctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk) 3504163953Srrs{ 3505163953Srrs struct sctp_association *asoc; 3506240198Stuexen struct sctp_chunkhdr *ch; 3507163953Srrs struct sctp_stream_reset_out_request *r; 3508163953Srrs struct sctp_tmit_chunk *chk; 3509163953Srrs int len, clen; 3510163953Srrs 3511163953Srrs asoc = &stcb->asoc; 3512163953Srrs if (TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 3513169208Srrs asoc->stream_reset_outstanding = 0; 3514163953Srrs return (NULL); 3515163953Srrs } 3516163953Srrs if (stcb->asoc.str_reset == NULL) { 3517169208Srrs asoc->stream_reset_outstanding = 0; 3518163953Srrs return (NULL); 3519163953Srrs } 3520163953Srrs chk = stcb->asoc.str_reset; 3521163953Srrs if (chk->data == NULL) { 3522163953Srrs return (NULL); 3523163953Srrs } 3524163953Srrs if (bchk) { 3525163953Srrs /* he wants a copy of the chk pointer */ 3526163953Srrs *bchk = chk; 3527163953Srrs } 3528163953Srrs clen = chk->send_size; 3529240198Stuexen ch = mtod(chk->data, struct sctp_chunkhdr *); 3530240198Stuexen r = (struct sctp_stream_reset_out_request *)(ch + 1); 3531163953Srrs if (ntohl(r->request_seq) == seq) { 3532163953Srrs /* found it */ 3533163953Srrs return (r); 3534163953Srrs } 3535163953Srrs len = SCTP_SIZE32(ntohs(r->ph.param_length)); 3536163953Srrs if (clen > (len + (int)sizeof(struct sctp_chunkhdr))) { 3537163953Srrs /* move to the next one, there can only be a max of two */ 3538163953Srrs r = (struct sctp_stream_reset_out_request *)((caddr_t)r + len); 3539163953Srrs if (ntohl(r->request_seq) == seq) { 3540163953Srrs return (r); 3541163953Srrs } 3542163953Srrs } 3543163953Srrs /* that seq is not here */ 3544163953Srrs return (NULL); 3545163953Srrs} 3546163953Srrs 3547163953Srrsstatic void 3548163953Srrssctp_clean_up_stream_reset(struct sctp_tcb *stcb) 3549163953Srrs{ 3550163953Srrs struct sctp_association *asoc; 3551163953Srrs struct sctp_tmit_chunk *chk = stcb->asoc.str_reset; 3552163953Srrs 3553163953Srrs if (stcb->asoc.str_reset == NULL) { 3554163953Srrs return; 3555163953Srrs } 3556166675Srrs asoc = &stcb->asoc; 3557166675Srrs 3558171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_26); 3559163953Srrs TAILQ_REMOVE(&asoc->control_send_queue, 3560163953Srrs chk, 3561163953Srrs sctp_next); 3562163953Srrs if (chk->data) { 3563163953Srrs sctp_m_freem(chk->data); 3564163953Srrs chk->data = NULL; 3565163953Srrs } 3566163953Srrs asoc->ctrl_queue_cnt--; 3567221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 3568172156Srrs /* sa_ignore NO_NULL_CHK */ 3569163953Srrs stcb->asoc.str_reset = NULL; 3570163953Srrs} 3571163953Srrs 3572163953Srrs 3573163953Srrsstatic int 3574163953Srrssctp_handle_stream_reset_response(struct sctp_tcb *stcb, 3575163953Srrs uint32_t seq, uint32_t action, 3576164139Srrs struct sctp_stream_reset_response *respin) 3577163953Srrs{ 3578163953Srrs uint16_t type; 3579163953Srrs int lparm_len; 3580163953Srrs struct sctp_association *asoc = &stcb->asoc; 3581163953Srrs struct sctp_tmit_chunk *chk; 3582163953Srrs struct sctp_stream_reset_out_request *srparam; 3583252585Stuexen uint32_t number_entries; 3584163953Srrs 3585163953Srrs if (asoc->stream_reset_outstanding == 0) { 3586163953Srrs /* duplicate */ 3587163953Srrs return (0); 3588163953Srrs } 3589163953Srrs if (seq == stcb->asoc.str_reset_seq_out) { 3590163953Srrs srparam = sctp_find_stream_reset(stcb, seq, &chk); 3591163953Srrs if (srparam) { 3592163953Srrs stcb->asoc.str_reset_seq_out++; 3593163953Srrs type = ntohs(srparam->ph.param_type); 3594163953Srrs lparm_len = ntohs(srparam->ph.param_length); 3595163953Srrs if (type == SCTP_STR_RESET_OUT_REQUEST) { 3596164139Srrs number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t); 3597163953Srrs asoc->stream_reset_out_is_outstanding = 0; 3598163953Srrs if (asoc->stream_reset_outstanding) 3599163953Srrs asoc->stream_reset_outstanding--; 3600235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3601163953Srrs /* do it */ 3602163953Srrs sctp_reset_out_streams(stcb, number_entries, srparam->list_of_streams); 3603235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3604235066Stuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 3605163953Srrs } else { 3606172090Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 3607163953Srrs } 3608163953Srrs } else if (type == SCTP_STR_RESET_IN_REQUEST) { 3609163953Srrs /* Answered my request */ 3610164139Srrs number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t); 3611163953Srrs if (asoc->stream_reset_outstanding) 3612163953Srrs asoc->stream_reset_outstanding--; 3613235066Stuexen if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3614235066Stuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_IN, stcb, 3615235066Stuexen number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 3616235066Stuexen } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 3617233660Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb, 3618233660Srrs number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 3619163953Srrs } 3620233660Srrs } else if (type == SCTP_STR_RESET_ADD_OUT_STREAMS) { 3621188854Srrs /* Ok we now may have more streams */ 3622233660Srrs int num_stream; 3623233660Srrs 3624233660Srrs num_stream = stcb->asoc.strm_pending_add_size; 3625233660Srrs if (num_stream > (stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt)) { 3626233660Srrs /* TSNH */ 3627233660Srrs num_stream = stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt; 3628233660Srrs } 3629233660Srrs stcb->asoc.strm_pending_add_size = 0; 3630189121Srrs if (asoc->stream_reset_outstanding) 3631189121Srrs asoc->stream_reset_outstanding--; 3632235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3633188854Srrs /* Put the new streams into effect */ 3634233660Srrs stcb->asoc.streamoutcnt += num_stream; 3635233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 3636235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3637235066Stuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3638235066Stuexen SCTP_STREAM_CHANGE_DENIED); 3639188854Srrs } else { 3640233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3641235066Stuexen SCTP_STREAM_CHANGE_FAILED); 3642188854Srrs } 3643233660Srrs } else if (type == SCTP_STR_RESET_ADD_IN_STREAMS) { 3644233660Srrs if (asoc->stream_reset_outstanding) 3645233660Srrs asoc->stream_reset_outstanding--; 3646235066Stuexen if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3647233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3648235066Stuexen SCTP_STREAM_CHANGE_DENIED); 3649235066Stuexen } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 3650235066Stuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3651235066Stuexen SCTP_STREAM_CHANGE_FAILED); 3652233660Srrs } 3653163953Srrs } else if (type == SCTP_STR_RESET_TSN_REQUEST) { 3654163953Srrs /** 3655163953Srrs * a) Adopt the new in tsn. 3656163953Srrs * b) reset the map 3657163953Srrs * c) Adopt the new out-tsn 3658163953Srrs */ 3659163953Srrs struct sctp_stream_reset_response_tsn *resp; 3660163953Srrs struct sctp_forward_tsn_chunk fwdtsn; 3661163953Srrs int abort_flag = 0; 3662163953Srrs 3663163953Srrs if (respin == NULL) { 3664163953Srrs /* huh ? */ 3665163953Srrs return (0); 3666163953Srrs } 3667235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3668163953Srrs resp = (struct sctp_stream_reset_response_tsn *)respin; 3669163953Srrs asoc->stream_reset_outstanding--; 3670163953Srrs fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 3671163953Srrs fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 3672163953Srrs fwdtsn.new_cumulative_tsn = htonl(ntohl(resp->senders_next_tsn) - 1); 3673170992Srrs sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 3674163953Srrs if (abort_flag) { 3675163953Srrs return (1); 3676163953Srrs } 3677163953Srrs stcb->asoc.highest_tsn_inside_map = (ntohl(resp->senders_next_tsn) - 1); 3678179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 3679179783Srrs sctp_log_map(0, 7, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 3680179783Srrs } 3681180955Srrs stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map; 3682163953Srrs stcb->asoc.mapping_array_base_tsn = ntohl(resp->senders_next_tsn); 3683163953Srrs memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); 3684185694Srrs 3685205627Srrs stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; 3686206137Stuexen memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size); 3687205627Srrs 3688163953Srrs stcb->asoc.sending_seq = ntohl(resp->receivers_next_tsn); 3689163953Srrs stcb->asoc.last_acked_seq = stcb->asoc.cumulative_tsn; 3690163953Srrs 3691163953Srrs sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 3692163953Srrs sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 3693233660Srrs sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 0); 3694235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3695235066Stuexen sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 3696235066Stuexen SCTP_ASSOC_RESET_DENIED); 3697233660Srrs } else { 3698233660Srrs sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 3699235066Stuexen SCTP_ASSOC_RESET_FAILED); 3700163953Srrs } 3701163953Srrs } 3702163953Srrs /* get rid of the request and get the request flags */ 3703163953Srrs if (asoc->stream_reset_outstanding == 0) { 3704163953Srrs sctp_clean_up_stream_reset(stcb); 3705163953Srrs } 3706163953Srrs } 3707163953Srrs } 3708163953Srrs return (0); 3709163953Srrs} 3710163953Srrs 3711163953Srrsstatic void 3712163953Srrssctp_handle_str_reset_request_in(struct sctp_tcb *stcb, 3713163953Srrs struct sctp_tmit_chunk *chk, 3714170992Srrs struct sctp_stream_reset_in_request *req, int trunc) 3715163953Srrs{ 3716163953Srrs uint32_t seq; 3717163953Srrs int len, i; 3718163953Srrs int number_entries; 3719163953Srrs uint16_t temp; 3720163953Srrs 3721163953Srrs /* 3722163953Srrs * peer wants me to send a str-reset to him for my outgoing seq's if 3723163953Srrs * seq_in is right. 3724163953Srrs */ 3725163953Srrs struct sctp_association *asoc = &stcb->asoc; 3726163953Srrs 3727163953Srrs seq = ntohl(req->request_seq); 3728163953Srrs if (asoc->str_reset_seq_in == seq) { 3729235064Stuexen asoc->last_reset_action[1] = asoc->last_reset_action[0]; 3730235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 3731235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3732235064Stuexen } else if (trunc) { 3733170992Srrs /* Can't do it, since they exceeded our buffer size */ 3734235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3735170992Srrs } else if (stcb->asoc.stream_reset_out_is_outstanding == 0) { 3736163953Srrs len = ntohs(req->ph.param_length); 3737163953Srrs number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t)); 3738163953Srrs for (i = 0; i < number_entries; i++) { 3739163953Srrs temp = ntohs(req->list_of_streams[i]); 3740163953Srrs req->list_of_streams[i] = temp; 3741163953Srrs } 3742235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3743163953Srrs sctp_add_stream_reset_out(chk, number_entries, req->list_of_streams, 3744163953Srrs asoc->str_reset_seq_out, 3745163953Srrs seq, (asoc->sending_seq - 1)); 3746163953Srrs asoc->stream_reset_out_is_outstanding = 1; 3747163953Srrs asoc->str_reset = chk; 3748163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); 3749163953Srrs stcb->asoc.stream_reset_outstanding++; 3750163953Srrs } else { 3751163953Srrs /* Can't do it, since we have sent one out */ 3752235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 3753163953Srrs } 3754233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3755163953Srrs asoc->str_reset_seq_in++; 3756163953Srrs } else if (asoc->str_reset_seq_in - 1 == seq) { 3757163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3758163953Srrs } else if (asoc->str_reset_seq_in - 2 == seq) { 3759163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 3760163953Srrs } else { 3761235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3762163953Srrs } 3763163953Srrs} 3764163953Srrs 3765163953Srrsstatic int 3766163953Srrssctp_handle_str_reset_request_tsn(struct sctp_tcb *stcb, 3767163953Srrs struct sctp_tmit_chunk *chk, 3768163953Srrs struct sctp_stream_reset_tsn_request *req) 3769163953Srrs{ 3770163953Srrs /* reset all in and out and update the tsn */ 3771163953Srrs /* 3772163953Srrs * A) reset my str-seq's on in and out. B) Select a receive next, 3773163953Srrs * and set cum-ack to it. Also process this selected number as a 3774163953Srrs * fwd-tsn as well. C) set in the response my next sending seq. 3775163953Srrs */ 3776163953Srrs struct sctp_forward_tsn_chunk fwdtsn; 3777163953Srrs struct sctp_association *asoc = &stcb->asoc; 3778163953Srrs int abort_flag = 0; 3779163953Srrs uint32_t seq; 3780163953Srrs 3781163953Srrs seq = ntohl(req->request_seq); 3782163953Srrs if (asoc->str_reset_seq_in == seq) { 3783235283Stuexen asoc->last_reset_action[1] = stcb->asoc.last_reset_action[0]; 3784235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 3785235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3786235283Stuexen } else { 3787235064Stuexen fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 3788235283Stuexen fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 3789235283Stuexen fwdtsn.ch.chunk_flags = 0; 3790235283Stuexen fwdtsn.new_cumulative_tsn = htonl(stcb->asoc.highest_tsn_inside_map + 1); 3791235283Stuexen sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 3792235283Stuexen if (abort_flag) { 3793235283Stuexen return (1); 3794235283Stuexen } 3795235283Stuexen asoc->highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA; 3796235283Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 3797235283Stuexen sctp_log_map(0, 10, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 3798235283Stuexen } 3799235283Stuexen asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->highest_tsn_inside_map; 3800235283Stuexen asoc->mapping_array_base_tsn = asoc->highest_tsn_inside_map + 1; 3801235283Stuexen memset(asoc->mapping_array, 0, asoc->mapping_array_size); 3802235283Stuexen asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 3803235283Stuexen memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size); 3804235283Stuexen atomic_add_int(&asoc->sending_seq, 1); 3805235283Stuexen /* save off historical data for retrans */ 3806235283Stuexen asoc->last_sending_seq[1] = asoc->last_sending_seq[0]; 3807235283Stuexen asoc->last_sending_seq[0] = asoc->sending_seq; 3808235283Stuexen asoc->last_base_tsnsent[1] = asoc->last_base_tsnsent[0]; 3809235283Stuexen asoc->last_base_tsnsent[0] = asoc->mapping_array_base_tsn; 3810235283Stuexen sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 3811235283Stuexen sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 3812235283Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3813235283Stuexen sctp_notify_stream_reset_tsn(stcb, asoc->sending_seq, (asoc->mapping_array_base_tsn + 1), 0); 3814163953Srrs } 3815235283Stuexen sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 3816235283Stuexen asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 3817163953Srrs asoc->str_reset_seq_in++; 3818163953Srrs } else if (asoc->str_reset_seq_in - 1 == seq) { 3819163953Srrs sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 3820235064Stuexen asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 3821163953Srrs } else if (asoc->str_reset_seq_in - 2 == seq) { 3822163953Srrs sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[1], 3823235064Stuexen asoc->last_sending_seq[1], asoc->last_base_tsnsent[1]); 3824163953Srrs } else { 3825235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3826163953Srrs } 3827163953Srrs return (0); 3828163953Srrs} 3829163953Srrs 3830163953Srrsstatic void 3831163953Srrssctp_handle_str_reset_request_out(struct sctp_tcb *stcb, 3832163953Srrs struct sctp_tmit_chunk *chk, 3833170992Srrs struct sctp_stream_reset_out_request *req, int trunc) 3834163953Srrs{ 3835163953Srrs uint32_t seq, tsn; 3836163953Srrs int number_entries, len; 3837163953Srrs struct sctp_association *asoc = &stcb->asoc; 3838163953Srrs 3839163953Srrs seq = ntohl(req->request_seq); 3840163953Srrs 3841163953Srrs /* now if its not a duplicate we process it */ 3842163953Srrs if (asoc->str_reset_seq_in == seq) { 3843163953Srrs len = ntohs(req->ph.param_length); 3844163953Srrs number_entries = ((len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t)); 3845163953Srrs /* 3846163953Srrs * the sender is resetting, handle the list issue.. we must 3847163953Srrs * a) verify if we can do the reset, if so no problem b) If 3848163953Srrs * we can't do the reset we must copy the request. c) queue 3849163953Srrs * it, and setup the data in processor to trigger it off 3850163953Srrs * when needed and dequeue all the queued data. 3851163953Srrs */ 3852163953Srrs tsn = ntohl(req->send_reset_at_tsn); 3853163953Srrs 3854163953Srrs /* move the reset action back one */ 3855163953Srrs asoc->last_reset_action[1] = asoc->last_reset_action[0]; 3856235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 3857235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3858235064Stuexen } else if (trunc) { 3859235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3860216825Stuexen } else if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) { 3861163953Srrs /* we can do it now */ 3862163953Srrs sctp_reset_in_stream(stcb, number_entries, req->list_of_streams); 3863235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3864163953Srrs } else { 3865163953Srrs /* 3866163953Srrs * we must queue it up and thus wait for the TSN's 3867163953Srrs * to arrive that are at or before tsn 3868163953Srrs */ 3869163953Srrs struct sctp_stream_reset_list *liste; 3870163953Srrs int siz; 3871163953Srrs 3872163953Srrs siz = sizeof(struct sctp_stream_reset_list) + (number_entries * sizeof(uint16_t)); 3873163953Srrs SCTP_MALLOC(liste, struct sctp_stream_reset_list *, 3874170091Srrs siz, SCTP_M_STRESET); 3875163953Srrs if (liste == NULL) { 3876163953Srrs /* gak out of memory */ 3877235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3878235064Stuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3879163953Srrs return; 3880163953Srrs } 3881163953Srrs liste->tsn = tsn; 3882163953Srrs liste->number_entries = number_entries; 3883240198Stuexen memcpy(&liste->list_of_streams, req->list_of_streams, number_entries * sizeof(uint16_t)); 3884163953Srrs TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp); 3885235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3886163953Srrs } 3887233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3888163953Srrs asoc->str_reset_seq_in++; 3889163953Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 3890163953Srrs /* 3891163953Srrs * one seq back, just echo back last action since my 3892163953Srrs * response was lost. 3893163953Srrs */ 3894163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3895163953Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 3896163953Srrs /* 3897163953Srrs * two seq back, just echo back last action since my 3898163953Srrs * response was lost. 3899163953Srrs */ 3900163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 3901163953Srrs } else { 3902235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3903163953Srrs } 3904163953Srrs} 3905163953Srrs 3906188854Srrsstatic void 3907188854Srrssctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 3908188854Srrs struct sctp_stream_reset_add_strm *str_add) 3909188854Srrs{ 3910188854Srrs /* 3911188854Srrs * Peer is requesting to add more streams. If its within our 3912188854Srrs * max-streams we will allow it. 3913188854Srrs */ 3914233660Srrs uint32_t num_stream, i; 3915188854Srrs uint32_t seq; 3916189121Srrs struct sctp_association *asoc = &stcb->asoc; 3917216822Stuexen struct sctp_queued_to_read *ctl, *nctl; 3918188854Srrs 3919188854Srrs /* Get the number. */ 3920188854Srrs seq = ntohl(str_add->request_seq); 3921188854Srrs num_stream = ntohs(str_add->number_of_streams); 3922188854Srrs /* Now what would be the new total? */ 3923189121Srrs if (asoc->str_reset_seq_in == seq) { 3924189121Srrs num_stream += stcb->asoc.streamincnt; 3925235064Stuexen stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 3926235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 3927235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3928235064Stuexen } else if ((num_stream > stcb->asoc.max_inbound_streams) || 3929233660Srrs (num_stream > 0xffff)) { 3930189121Srrs /* We must reject it they ask for to many */ 3931189121Srrs denied: 3932235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3933189121Srrs } else { 3934189121Srrs /* Ok, we can do that :-) */ 3935189121Srrs struct sctp_stream_in *oldstrm; 3936189121Srrs 3937189121Srrs /* save off the old */ 3938189121Srrs oldstrm = stcb->asoc.strmin; 3939189121Srrs SCTP_MALLOC(stcb->asoc.strmin, struct sctp_stream_in *, 3940189121Srrs (num_stream * sizeof(struct sctp_stream_in)), 3941189121Srrs SCTP_M_STRMI); 3942189121Srrs if (stcb->asoc.strmin == NULL) { 3943189121Srrs stcb->asoc.strmin = oldstrm; 3944189121Srrs goto denied; 3945189121Srrs } 3946189121Srrs /* copy off the old data */ 3947189121Srrs for (i = 0; i < stcb->asoc.streamincnt; i++) { 3948189121Srrs TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 3949189121Srrs stcb->asoc.strmin[i].stream_no = i; 3950189121Srrs stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered; 3951189121Srrs stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started; 3952189121Srrs /* now anything on those queues? */ 3953216822Stuexen TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next, nctl) { 3954189121Srrs TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next); 3955189121Srrs TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next); 3956189121Srrs } 3957189121Srrs } 3958189121Srrs /* Init the new streams */ 3959189121Srrs for (i = stcb->asoc.streamincnt; i < num_stream; i++) { 3960189121Srrs TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 3961189121Srrs stcb->asoc.strmin[i].stream_no = i; 3962189121Srrs stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 3963189121Srrs stcb->asoc.strmin[i].delivery_started = 0; 3964189121Srrs } 3965189121Srrs SCTP_FREE(oldstrm, SCTP_M_STRMI); 3966189121Srrs /* update the size */ 3967189121Srrs stcb->asoc.streamincnt = num_stream; 3968235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3969233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 3970189121Srrs } 3971233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3972233660Srrs asoc->str_reset_seq_in++; 3973189121Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 3974189121Srrs /* 3975189121Srrs * one seq back, just echo back last action since my 3976189121Srrs * response was lost. 3977189121Srrs */ 3978189121Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3979189121Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 3980189121Srrs /* 3981189121Srrs * two seq back, just echo back last action since my 3982189121Srrs * response was lost. 3983189121Srrs */ 3984189121Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 3985188854Srrs } else { 3986235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3987188854Srrs 3988188854Srrs } 3989188854Srrs} 3990188854Srrs 3991233660Srrsstatic void 3992233660Srrssctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 3993233660Srrs struct sctp_stream_reset_add_strm *str_add) 3994233660Srrs{ 3995233660Srrs /* 3996233660Srrs * Peer is requesting to add more streams. If its within our 3997233660Srrs * max-streams we will allow it. 3998233660Srrs */ 3999233660Srrs uint16_t num_stream; 4000233660Srrs uint32_t seq; 4001233660Srrs struct sctp_association *asoc = &stcb->asoc; 4002233660Srrs 4003233660Srrs /* Get the number. */ 4004233660Srrs seq = ntohl(str_add->request_seq); 4005233660Srrs num_stream = ntohs(str_add->number_of_streams); 4006233660Srrs /* Now what would be the new total? */ 4007233660Srrs if (asoc->str_reset_seq_in == seq) { 4008235064Stuexen stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 4009235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 4010235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4011235064Stuexen } else if (stcb->asoc.stream_reset_outstanding) { 4012233660Srrs /* We must reject it we have something pending */ 4013235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 4014233660Srrs } else { 4015233660Srrs /* Ok, we can do that :-) */ 4016233660Srrs int mychk; 4017233660Srrs 4018233660Srrs mychk = stcb->asoc.streamoutcnt; 4019233660Srrs mychk += num_stream; 4020233660Srrs if (mychk < 0x10000) { 4021235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 4022233660Srrs if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, 1, num_stream, 0, 1)) { 4023235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4024233660Srrs } 4025233660Srrs } else { 4026235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4027233660Srrs } 4028233660Srrs } 4029233660Srrs sctp_add_stream_reset_result(chk, seq, stcb->asoc.last_reset_action[0]); 4030233660Srrs asoc->str_reset_seq_in++; 4031233660Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 4032233660Srrs /* 4033233660Srrs * one seq back, just echo back last action since my 4034233660Srrs * response was lost. 4035233660Srrs */ 4036233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 4037233660Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 4038233660Srrs /* 4039233660Srrs * two seq back, just echo back last action since my 4040233660Srrs * response was lost. 4041233660Srrs */ 4042233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 4043233660Srrs } else { 4044235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 4045233660Srrs } 4046233660Srrs} 4047233660Srrs 4048170992Srrs#ifdef __GNUC__ 4049170992Srrs__attribute__((noinline)) 4050170992Srrs#endif 4051170992Srrs static int 4052170992Srrs sctp_handle_stream_reset(struct sctp_tcb *stcb, struct mbuf *m, int offset, 4053240198Stuexen struct sctp_chunkhdr *ch_req) 4054163953Srrs{ 4055163953Srrs int chk_length, param_len, ptype; 4056170992Srrs struct sctp_paramhdr pstore; 4057170992Srrs uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE]; 4058233660Srrs uint32_t seq = 0; 4059163953Srrs int num_req = 0; 4060170992Srrs int trunc = 0; 4061163953Srrs struct sctp_tmit_chunk *chk; 4062163953Srrs struct sctp_chunkhdr *ch; 4063163953Srrs struct sctp_paramhdr *ph; 4064166675Srrs int ret_code = 0; 4065166675Srrs int num_param = 0; 4066163953Srrs 4067163953Srrs /* now it may be a reset or a reset-response */ 4068240198Stuexen chk_length = ntohs(ch_req->chunk_length); 4069163953Srrs 4070163953Srrs /* setup for adding the response */ 4071163953Srrs sctp_alloc_a_chunk(stcb, chk); 4072163953Srrs if (chk == NULL) { 4073163953Srrs return (ret_code); 4074163953Srrs } 4075163953Srrs chk->rec.chunk_id.id = SCTP_STREAM_RESET; 4076169208Srrs chk->rec.chunk_id.can_take_data = 0; 4077163953Srrs chk->asoc = &stcb->asoc; 4078163953Srrs chk->no_fr_allowed = 0; 4079163953Srrs chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr); 4080166023Srrs chk->book_size_scale = 0; 4081243882Sglebius chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); 4082163953Srrs if (chk->data == NULL) { 4083163953Srrsstrres_nochunk: 4084163953Srrs if (chk->data) { 4085163953Srrs sctp_m_freem(chk->data); 4086163953Srrs chk->data = NULL; 4087163953Srrs } 4088221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 4089163953Srrs return (ret_code); 4090163953Srrs } 4091165647Srrs SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); 4092163953Srrs 4093163953Srrs /* setup chunk parameters */ 4094163953Srrs chk->sent = SCTP_DATAGRAM_UNSENT; 4095163953Srrs chk->snd_count = 0; 4096224641Stuexen chk->whoTo = NULL; 4097163953Srrs 4098163953Srrs ch = mtod(chk->data, struct sctp_chunkhdr *); 4099163953Srrs ch->chunk_type = SCTP_STREAM_RESET; 4100163953Srrs ch->chunk_flags = 0; 4101163953Srrs ch->chunk_length = htons(chk->send_size); 4102165647Srrs SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size); 4103170992Srrs offset += sizeof(struct sctp_chunkhdr); 4104163953Srrs while ((size_t)chk_length >= sizeof(struct sctp_stream_reset_tsn_request)) { 4105170992Srrs ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(pstore), (uint8_t *) & pstore); 4106170992Srrs if (ph == NULL) 4107170992Srrs break; 4108163953Srrs param_len = ntohs(ph->param_length); 4109163953Srrs if (param_len < (int)sizeof(struct sctp_stream_reset_tsn_request)) { 4110163953Srrs /* bad param */ 4111163953Srrs break; 4112163953Srrs } 4113170994Srrs ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, (int)sizeof(cstore)), 4114170992Srrs (uint8_t *) & cstore); 4115163953Srrs ptype = ntohs(ph->param_type); 4116163953Srrs num_param++; 4117170994Srrs if (param_len > (int)sizeof(cstore)) { 4118170992Srrs trunc = 1; 4119170992Srrs } else { 4120170992Srrs trunc = 0; 4121170992Srrs } 4122163953Srrs if (num_param > SCTP_MAX_RESET_PARAMS) { 4123163953Srrs /* hit the max of parameters already sorry.. */ 4124163953Srrs break; 4125163953Srrs } 4126163953Srrs if (ptype == SCTP_STR_RESET_OUT_REQUEST) { 4127163953Srrs struct sctp_stream_reset_out_request *req_out; 4128163953Srrs 4129163953Srrs req_out = (struct sctp_stream_reset_out_request *)ph; 4130163953Srrs num_req++; 4131163953Srrs if (stcb->asoc.stream_reset_outstanding) { 4132163953Srrs seq = ntohl(req_out->response_seq); 4133163953Srrs if (seq == stcb->asoc.str_reset_seq_out) { 4134163953Srrs /* implicit ack */ 4135235064Stuexen (void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_RESULT_PERFORMED, NULL); 4136163953Srrs } 4137163953Srrs } 4138170992Srrs sctp_handle_str_reset_request_out(stcb, chk, req_out, trunc); 4139233660Srrs } else if (ptype == SCTP_STR_RESET_ADD_OUT_STREAMS) { 4140188854Srrs struct sctp_stream_reset_add_strm *str_add; 4141188854Srrs 4142188854Srrs str_add = (struct sctp_stream_reset_add_strm *)ph; 4143188854Srrs num_req++; 4144188854Srrs sctp_handle_str_reset_add_strm(stcb, chk, str_add); 4145233660Srrs } else if (ptype == SCTP_STR_RESET_ADD_IN_STREAMS) { 4146233660Srrs struct sctp_stream_reset_add_strm *str_add; 4147233660Srrs 4148233660Srrs str_add = (struct sctp_stream_reset_add_strm *)ph; 4149233660Srrs num_req++; 4150233660Srrs sctp_handle_str_reset_add_out_strm(stcb, chk, str_add); 4151163953Srrs } else if (ptype == SCTP_STR_RESET_IN_REQUEST) { 4152163953Srrs struct sctp_stream_reset_in_request *req_in; 4153163953Srrs 4154163953Srrs num_req++; 4155163953Srrs req_in = (struct sctp_stream_reset_in_request *)ph; 4156170992Srrs sctp_handle_str_reset_request_in(stcb, chk, req_in, trunc); 4157163953Srrs } else if (ptype == SCTP_STR_RESET_TSN_REQUEST) { 4158163953Srrs struct sctp_stream_reset_tsn_request *req_tsn; 4159163953Srrs 4160163953Srrs num_req++; 4161163953Srrs req_tsn = (struct sctp_stream_reset_tsn_request *)ph; 4162163953Srrs if (sctp_handle_str_reset_request_tsn(stcb, chk, req_tsn)) { 4163163953Srrs ret_code = 1; 4164163953Srrs goto strres_nochunk; 4165163953Srrs } 4166163953Srrs /* no more */ 4167163953Srrs break; 4168163953Srrs } else if (ptype == SCTP_STR_RESET_RESPONSE) { 4169163953Srrs struct sctp_stream_reset_response *resp; 4170163953Srrs uint32_t result; 4171163953Srrs 4172163953Srrs resp = (struct sctp_stream_reset_response *)ph; 4173163953Srrs seq = ntohl(resp->response_seq); 4174163953Srrs result = ntohl(resp->result); 4175163953Srrs if (sctp_handle_stream_reset_response(stcb, seq, result, resp)) { 4176163953Srrs ret_code = 1; 4177163953Srrs goto strres_nochunk; 4178163953Srrs } 4179163953Srrs } else { 4180163953Srrs break; 4181163953Srrs } 4182170992Srrs offset += SCTP_SIZE32(param_len); 4183163953Srrs chk_length -= SCTP_SIZE32(param_len); 4184163953Srrs } 4185163953Srrs if (num_req == 0) { 4186163953Srrs /* we have no response free the stuff */ 4187163953Srrs goto strres_nochunk; 4188163953Srrs } 4189163953Srrs /* ok we have a chunk to link in */ 4190163953Srrs TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue, 4191163953Srrs chk, 4192163953Srrs sctp_next); 4193163953Srrs stcb->asoc.ctrl_queue_cnt++; 4194163953Srrs return (ret_code); 4195163953Srrs} 4196163953Srrs 4197163953Srrs/* 4198163953Srrs * Handle a router or endpoints report of a packet loss, there are two ways 4199163953Srrs * to handle this, either we get the whole packet and must disect it 4200163953Srrs * ourselves (possibly with truncation and or corruption) or it is a summary 4201163953Srrs * from a middle box that did the disectting for us. 4202163953Srrs */ 4203163953Srrsstatic void 4204163953Srrssctp_handle_packet_dropped(struct sctp_pktdrop_chunk *cp, 4205170781Srrs struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t limit) 4206163953Srrs{ 4207163953Srrs uint32_t bottle_bw, on_queue; 4208163953Srrs uint16_t trunc_len; 4209163953Srrs unsigned int chlen; 4210163953Srrs unsigned int at; 4211163953Srrs struct sctp_chunk_desc desc; 4212163953Srrs struct sctp_chunkhdr *ch; 4213163953Srrs 4214163953Srrs chlen = ntohs(cp->ch.chunk_length); 4215163953Srrs chlen -= sizeof(struct sctp_pktdrop_chunk); 4216163953Srrs /* XXX possible chlen underflow */ 4217163953Srrs if (chlen == 0) { 4218163953Srrs ch = NULL; 4219163953Srrs if (cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) 4220163953Srrs SCTP_STAT_INCR(sctps_pdrpbwrpt); 4221163953Srrs } else { 4222163953Srrs ch = (struct sctp_chunkhdr *)(cp->data + sizeof(struct sctphdr)); 4223163953Srrs chlen -= sizeof(struct sctphdr); 4224163953Srrs /* XXX possible chlen underflow */ 4225163953Srrs memset(&desc, 0, sizeof(desc)); 4226163953Srrs } 4227163953Srrs trunc_len = (uint16_t) ntohs(cp->trunc_len); 4228170781Srrs if (trunc_len > limit) { 4229170781Srrs trunc_len = limit; 4230170781Srrs } 4231163953Srrs /* now the chunks themselves */ 4232163953Srrs while ((ch != NULL) && (chlen >= sizeof(struct sctp_chunkhdr))) { 4233163953Srrs desc.chunk_type = ch->chunk_type; 4234163953Srrs /* get amount we need to move */ 4235163953Srrs at = ntohs(ch->chunk_length); 4236163953Srrs if (at < sizeof(struct sctp_chunkhdr)) { 4237163953Srrs /* corrupt chunk, maybe at the end? */ 4238163953Srrs SCTP_STAT_INCR(sctps_pdrpcrupt); 4239163953Srrs break; 4240163953Srrs } 4241163953Srrs if (trunc_len == 0) { 4242163953Srrs /* we are supposed to have all of it */ 4243163953Srrs if (at > chlen) { 4244163953Srrs /* corrupt skip it */ 4245163953Srrs SCTP_STAT_INCR(sctps_pdrpcrupt); 4246163953Srrs break; 4247163953Srrs } 4248163953Srrs } else { 4249163953Srrs /* is there enough of it left ? */ 4250163953Srrs if (desc.chunk_type == SCTP_DATA) { 4251163953Srrs if (chlen < (sizeof(struct sctp_data_chunk) + 4252163953Srrs sizeof(desc.data_bytes))) { 4253163953Srrs break; 4254163953Srrs } 4255163953Srrs } else { 4256163953Srrs if (chlen < sizeof(struct sctp_chunkhdr)) { 4257163953Srrs break; 4258163953Srrs } 4259163953Srrs } 4260163953Srrs } 4261163953Srrs if (desc.chunk_type == SCTP_DATA) { 4262163953Srrs /* can we get out the tsn? */ 4263163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 4264163953Srrs SCTP_STAT_INCR(sctps_pdrpmbda); 4265163953Srrs 4266163953Srrs if (chlen >= (sizeof(struct sctp_data_chunk) + sizeof(uint32_t))) { 4267163953Srrs /* yep */ 4268163953Srrs struct sctp_data_chunk *dcp; 4269163953Srrs uint8_t *ddp; 4270163953Srrs unsigned int iii; 4271163953Srrs 4272163953Srrs dcp = (struct sctp_data_chunk *)ch; 4273163953Srrs ddp = (uint8_t *) (dcp + 1); 4274163953Srrs for (iii = 0; iii < sizeof(desc.data_bytes); iii++) { 4275163953Srrs desc.data_bytes[iii] = ddp[iii]; 4276163953Srrs } 4277163953Srrs desc.tsn_ifany = dcp->dp.tsn; 4278163953Srrs } else { 4279163953Srrs /* nope we are done. */ 4280163953Srrs SCTP_STAT_INCR(sctps_pdrpnedat); 4281163953Srrs break; 4282163953Srrs } 4283163953Srrs } else { 4284163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 4285163953Srrs SCTP_STAT_INCR(sctps_pdrpmbct); 4286163953Srrs } 4287163953Srrs 4288163953Srrs if (process_chunk_drop(stcb, &desc, net, cp->ch.chunk_flags)) { 4289163953Srrs SCTP_STAT_INCR(sctps_pdrppdbrk); 4290163953Srrs break; 4291163953Srrs } 4292163953Srrs if (SCTP_SIZE32(at) > chlen) { 4293163953Srrs break; 4294163953Srrs } 4295163953Srrs chlen -= SCTP_SIZE32(at); 4296163953Srrs if (chlen < sizeof(struct sctp_chunkhdr)) { 4297163953Srrs /* done, none left */ 4298163953Srrs break; 4299163953Srrs } 4300163953Srrs ch = (struct sctp_chunkhdr *)((caddr_t)ch + SCTP_SIZE32(at)); 4301163953Srrs } 4302163953Srrs /* Now update any rwnd --- possibly */ 4303163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) == 0) { 4304163953Srrs /* From a peer, we get a rwnd report */ 4305163953Srrs uint32_t a_rwnd; 4306163953Srrs 4307163953Srrs SCTP_STAT_INCR(sctps_pdrpfehos); 4308163953Srrs 4309163953Srrs bottle_bw = ntohl(cp->bottle_bw); 4310163953Srrs on_queue = ntohl(cp->current_onq); 4311163953Srrs if (bottle_bw && on_queue) { 4312163953Srrs /* a rwnd report is in here */ 4313163953Srrs if (bottle_bw > on_queue) 4314163953Srrs a_rwnd = bottle_bw - on_queue; 4315163953Srrs else 4316163953Srrs a_rwnd = 0; 4317163953Srrs 4318163953Srrs if (a_rwnd == 0) 4319163953Srrs stcb->asoc.peers_rwnd = 0; 4320163953Srrs else { 4321163953Srrs if (a_rwnd > stcb->asoc.total_flight) { 4322163953Srrs stcb->asoc.peers_rwnd = 4323163953Srrs a_rwnd - stcb->asoc.total_flight; 4324163953Srrs } else { 4325163953Srrs stcb->asoc.peers_rwnd = 0; 4326163953Srrs } 4327163953Srrs if (stcb->asoc.peers_rwnd < 4328163953Srrs stcb->sctp_ep->sctp_ep.sctp_sws_sender) { 4329163953Srrs /* SWS sender side engages */ 4330163953Srrs stcb->asoc.peers_rwnd = 0; 4331163953Srrs } 4332163953Srrs } 4333163953Srrs } 4334163953Srrs } else { 4335163953Srrs SCTP_STAT_INCR(sctps_pdrpfmbox); 4336163953Srrs } 4337163953Srrs 4338163953Srrs /* now middle boxes in sat networks get a cwnd bump */ 4339163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) && 4340163953Srrs (stcb->asoc.sat_t3_loss_recovery == 0) && 4341163953Srrs (stcb->asoc.sat_network)) { 4342163953Srrs /* 4343163953Srrs * This is debateable but for sat networks it makes sense 4344163953Srrs * Note if a T3 timer has went off, we will prohibit any 4345163953Srrs * changes to cwnd until we exit the t3 loss recovery. 4346163953Srrs */ 4347171440Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped(stcb, 4348171440Srrs net, cp, &bottle_bw, &on_queue); 4349163953Srrs } 4350163953Srrs} 4351163953Srrs 4352163953Srrs/* 4353163953Srrs * handles all control chunks in a packet inputs: - m: mbuf chain, assumed to 4354163953Srrs * still contain IP/SCTP header - stcb: is the tcb found for this packet - 4355163953Srrs * offset: offset into the mbuf chain to first chunkhdr - length: is the 4356163953Srrs * length of the complete packet outputs: - length: modified to remaining 4357163953Srrs * length after control processing - netp: modified to new sctp_nets after 4358163953Srrs * cookie-echo processing - return NULL to discard the packet (ie. no asoc, 4359163953Srrs * bad packet,...) otherwise return the tcb for this packet 4360163953Srrs */ 4361170099Srrs#ifdef __GNUC__ 4362170099Srrs__attribute__((noinline)) 4363170099Srrs#endif 4364170099Srrs static struct sctp_tcb * 4365170099Srrs sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, 4366237715Stuexen struct sockaddr *src, struct sockaddr *dst, 4367170099Srrs struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp, 4368170099Srrs struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen, 4369237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 4370179157Srrs uint32_t vrf_id, uint16_t port) 4371163953Srrs{ 4372163953Srrs struct sctp_association *asoc; 4373267723Stuexen struct mbuf *op_err; 4374267723Stuexen char msg[SCTP_DIAG_INFO_LEN]; 4375163953Srrs uint32_t vtag_in; 4376163953Srrs int num_chunks = 0; /* number of control chunks processed */ 4377170140Srrs uint32_t chk_length; 4378163953Srrs int ret; 4379168299Srrs int abort_no_unlock = 0; 4380218186Srrs int ecne_seen = 0; 4381163953Srrs 4382163953Srrs /* 4383163953Srrs * How big should this be, and should it be alloc'd? Lets try the 4384163953Srrs * d-mtu-ceiling for now (2k) and that should hopefully work ... 4385163953Srrs * until we get into jumbo grams and such.. 4386163953Srrs */ 4387166675Srrs uint8_t chunk_buf[SCTP_CHUNK_BUFFER_SIZE]; 4388163953Srrs struct sctp_tcb *locked_tcb = stcb; 4389163953Srrs int got_auth = 0; 4390163953Srrs uint32_t auth_offset = 0, auth_len = 0; 4391163953Srrs int auth_skipped = 0; 4392171990Srrs int asconf_cnt = 0; 4393163953Srrs 4394237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4395172090Srrs struct socket *so; 4396172090Srrs 4397172090Srrs#endif 4398172090Srrs 4399169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n", 4400240148Stuexen iphlen, *offset, length, (void *)stcb); 4401163953Srrs 4402163953Srrs /* validate chunk header length... */ 4403163953Srrs if (ntohs(ch->chunk_length) < sizeof(*ch)) { 4404170056Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Invalid header length %d\n", 4405170056Srrs ntohs(ch->chunk_length)); 4406170091Srrs if (locked_tcb) { 4407170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4408170091Srrs } 4409163953Srrs return (NULL); 4410163953Srrs } 4411163953Srrs /* 4412163953Srrs * validate the verification tag 4413163953Srrs */ 4414163953Srrs vtag_in = ntohl(sh->v_tag); 4415163953Srrs 4416165220Srrs if (locked_tcb) { 4417165220Srrs SCTP_TCB_LOCK_ASSERT(locked_tcb); 4418165220Srrs } 4419163953Srrs if (ch->chunk_type == SCTP_INITIATION) { 4420170056Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Its an INIT of len:%d vtag:%x\n", 4421170056Srrs ntohs(ch->chunk_length), vtag_in); 4422163953Srrs if (vtag_in != 0) { 4423163953Srrs /* protocol error- silently discard... */ 4424163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4425169378Srrs if (locked_tcb) { 4426163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4427169378Srrs } 4428163953Srrs return (NULL); 4429163953Srrs } 4430163953Srrs } else if (ch->chunk_type != SCTP_COOKIE_ECHO) { 4431163953Srrs /* 4432163953Srrs * If there is no stcb, skip the AUTH chunk and process 4433163953Srrs * later after a stcb is found (to validate the lookup was 4434163953Srrs * valid. 4435163953Srrs */ 4436163953Srrs if ((ch->chunk_type == SCTP_AUTHENTICATION) && 4437179783Srrs (stcb == NULL) && 4438179783Srrs !SCTP_BASE_SYSCTL(sctp_auth_disable)) { 4439163953Srrs /* save this chunk for later processing */ 4440163953Srrs auth_skipped = 1; 4441163953Srrs auth_offset = *offset; 4442163953Srrs auth_len = ntohs(ch->chunk_length); 4443163953Srrs 4444163953Srrs /* (temporarily) move past this chunk */ 4445163953Srrs *offset += SCTP_SIZE32(auth_len); 4446163953Srrs if (*offset >= length) { 4447163953Srrs /* no more data left in the mbuf chain */ 4448163953Srrs *offset = length; 4449170091Srrs if (locked_tcb) { 4450170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4451170091Srrs } 4452163953Srrs return (NULL); 4453163953Srrs } 4454163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4455163953Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 4456163953Srrs } 4457169420Srrs if (ch == NULL) { 4458169420Srrs /* Help */ 4459169420Srrs *offset = length; 4460170091Srrs if (locked_tcb) { 4461170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4462170091Srrs } 4463169420Srrs return (NULL); 4464169420Srrs } 4465163953Srrs if (ch->chunk_type == SCTP_COOKIE_ECHO) { 4466163953Srrs goto process_control_chunks; 4467163953Srrs } 4468163953Srrs /* 4469163953Srrs * first check if it's an ASCONF with an unknown src addr we 4470163953Srrs * need to look inside to find the association 4471163953Srrs */ 4472163953Srrs if (ch->chunk_type == SCTP_ASCONF && stcb == NULL) { 4473171990Srrs struct sctp_chunkhdr *asconf_ch = ch; 4474171990Srrs uint32_t asconf_offset = 0, asconf_len = 0; 4475171990Srrs 4476163953Srrs /* inp's refcount may be reduced */ 4477163953Srrs SCTP_INP_INCR_REF(inp); 4478163953Srrs 4479171990Srrs asconf_offset = *offset; 4480171990Srrs do { 4481171990Srrs asconf_len = ntohs(asconf_ch->chunk_length); 4482171990Srrs if (asconf_len < sizeof(struct sctp_asconf_paramhdr)) 4483171990Srrs break; 4484228653Stuexen stcb = sctp_findassociation_ep_asconf(m, 4485237715Stuexen *offset, 4486237715Stuexen dst, 4487237715Stuexen sh, &inp, netp, vrf_id); 4488171990Srrs if (stcb != NULL) 4489171990Srrs break; 4490171990Srrs asconf_offset += SCTP_SIZE32(asconf_len); 4491171990Srrs asconf_ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, asconf_offset, 4492171990Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 4493171990Srrs } while (asconf_ch != NULL && asconf_ch->chunk_type == SCTP_ASCONF); 4494163953Srrs if (stcb == NULL) { 4495163953Srrs /* 4496163953Srrs * reduce inp's refcount if not reduced in 4497163953Srrs * sctp_findassociation_ep_asconf(). 4498163953Srrs */ 4499163953Srrs SCTP_INP_DECR_REF(inp); 4500171990Srrs } else { 4501171990Srrs locked_tcb = stcb; 4502163953Srrs } 4503171990Srrs 4504163953Srrs /* now go back and verify any auth chunk to be sure */ 4505163953Srrs if (auth_skipped && (stcb != NULL)) { 4506163953Srrs struct sctp_auth_chunk *auth; 4507163953Srrs 4508163953Srrs auth = (struct sctp_auth_chunk *) 4509163953Srrs sctp_m_getptr(m, auth_offset, 4510163953Srrs auth_len, chunk_buf); 4511163953Srrs got_auth = 1; 4512163953Srrs auth_skipped = 0; 4513169420Srrs if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, 4514163953Srrs auth_offset)) { 4515163953Srrs /* auth HMAC failed so dump it */ 4516163953Srrs *offset = length; 4517170091Srrs if (locked_tcb) { 4518170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4519170091Srrs } 4520163953Srrs return (NULL); 4521163953Srrs } else { 4522163953Srrs /* remaining chunks are HMAC checked */ 4523163953Srrs stcb->asoc.authenticated = 1; 4524163953Srrs } 4525163953Srrs } 4526163953Srrs } 4527163953Srrs if (stcb == NULL) { 4528267723Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 4529267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 4530267723Stuexen msg); 4531163953Srrs /* no association, so it's out of the blue... */ 4532267723Stuexen sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err, 4533237049Stuexen use_mflowid, mflowid, 4534179157Srrs vrf_id, port); 4535163953Srrs *offset = length; 4536169378Srrs if (locked_tcb) { 4537163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4538169378Srrs } 4539163953Srrs return (NULL); 4540163953Srrs } 4541163953Srrs asoc = &stcb->asoc; 4542163953Srrs /* ABORT and SHUTDOWN can use either v_tag... */ 4543163953Srrs if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) || 4544163953Srrs (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) || 4545163953Srrs (ch->chunk_type == SCTP_PACKET_DROPPED)) { 4546252718Stuexen /* Take the T-bit always into account. */ 4547252718Stuexen if ((((ch->chunk_flags & SCTP_HAD_NO_TCB) == 0) && 4548252718Stuexen (vtag_in == asoc->my_vtag)) || 4549252718Stuexen (((ch->chunk_flags & SCTP_HAD_NO_TCB) == SCTP_HAD_NO_TCB) && 4550163953Srrs (vtag_in == asoc->peer_vtag))) { 4551163953Srrs /* this is valid */ 4552163953Srrs } else { 4553163953Srrs /* drop this packet... */ 4554163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4555169378Srrs if (locked_tcb) { 4556163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4557169378Srrs } 4558163953Srrs return (NULL); 4559163953Srrs } 4560163953Srrs } else if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 4561163953Srrs if (vtag_in != asoc->my_vtag) { 4562163953Srrs /* 4563163953Srrs * this could be a stale SHUTDOWN-ACK or the 4564163953Srrs * peer never got the SHUTDOWN-COMPLETE and 4565163953Srrs * is still hung; we have started a new asoc 4566163953Srrs * but it won't complete until the shutdown 4567163953Srrs * is completed 4568163953Srrs */ 4569169378Srrs if (locked_tcb) { 4570163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4571169378Srrs } 4572267723Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 4573267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 4574267723Stuexen msg); 4575237715Stuexen sctp_handle_ootb(m, iphlen, *offset, src, dst, 4576267723Stuexen sh, inp, op_err, 4577237049Stuexen use_mflowid, mflowid, 4578236450Stuexen vrf_id, port); 4579163953Srrs return (NULL); 4580163953Srrs } 4581163953Srrs } else { 4582163953Srrs /* for all other chunks, vtag must match */ 4583163953Srrs if (vtag_in != asoc->my_vtag) { 4584163953Srrs /* invalid vtag... */ 4585169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 4586169420Srrs "invalid vtag: %xh, expect %xh\n", 4587169420Srrs vtag_in, asoc->my_vtag); 4588163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4589169378Srrs if (locked_tcb) { 4590163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4591169378Srrs } 4592163953Srrs *offset = length; 4593163953Srrs return (NULL); 4594163953Srrs } 4595163953Srrs } 4596163953Srrs } /* end if !SCTP_COOKIE_ECHO */ 4597163953Srrs /* 4598163953Srrs * process all control chunks... 4599163953Srrs */ 4600163953Srrs if (((ch->chunk_type == SCTP_SELECTIVE_ACK) || 4601185694Srrs (ch->chunk_type == SCTP_NR_SELECTIVE_ACK) || 4602163953Srrs (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) && 4603163953Srrs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { 4604163953Srrs /* implied cookie-ack.. we must have lost the ack */ 4605179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 4606171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 4607171943Srrs stcb->asoc.overall_error_count, 4608171943Srrs 0, 4609171943Srrs SCTP_FROM_SCTP_INPUT, 4610171943Srrs __LINE__); 4611171943Srrs } 4612163953Srrs stcb->asoc.overall_error_count = 0; 4613163953Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, 4614163953Srrs *netp); 4615163953Srrs } 4616163953Srrsprocess_control_chunks: 4617163953Srrs while (IS_SCTP_CONTROL(ch)) { 4618163953Srrs /* validate chunk length */ 4619163953Srrs chk_length = ntohs(ch->chunk_length); 4620169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_process_control: processing a chunk type=%u, len=%u\n", 4621169420Srrs ch->chunk_type, chk_length); 4622170744Srrs SCTP_LTRACE_CHK(inp, stcb, ch->chunk_type, chk_length); 4623170140Srrs if (chk_length < sizeof(*ch) || 4624170140Srrs (*offset + (int)chk_length) > length) { 4625163953Srrs *offset = length; 4626169378Srrs if (locked_tcb) { 4627163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4628169378Srrs } 4629163953Srrs return (NULL); 4630163953Srrs } 4631163953Srrs SCTP_STAT_INCR_COUNTER64(sctps_incontrolchunks); 4632163953Srrs /* 4633163953Srrs * INIT-ACK only gets the init ack "header" portion only 4634163953Srrs * because we don't have to process the peer's COOKIE. All 4635163953Srrs * others get a complete chunk. 4636163953Srrs */ 4637169208Srrs if ((ch->chunk_type == SCTP_INITIATION_ACK) || 4638169208Srrs (ch->chunk_type == SCTP_INITIATION)) { 4639163953Srrs /* get an init-ack chunk */ 4640163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4641163953Srrs sizeof(struct sctp_init_ack_chunk), chunk_buf); 4642163953Srrs if (ch == NULL) { 4643163953Srrs *offset = length; 4644169378Srrs if (locked_tcb) { 4645163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4646169378Srrs } 4647163953Srrs return (NULL); 4648163953Srrs } 4649170642Srrs } else { 4650170786Srrs /* For cookies and all other chunks. */ 4651169208Srrs if (chk_length > sizeof(chunk_buf)) { 4652169208Srrs /* 4653169208Srrs * use just the size of the chunk buffer so 4654170642Srrs * the front part of our chunks fit in 4655170642Srrs * contiguous space up to the chunk buffer 4656170642Srrs * size (508 bytes). For chunks that need to 4657170786Srrs * get more than that they must use the 4658170642Srrs * sctp_m_getptr() function or other means 4659170786Srrs * (e.g. know how to parse mbuf chains). 4660170786Srrs * Cookies do this already. 4661169208Srrs */ 4662169208Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4663169208Srrs (sizeof(chunk_buf) - 4), 4664169208Srrs chunk_buf); 4665169208Srrs if (ch == NULL) { 4666169208Srrs *offset = length; 4667169378Srrs if (locked_tcb) { 4668169208Srrs SCTP_TCB_UNLOCK(locked_tcb); 4669169378Srrs } 4670169208Srrs return (NULL); 4671169208Srrs } 4672169208Srrs } else { 4673169208Srrs /* We can fit it all */ 4674170642Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4675170642Srrs chk_length, chunk_buf); 4676170642Srrs if (ch == NULL) { 4677170642Srrs SCTP_PRINTF("sctp_process_control: Can't get the all data....\n"); 4678170642Srrs *offset = length; 4679170642Srrs if (locked_tcb) { 4680170642Srrs SCTP_TCB_UNLOCK(locked_tcb); 4681169208Srrs } 4682170642Srrs return (NULL); 4683163953Srrs } 4684163953Srrs } 4685163953Srrs } 4686163953Srrs num_chunks++; 4687163953Srrs /* Save off the last place we got a control from */ 4688163953Srrs if (stcb != NULL) { 4689169420Srrs if (((netp != NULL) && (*netp != NULL)) || (ch->chunk_type == SCTP_ASCONF)) { 4690163953Srrs /* 4691163953Srrs * allow last_control to be NULL if 4692163953Srrs * ASCONF... ASCONF processing will find the 4693163953Srrs * right net later 4694163953Srrs */ 4695169420Srrs if ((netp != NULL) && (*netp != NULL)) 4696169420Srrs stcb->asoc.last_control_chunk_from = *netp; 4697163953Srrs } 4698163953Srrs } 4699163953Srrs#ifdef SCTP_AUDITING_ENABLED 4700163953Srrs sctp_audit_log(0xB0, ch->chunk_type); 4701163953Srrs#endif 4702163953Srrs 4703163953Srrs /* check to see if this chunk required auth, but isn't */ 4704179783Srrs if ((stcb != NULL) && 4705179783Srrs !SCTP_BASE_SYSCTL(sctp_auth_disable) && 4706179783Srrs sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) && 4707163953Srrs !stcb->asoc.authenticated) { 4708163953Srrs /* "silently" ignore */ 4709163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 4710163953Srrs goto next_chunk; 4711163953Srrs } 4712163953Srrs switch (ch->chunk_type) { 4713163953Srrs case SCTP_INITIATION: 4714169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT\n"); 4715229774Stuexen /* The INIT chunk must be the only chunk. */ 4716229774Stuexen if ((num_chunks > 1) || 4717229775Stuexen (length - *offset > (int)SCTP_SIZE32(chk_length))) { 4718267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 4719267723Stuexen "INIT not the only chunk"); 4720237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, 4721267723Stuexen src, dst, sh, op_err, 4722237049Stuexen use_mflowid, mflowid, 4723237049Stuexen vrf_id, port); 4724163953Srrs *offset = length; 4725163953Srrs return (NULL); 4726163953Srrs } 4727229774Stuexen /* Honor our resource limit. */ 4728229774Stuexen if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) { 4729267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 4730237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, 4731237715Stuexen src, dst, sh, op_err, 4732237049Stuexen use_mflowid, mflowid, 4733237049Stuexen vrf_id, port); 4734163953Srrs *offset = length; 4735163953Srrs return (NULL); 4736163953Srrs } 4737237715Stuexen sctp_handle_init(m, iphlen, *offset, src, dst, sh, 4738229774Stuexen (struct sctp_init_chunk *)ch, inp, 4739237049Stuexen stcb, &abort_no_unlock, 4740237049Stuexen use_mflowid, mflowid, 4741237049Stuexen vrf_id, port); 4742163953Srrs *offset = length; 4743229774Stuexen if ((!abort_no_unlock) && (locked_tcb)) { 4744163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4745169378Srrs } 4746163953Srrs return (NULL); 4747163953Srrs break; 4748170642Srrs case SCTP_PAD_CHUNK: 4749170642Srrs break; 4750163953Srrs case SCTP_INITIATION_ACK: 4751169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n"); 4752163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 4753163953Srrs /* We are not interested anymore */ 4754163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 4755163953Srrs ; 4756163953Srrs } else { 4757208876Srrs if (locked_tcb != stcb) { 4758208876Srrs /* Very unlikely */ 4759163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4760169378Srrs } 4761163953Srrs *offset = length; 4762163953Srrs if (stcb) { 4763237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4764172090Srrs so = SCTP_INP_SO(inp); 4765172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 4766172090Srrs SCTP_TCB_UNLOCK(stcb); 4767172090Srrs SCTP_SOCKET_LOCK(so, 1); 4768172090Srrs SCTP_TCB_LOCK(stcb); 4769172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 4770172090Srrs#endif 4771171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27); 4772237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4773172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4774172090Srrs#endif 4775163953Srrs } 4776163953Srrs return (NULL); 4777163953Srrs } 4778163953Srrs } 4779229775Stuexen /* The INIT-ACK chunk must be the only chunk. */ 4780163953Srrs if ((num_chunks > 1) || 4781229775Stuexen (length - *offset > (int)SCTP_SIZE32(chk_length))) { 4782163953Srrs *offset = length; 4783169378Srrs if (locked_tcb) { 4784163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4785169378Srrs } 4786163953Srrs return (NULL); 4787163953Srrs } 4788169420Srrs if ((netp) && (*netp)) { 4789237715Stuexen ret = sctp_handle_init_ack(m, iphlen, *offset, 4790237715Stuexen src, dst, sh, 4791237049Stuexen (struct sctp_init_ack_chunk *)ch, 4792237049Stuexen stcb, *netp, 4793237049Stuexen &abort_no_unlock, 4794237049Stuexen use_mflowid, mflowid, 4795237049Stuexen vrf_id); 4796169420Srrs } else { 4797169420Srrs ret = -1; 4798169420Srrs } 4799229774Stuexen *offset = length; 4800229774Stuexen if (abort_no_unlock) { 4801229774Stuexen return (NULL); 4802229774Stuexen } 4803163953Srrs /* 4804163953Srrs * Special case, I must call the output routine to 4805163953Srrs * get the cookie echoed 4806163953Srrs */ 4807229774Stuexen if ((stcb != NULL) && (ret == 0)) { 4808172090Srrs sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 4809229774Stuexen } 4810169378Srrs if (locked_tcb) { 4811163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4812169378Srrs } 4813163953Srrs return (NULL); 4814163953Srrs break; 4815163953Srrs case SCTP_SELECTIVE_ACK: 4816163953Srrs { 4817163953Srrs struct sctp_sack_chunk *sack; 4818163953Srrs int abort_now = 0; 4819163953Srrs uint32_t a_rwnd, cum_ack; 4820202526Stuexen uint16_t num_seg, num_dup; 4821202526Stuexen uint8_t flags; 4822202526Stuexen int offset_seg, offset_dup; 4823163953Srrs 4824211944Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n"); 4825211944Stuexen SCTP_STAT_INCR(sctps_recvsacks); 4826202526Stuexen if (stcb == NULL) { 4827202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing SACK chunk\n"); 4828202526Stuexen break; 4829169208Srrs } 4830202526Stuexen if (chk_length < sizeof(struct sctp_sack_chunk)) { 4831202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on SACK chunk, too small\n"); 4832202526Stuexen break; 4833202526Stuexen } 4834171990Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 4835171990Srrs /*- 4836171990Srrs * If we have sent a shutdown-ack, we will pay no 4837171990Srrs * attention to a sack sent in to us since 4838171990Srrs * we don't care anymore. 4839171990Srrs */ 4840184883Srrs break; 4841171990Srrs } 4842163953Srrs sack = (struct sctp_sack_chunk *)ch; 4843202526Stuexen flags = ch->chunk_flags; 4844163953Srrs cum_ack = ntohl(sack->sack.cum_tsn_ack); 4845163953Srrs num_seg = ntohs(sack->sack.num_gap_ack_blks); 4846202526Stuexen num_dup = ntohs(sack->sack.num_dup_tsns); 4847163953Srrs a_rwnd = (uint32_t) ntohl(sack->sack.a_rwnd); 4848202526Stuexen if (sizeof(struct sctp_sack_chunk) + 4849202526Stuexen num_seg * sizeof(struct sctp_gap_ack_block) + 4850202526Stuexen num_dup * sizeof(uint32_t) != chk_length) { 4851202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of SACK chunk\n"); 4852202526Stuexen break; 4853202526Stuexen } 4854202526Stuexen offset_seg = *offset + sizeof(struct sctp_sack_chunk); 4855202526Stuexen offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 4856170606Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 4857202526Stuexen cum_ack, num_seg, a_rwnd); 4858163953Srrs stcb->asoc.seen_a_sack_this_pkt = 1; 4859163953Srrs if ((stcb->asoc.pr_sctp_cnt == 0) && 4860163953Srrs (num_seg == 0) && 4861216825Stuexen SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 4862163953Srrs (stcb->asoc.saw_sack_with_frags == 0) && 4863216188Stuexen (stcb->asoc.saw_sack_with_nr_frags == 0) && 4864163953Srrs (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) 4865163953Srrs ) { 4866163953Srrs /* 4867163953Srrs * We have a SIMPLE sack having no 4868163953Srrs * prior segments and data on sent 4869163953Srrs * queue to be acked.. Use the 4870163953Srrs * faster path sack processing. We 4871163953Srrs * also allow window update sacks 4872163953Srrs * with no missing segments to go 4873163953Srrs * this way too. 4874163953Srrs */ 4875218186Srrs sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now, ecne_seen); 4876163953Srrs } else { 4877169420Srrs if (netp && *netp) 4878228653Stuexen sctp_handle_sack(m, offset_seg, offset_dup, stcb, 4879202526Stuexen num_seg, 0, num_dup, &abort_now, flags, 4880218186Srrs cum_ack, a_rwnd, ecne_seen); 4881163953Srrs } 4882202526Stuexen if (abort_now) { 4883202526Stuexen /* ABORT signal from sack processing */ 4884202526Stuexen *offset = length; 4885202526Stuexen return (NULL); 4886202526Stuexen } 4887185694Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 4888185694Srrs TAILQ_EMPTY(&stcb->asoc.sent_queue) && 4889185694Srrs (stcb->asoc.stream_queue_cnt == 0)) { 4890185694Srrs sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 4891185694Srrs } 4892163953Srrs } 4893163953Srrs break; 4894185694Srrs /* 4895185694Srrs * EY - nr_sack: If the received chunk is an 4896185694Srrs * nr_sack chunk 4897185694Srrs */ 4898185694Srrs case SCTP_NR_SELECTIVE_ACK: 4899185694Srrs { 4900185694Srrs struct sctp_nr_sack_chunk *nr_sack; 4901185694Srrs int abort_now = 0; 4902185694Srrs uint32_t a_rwnd, cum_ack; 4903202526Stuexen uint16_t num_seg, num_nr_seg, num_dup; 4904202526Stuexen uint8_t flags; 4905202526Stuexen int offset_seg, offset_dup; 4906185694Srrs 4907211944Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n"); 4908211944Stuexen SCTP_STAT_INCR(sctps_recvsacks); 4909212225Srrs if (stcb == NULL) { 4910212225Srrs SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing NR-SACK chunk\n"); 4911212225Srrs break; 4912212225Srrs } 4913211944Stuexen if ((stcb->asoc.sctp_nr_sack_on_off == 0) || 4914211944Stuexen (stcb->asoc.peer_supports_nr_sack == 0)) { 4915185694Srrs goto unknown_chunk; 4916185694Srrs } 4917202526Stuexen if (chk_length < sizeof(struct sctp_nr_sack_chunk)) { 4918202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on NR-SACK chunk, too small\n"); 4919202526Stuexen break; 4920202526Stuexen } 4921185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 4922185694Srrs /*- 4923185694Srrs * If we have sent a shutdown-ack, we will pay no 4924185694Srrs * attention to a sack sent in to us since 4925185694Srrs * we don't care anymore. 4926185694Srrs */ 4927202526Stuexen break; 4928185694Srrs } 4929185694Srrs nr_sack = (struct sctp_nr_sack_chunk *)ch; 4930202526Stuexen flags = ch->chunk_flags; 4931185694Srrs cum_ack = ntohl(nr_sack->nr_sack.cum_tsn_ack); 4932185694Srrs num_seg = ntohs(nr_sack->nr_sack.num_gap_ack_blks); 4933185694Srrs num_nr_seg = ntohs(nr_sack->nr_sack.num_nr_gap_ack_blks); 4934202526Stuexen num_dup = ntohs(nr_sack->nr_sack.num_dup_tsns); 4935185694Srrs a_rwnd = (uint32_t) ntohl(nr_sack->nr_sack.a_rwnd); 4936202526Stuexen if (sizeof(struct sctp_nr_sack_chunk) + 4937202526Stuexen (num_seg + num_nr_seg) * sizeof(struct sctp_gap_ack_block) + 4938202526Stuexen num_dup * sizeof(uint32_t) != chk_length) { 4939202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of NR_SACK chunk\n"); 4940202526Stuexen break; 4941202526Stuexen } 4942202526Stuexen offset_seg = *offset + sizeof(struct sctp_nr_sack_chunk); 4943202526Stuexen offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 4944185694Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 4945202526Stuexen cum_ack, num_seg, a_rwnd); 4946185694Srrs stcb->asoc.seen_a_sack_this_pkt = 1; 4947185694Srrs if ((stcb->asoc.pr_sctp_cnt == 0) && 4948202526Stuexen (num_seg == 0) && (num_nr_seg == 0) && 4949216825Stuexen SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 4950185694Srrs (stcb->asoc.saw_sack_with_frags == 0) && 4951216188Stuexen (stcb->asoc.saw_sack_with_nr_frags == 0) && 4952202526Stuexen (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 4953185694Srrs /* 4954185694Srrs * We have a SIMPLE sack having no 4955185694Srrs * prior segments and data on sent 4956202526Stuexen * queue to be acked. Use the faster 4957202526Stuexen * path sack processing. We also 4958202526Stuexen * allow window update sacks with no 4959202526Stuexen * missing segments to go this way 4960202526Stuexen * too. 4961185694Srrs */ 4962218129Srrs sctp_express_handle_sack(stcb, cum_ack, a_rwnd, 4963218186Srrs &abort_now, ecne_seen); 4964185694Srrs } else { 4965185694Srrs if (netp && *netp) 4966228653Stuexen sctp_handle_sack(m, offset_seg, offset_dup, stcb, 4967202526Stuexen num_seg, num_nr_seg, num_dup, &abort_now, flags, 4968218186Srrs cum_ack, a_rwnd, ecne_seen); 4969185694Srrs } 4970202526Stuexen if (abort_now) { 4971202526Stuexen /* ABORT signal from sack processing */ 4972202526Stuexen *offset = length; 4973202526Stuexen return (NULL); 4974202526Stuexen } 4975185694Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 4976185694Srrs TAILQ_EMPTY(&stcb->asoc.sent_queue) && 4977185694Srrs (stcb->asoc.stream_queue_cnt == 0)) { 4978185694Srrs sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 4979185694Srrs } 4980185694Srrs } 4981185694Srrs break; 4982185694Srrs 4983163953Srrs case SCTP_HEARTBEAT_REQUEST: 4984169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT\n"); 4985169420Srrs if ((stcb) && netp && *netp) { 4986169420Srrs SCTP_STAT_INCR(sctps_recvheartbeat); 4987169420Srrs sctp_send_heartbeat_ack(stcb, m, *offset, 4988169420Srrs chk_length, *netp); 4989169420Srrs 4990169420Srrs /* He's alive so give him credit */ 4991179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 4992171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 4993171943Srrs stcb->asoc.overall_error_count, 4994171943Srrs 0, 4995171943Srrs SCTP_FROM_SCTP_INPUT, 4996171943Srrs __LINE__); 4997171943Srrs } 4998169420Srrs stcb->asoc.overall_error_count = 0; 4999163953Srrs } 5000163953Srrs break; 5001163953Srrs case SCTP_HEARTBEAT_ACK: 5002169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT-ACK\n"); 5003169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_heartbeat_chunk))) { 5004169208Srrs /* Its not ours */ 5005169352Srrs *offset = length; 5006169378Srrs if (locked_tcb) { 5007169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5008169378Srrs } 5009169208Srrs return (NULL); 5010169208Srrs } 5011163953Srrs /* He's alive so give him credit */ 5012179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5013171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5014171943Srrs stcb->asoc.overall_error_count, 5015171943Srrs 0, 5016171943Srrs SCTP_FROM_SCTP_INPUT, 5017171943Srrs __LINE__); 5018171943Srrs } 5019163953Srrs stcb->asoc.overall_error_count = 0; 5020163953Srrs SCTP_STAT_INCR(sctps_recvheartbeatack); 5021169420Srrs if (netp && *netp) 5022169420Srrs sctp_handle_heartbeat_ack((struct sctp_heartbeat_chunk *)ch, 5023169420Srrs stcb, *netp); 5024163953Srrs break; 5025163953Srrs case SCTP_ABORT_ASSOCIATION: 5026170091Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT, stcb %p\n", 5027240148Stuexen (void *)stcb); 5028169420Srrs if ((stcb) && netp && *netp) 5029169420Srrs sctp_handle_abort((struct sctp_abort_chunk *)ch, 5030169420Srrs stcb, *netp); 5031163953Srrs *offset = length; 5032163953Srrs return (NULL); 5033163953Srrs break; 5034163953Srrs case SCTP_SHUTDOWN: 5035170091Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN, stcb %p\n", 5036240148Stuexen (void *)stcb); 5037169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_shutdown_chunk))) { 5038169208Srrs *offset = length; 5039169378Srrs if (locked_tcb) { 5040169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5041169378Srrs } 5042169208Srrs return (NULL); 5043169420Srrs } 5044169420Srrs if (netp && *netp) { 5045163953Srrs int abort_flag = 0; 5046163953Srrs 5047163953Srrs sctp_handle_shutdown((struct sctp_shutdown_chunk *)ch, 5048163953Srrs stcb, *netp, &abort_flag); 5049163953Srrs if (abort_flag) { 5050163953Srrs *offset = length; 5051163953Srrs return (NULL); 5052163953Srrs } 5053163953Srrs } 5054163953Srrs break; 5055163953Srrs case SCTP_SHUTDOWN_ACK: 5056240148Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", (void *)stcb); 5057169420Srrs if ((stcb) && (netp) && (*netp)) 5058169420Srrs sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp); 5059163953Srrs *offset = length; 5060163953Srrs return (NULL); 5061163953Srrs break; 5062169420Srrs 5063163953Srrs case SCTP_OPERATION_ERROR: 5064169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_OP-ERR\n"); 5065169420Srrs if ((stcb) && netp && *netp && sctp_handle_error(ch, stcb, *netp) < 0) { 5066163953Srrs *offset = length; 5067163953Srrs return (NULL); 5068163953Srrs } 5069163953Srrs break; 5070163953Srrs case SCTP_COOKIE_ECHO: 5071169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 5072240148Stuexen "SCTP_COOKIE-ECHO, stcb %p\n", (void *)stcb); 5073163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 5074163953Srrs ; 5075163953Srrs } else { 5076169420Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5077163953Srrs /* We are not interested anymore */ 5078208878Srrs abend: 5079208853Srrs if (stcb) { 5080208853Srrs SCTP_TCB_UNLOCK(stcb); 5081208853Srrs } 5082163953Srrs *offset = length; 5083163953Srrs return (NULL); 5084163953Srrs } 5085163953Srrs } 5086163953Srrs /* 5087163953Srrs * First are we accepting? We do this again here 5088207924Srrs * since it is possible that a previous endpoint WAS 5089207924Srrs * listening responded to a INIT-ACK and then 5090163953Srrs * closed. We opened and bound.. and are now no 5091163953Srrs * longer listening. 5092163953Srrs */ 5093172703Srrs 5094172703Srrs if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) { 5095172703Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 5096179783Srrs (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) { 5097267723Stuexen op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); 5098237715Stuexen sctp_abort_association(inp, stcb, m, iphlen, 5099237715Stuexen src, dst, sh, op_err, 5100237049Stuexen use_mflowid, mflowid, 5101237049Stuexen vrf_id, port); 5102163953Srrs } 5103172703Srrs *offset = length; 5104172703Srrs return (NULL); 5105172703Srrs } else { 5106163953Srrs struct mbuf *ret_buf; 5107165220Srrs struct sctp_inpcb *linp; 5108163953Srrs 5109169420Srrs if (stcb) { 5110165220Srrs linp = NULL; 5111169420Srrs } else { 5112165220Srrs linp = inp; 5113169420Srrs } 5114165220Srrs 5115169420Srrs if (linp) { 5116165220Srrs SCTP_ASOC_CREATE_LOCK(linp); 5117208878Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 5118208878Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 5119208878Srrs SCTP_ASOC_CREATE_UNLOCK(linp); 5120208878Srrs goto abend; 5121208878Srrs } 5122169420Srrs } 5123169420Srrs if (netp) { 5124169420Srrs ret_buf = 5125169420Srrs sctp_handle_cookie_echo(m, iphlen, 5126237715Stuexen *offset, 5127237715Stuexen src, dst, 5128237715Stuexen sh, 5129169420Srrs (struct sctp_cookie_echo_chunk *)ch, 5130169420Srrs &inp, &stcb, netp, 5131169420Srrs auth_skipped, 5132169420Srrs auth_offset, 5133169420Srrs auth_len, 5134169420Srrs &locked_tcb, 5135237049Stuexen use_mflowid, 5136237049Stuexen mflowid, 5137179157Srrs vrf_id, 5138179157Srrs port); 5139169420Srrs } else { 5140169420Srrs ret_buf = NULL; 5141169420Srrs } 5142169420Srrs if (linp) { 5143165220Srrs SCTP_ASOC_CREATE_UNLOCK(linp); 5144169420Srrs } 5145163953Srrs if (ret_buf == NULL) { 5146163953Srrs if (locked_tcb) { 5147163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5148163953Srrs } 5149169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 5150169420Srrs "GAK, null buffer\n"); 5151163953Srrs *offset = length; 5152163953Srrs return (NULL); 5153163953Srrs } 5154163953Srrs /* if AUTH skipped, see if it verified... */ 5155163953Srrs if (auth_skipped) { 5156163953Srrs got_auth = 1; 5157163953Srrs auth_skipped = 0; 5158163953Srrs } 5159163953Srrs if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) { 5160163953Srrs /* 5161163953Srrs * Restart the timer if we have 5162163953Srrs * pending data 5163163953Srrs */ 5164163953Srrs struct sctp_tmit_chunk *chk; 5165163953Srrs 5166163953Srrs chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 5167216822Stuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 5168163953Srrs } 5169163953Srrs } 5170163953Srrs break; 5171163953Srrs case SCTP_COOKIE_ACK: 5172240148Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", (void *)stcb); 5173169420Srrs if ((stcb == NULL) || chk_length != sizeof(struct sctp_cookie_ack_chunk)) { 5174169378Srrs if (locked_tcb) { 5175169352Srrs SCTP_TCB_UNLOCK(locked_tcb); 5176169378Srrs } 5177169352Srrs return (NULL); 5178169352Srrs } 5179163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5180163953Srrs /* We are not interested anymore */ 5181163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 5182163953Srrs ; 5183169420Srrs } else if (stcb) { 5184237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5185172090Srrs so = SCTP_INP_SO(inp); 5186172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5187172090Srrs SCTP_TCB_UNLOCK(stcb); 5188172090Srrs SCTP_SOCKET_LOCK(so, 1); 5189172090Srrs SCTP_TCB_LOCK(stcb); 5190172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 5191172090Srrs#endif 5192171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27); 5193237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5194172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 5195172090Srrs#endif 5196163953Srrs *offset = length; 5197163953Srrs return (NULL); 5198163953Srrs } 5199163953Srrs } 5200163953Srrs /* He's alive so give him credit */ 5201169420Srrs if ((stcb) && netp && *netp) { 5202179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5203171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5204171943Srrs stcb->asoc.overall_error_count, 5205171943Srrs 0, 5206171943Srrs SCTP_FROM_SCTP_INPUT, 5207171943Srrs __LINE__); 5208171943Srrs } 5209169378Srrs stcb->asoc.overall_error_count = 0; 5210169378Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, *netp); 5211169378Srrs } 5212163953Srrs break; 5213163953Srrs case SCTP_ECN_ECHO: 5214169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-ECHO\n"); 5215163953Srrs /* He's alive so give him credit */ 5216169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_ecne_chunk))) { 5217169208Srrs /* Its not ours */ 5218169378Srrs if (locked_tcb) { 5219169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5220169378Srrs } 5221169208Srrs *offset = length; 5222169208Srrs return (NULL); 5223169208Srrs } 5224169378Srrs if (stcb) { 5225179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5226171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5227171943Srrs stcb->asoc.overall_error_count, 5228171943Srrs 0, 5229171943Srrs SCTP_FROM_SCTP_INPUT, 5230171943Srrs __LINE__); 5231171943Srrs } 5232169378Srrs stcb->asoc.overall_error_count = 0; 5233169378Srrs sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch, 5234169378Srrs stcb); 5235218186Srrs ecne_seen = 1; 5236169378Srrs } 5237163953Srrs break; 5238163953Srrs case SCTP_ECN_CWR: 5239169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-CWR\n"); 5240163953Srrs /* He's alive so give him credit */ 5241169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_cwr_chunk))) { 5242169208Srrs /* Its not ours */ 5243169378Srrs if (locked_tcb) { 5244169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5245169378Srrs } 5246169208Srrs *offset = length; 5247169208Srrs return (NULL); 5248169208Srrs } 5249169378Srrs if (stcb) { 5250179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5251171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5252171943Srrs stcb->asoc.overall_error_count, 5253171943Srrs 0, 5254171943Srrs SCTP_FROM_SCTP_INPUT, 5255171943Srrs __LINE__); 5256171943Srrs } 5257169378Srrs stcb->asoc.overall_error_count = 0; 5258218072Srrs sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb, *netp); 5259169378Srrs } 5260163953Srrs break; 5261163953Srrs case SCTP_SHUTDOWN_COMPLETE: 5262240148Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", (void *)stcb); 5263163953Srrs /* must be first and only chunk */ 5264163953Srrs if ((num_chunks > 1) || 5265170140Srrs (length - *offset > (int)SCTP_SIZE32(chk_length))) { 5266163953Srrs *offset = length; 5267169378Srrs if (locked_tcb) { 5268163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5269169378Srrs } 5270163953Srrs return (NULL); 5271163953Srrs } 5272169420Srrs if ((stcb) && netp && *netp) { 5273169378Srrs sctp_handle_shutdown_complete((struct sctp_shutdown_complete_chunk *)ch, 5274169378Srrs stcb, *netp); 5275169378Srrs } 5276163953Srrs *offset = length; 5277163953Srrs return (NULL); 5278163953Srrs break; 5279163953Srrs case SCTP_ASCONF: 5280169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n"); 5281163953Srrs /* He's alive so give him credit */ 5282169378Srrs if (stcb) { 5283179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5284171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5285171943Srrs stcb->asoc.overall_error_count, 5286171943Srrs 0, 5287171943Srrs SCTP_FROM_SCTP_INPUT, 5288171943Srrs __LINE__); 5289171943Srrs } 5290169378Srrs stcb->asoc.overall_error_count = 0; 5291237715Stuexen sctp_handle_asconf(m, *offset, src, 5292171990Srrs (struct sctp_asconf_chunk *)ch, stcb, asconf_cnt == 0); 5293171990Srrs asconf_cnt++; 5294169378Srrs } 5295163953Srrs break; 5296163953Srrs case SCTP_ASCONF_ACK: 5297169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF-ACK\n"); 5298169208Srrs if (chk_length < sizeof(struct sctp_asconf_ack_chunk)) { 5299169208Srrs /* Its not ours */ 5300169378Srrs if (locked_tcb) { 5301169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5302169378Srrs } 5303169208Srrs *offset = length; 5304169208Srrs return (NULL); 5305169208Srrs } 5306169420Srrs if ((stcb) && netp && *netp) { 5307169378Srrs /* He's alive so give him credit */ 5308179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5309171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5310171943Srrs stcb->asoc.overall_error_count, 5311171943Srrs 0, 5312171943Srrs SCTP_FROM_SCTP_INPUT, 5313171943Srrs __LINE__); 5314171943Srrs } 5315169378Srrs stcb->asoc.overall_error_count = 0; 5316169378Srrs sctp_handle_asconf_ack(m, *offset, 5317172190Srrs (struct sctp_asconf_ack_chunk *)ch, stcb, *netp, &abort_no_unlock); 5318172190Srrs if (abort_no_unlock) 5319172190Srrs return (NULL); 5320169378Srrs } 5321163953Srrs break; 5322163953Srrs case SCTP_FORWARD_CUM_TSN: 5323169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_FWD-TSN\n"); 5324169208Srrs if (chk_length < sizeof(struct sctp_forward_tsn_chunk)) { 5325169208Srrs /* Its not ours */ 5326169378Srrs if (locked_tcb) { 5327169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5328169378Srrs } 5329169208Srrs *offset = length; 5330169208Srrs return (NULL); 5331169208Srrs } 5332163953Srrs /* He's alive so give him credit */ 5333169378Srrs if (stcb) { 5334163953Srrs int abort_flag = 0; 5335163953Srrs 5336163953Srrs stcb->asoc.overall_error_count = 0; 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 } 5344163953Srrs *fwd_tsn_seen = 1; 5345163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5346163953Srrs /* We are not interested anymore */ 5347237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5348172090Srrs so = SCTP_INP_SO(inp); 5349172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5350172090Srrs SCTP_TCB_UNLOCK(stcb); 5351172090Srrs SCTP_SOCKET_LOCK(so, 1); 5352172090Srrs SCTP_TCB_LOCK(stcb); 5353172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 5354172090Srrs#endif 5355171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_29); 5356237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5357172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 5358172090Srrs#endif 5359163953Srrs *offset = length; 5360163953Srrs return (NULL); 5361163953Srrs } 5362163953Srrs sctp_handle_forward_tsn(stcb, 5363170992Srrs (struct sctp_forward_tsn_chunk *)ch, &abort_flag, m, *offset); 5364163953Srrs if (abort_flag) { 5365163953Srrs *offset = length; 5366163953Srrs return (NULL); 5367163953Srrs } else { 5368179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5369171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5370171943Srrs stcb->asoc.overall_error_count, 5371171943Srrs 0, 5372171943Srrs SCTP_FROM_SCTP_INPUT, 5373171943Srrs __LINE__); 5374171943Srrs } 5375163953Srrs stcb->asoc.overall_error_count = 0; 5376163953Srrs } 5377163953Srrs 5378163953Srrs } 5379163953Srrs break; 5380163953Srrs case SCTP_STREAM_RESET: 5381169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_STREAM_RESET\n"); 5382169420Srrs if (((stcb == NULL) || (ch == NULL) || (chk_length < sizeof(struct sctp_stream_reset_tsn_req)))) { 5383169208Srrs /* Its not ours */ 5384169378Srrs if (locked_tcb) { 5385169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5386169378Srrs } 5387169208Srrs *offset = length; 5388169208Srrs return (NULL); 5389169208Srrs } 5390169420Srrs if (stcb->asoc.peer_supports_strreset == 0) { 5391169420Srrs /* 5392169420Srrs * hmm, peer should have announced this, but 5393169420Srrs * we will turn it on since he is sending us 5394169420Srrs * a stream reset. 5395169420Srrs */ 5396169420Srrs stcb->asoc.peer_supports_strreset = 1; 5397163953Srrs } 5398240198Stuexen if (sctp_handle_stream_reset(stcb, m, *offset, ch)) { 5399169420Srrs /* stop processing */ 5400169420Srrs *offset = length; 5401169420Srrs return (NULL); 5402169420Srrs } 5403163953Srrs break; 5404163953Srrs case SCTP_PACKET_DROPPED: 5405169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_PACKET_DROPPED\n"); 5406163953Srrs /* re-get it all please */ 5407169208Srrs if (chk_length < sizeof(struct sctp_pktdrop_chunk)) { 5408169208Srrs /* Its not ours */ 5409169378Srrs if (locked_tcb) { 5410169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5411169378Srrs } 5412169208Srrs *offset = length; 5413169208Srrs return (NULL); 5414169208Srrs } 5415169420Srrs if (ch && (stcb) && netp && (*netp)) { 5416169378Srrs sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch, 5417170781Srrs stcb, *netp, 5418170781Srrs min(chk_length, (sizeof(chunk_buf) - 4))); 5419170781Srrs 5420169378Srrs } 5421163953Srrs break; 5422163953Srrs 5423163953Srrs case SCTP_AUTHENTICATION: 5424169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n"); 5425179783Srrs if (SCTP_BASE_SYSCTL(sctp_auth_disable)) 5426163953Srrs goto unknown_chunk; 5427163953Srrs 5428163953Srrs if (stcb == NULL) { 5429163953Srrs /* save the first AUTH for later processing */ 5430163953Srrs if (auth_skipped == 0) { 5431163953Srrs auth_offset = *offset; 5432163953Srrs auth_len = chk_length; 5433163953Srrs auth_skipped = 1; 5434163953Srrs } 5435163953Srrs /* skip this chunk (temporarily) */ 5436163953Srrs goto next_chunk; 5437163953Srrs } 5438169208Srrs if ((chk_length < (sizeof(struct sctp_auth_chunk))) || 5439169420Srrs (chk_length > (sizeof(struct sctp_auth_chunk) + 5440169420Srrs SCTP_AUTH_DIGEST_LEN_MAX))) { 5441169208Srrs /* Its not ours */ 5442169378Srrs if (locked_tcb) { 5443169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5444169378Srrs } 5445169208Srrs *offset = length; 5446169208Srrs return (NULL); 5447169208Srrs } 5448163953Srrs if (got_auth == 1) { 5449163953Srrs /* skip this chunk... it's already auth'd */ 5450163953Srrs goto next_chunk; 5451163953Srrs } 5452163953Srrs got_auth = 1; 5453169420Srrs if ((ch == NULL) || sctp_handle_auth(stcb, (struct sctp_auth_chunk *)ch, 5454163953Srrs m, *offset)) { 5455163953Srrs /* auth HMAC failed so dump the packet */ 5456163953Srrs *offset = length; 5457163953Srrs return (stcb); 5458163953Srrs } else { 5459163953Srrs /* remaining chunks are HMAC checked */ 5460163953Srrs stcb->asoc.authenticated = 1; 5461163953Srrs } 5462163953Srrs break; 5463163953Srrs 5464163953Srrs default: 5465163953Srrs unknown_chunk: 5466163953Srrs /* it's an unknown chunk! */ 5467163953Srrs if ((ch->chunk_type & 0x40) && (stcb != NULL)) { 5468163953Srrs struct mbuf *mm; 5469163953Srrs struct sctp_paramhdr *phd; 5470163953Srrs 5471163953Srrs mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 5472243882Sglebius 0, M_NOWAIT, 1, MT_DATA); 5473163953Srrs if (mm) { 5474163953Srrs phd = mtod(mm, struct sctp_paramhdr *); 5475163953Srrs /* 5476163953Srrs * We cheat and use param type since 5477163953Srrs * we did not bother to define a 5478163953Srrs * error cause struct. They are the 5479163953Srrs * same basic format with different 5480163953Srrs * names. 5481163953Srrs */ 5482163953Srrs phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK); 5483163953Srrs phd->param_length = htons(chk_length + sizeof(*phd)); 5484165647Srrs SCTP_BUF_LEN(mm) = sizeof(*phd); 5485243882Sglebius SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); 5486165647Srrs if (SCTP_BUF_NEXT(mm)) { 5487270354Stuexen if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) { 5488234459Stuexen sctp_m_freem(mm); 5489234459Stuexen } else { 5490178202Srrs#ifdef SCTP_MBUF_LOGGING 5491234459Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 5492234459Stuexen struct mbuf *mat; 5493178202Srrs 5494234461Stuexen for (mat = SCTP_BUF_NEXT(mm); mat; mat = SCTP_BUF_NEXT(mat)) { 5495234459Stuexen if (SCTP_BUF_IS_EXTENDED(mat)) { 5496234459Stuexen sctp_log_mb(mat, SCTP_MBUF_ICOPY); 5497234459Stuexen } 5498178202Srrs } 5499178202Srrs } 5500234459Stuexen#endif 5501234459Stuexen sctp_queue_op_err(stcb, mm); 5502178202Srrs } 5503163953Srrs } else { 5504163953Srrs sctp_m_freem(mm); 5505163953Srrs } 5506163953Srrs } 5507163953Srrs } 5508163953Srrs if ((ch->chunk_type & 0x80) == 0) { 5509163953Srrs /* discard this packet */ 5510163953Srrs *offset = length; 5511163953Srrs return (stcb); 5512163953Srrs } /* else skip this bad chunk and continue... */ 5513163953Srrs break; 5514163953Srrs } /* switch (ch->chunk_type) */ 5515163953Srrs 5516163953Srrs 5517163953Srrsnext_chunk: 5518163953Srrs /* get the next chunk */ 5519163953Srrs *offset += SCTP_SIZE32(chk_length); 5520163953Srrs if (*offset >= length) { 5521163953Srrs /* no more data left in the mbuf chain */ 5522163953Srrs break; 5523163953Srrs } 5524163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 5525163953Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 5526163953Srrs if (ch == NULL) { 5527169378Srrs if (locked_tcb) { 5528163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5529169378Srrs } 5530163953Srrs *offset = length; 5531163953Srrs return (NULL); 5532163953Srrs } 5533163953Srrs } /* while */ 5534171990Srrs 5535171990Srrs if (asconf_cnt > 0 && stcb != NULL) { 5536171990Srrs sctp_send_asconf_ack(stcb); 5537171990Srrs } 5538163953Srrs return (stcb); 5539163953Srrs} 5540163953Srrs 5541163953Srrs 5542171440Srrs#ifdef INVARIANTS 5543208853Srrs#ifdef __GNUC__ 5544208853Srrs__attribute__((noinline)) 5545208853Srrs#endif 5546208853Srrs void 5547208853Srrs sctp_validate_no_locks(struct sctp_inpcb *inp) 5548171440Srrs{ 5549208853Srrs struct sctp_tcb *lstcb; 5550171440Srrs 5551208853Srrs LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) { 5552208853Srrs if (mtx_owned(&lstcb->tcb_mtx)) { 5553171440Srrs panic("Own lock on stcb at return from input"); 5554171440Srrs } 5555171440Srrs } 5556208876Srrs if (mtx_owned(&inp->inp_create_mtx)) { 5557208876Srrs panic("Own create lock on inp"); 5558208876Srrs } 5559208876Srrs if (mtx_owned(&inp->inp_mtx)) { 5560208876Srrs panic("Own inp lock on inp"); 5561208876Srrs } 5562171440Srrs} 5563171440Srrs 5564171440Srrs#endif 5565171440Srrs 5566163953Srrs/* 5567163953Srrs * common input chunk processing (v4 and v6) 5568163953Srrs */ 5569169378Srrsvoid 5570237715Stuexensctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int length, 5571237715Stuexen struct sockaddr *src, struct sockaddr *dst, 5572237715Stuexen struct sctphdr *sh, struct sctp_chunkhdr *ch, 5573238003Stuexen#if !defined(SCTP_WITH_NO_CSUM) 5574238003Stuexen uint8_t compute_crc, 5575238003Stuexen#endif 5576238003Stuexen uint8_t ecn_bits, 5577237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 5578237049Stuexen uint32_t vrf_id, uint16_t port) 5579163953Srrs{ 5580163953Srrs uint32_t high_tsn; 5581163953Srrs int fwd_tsn_seen = 0, data_processed = 0; 5582267723Stuexen struct mbuf *m = *mm, *op_err; 5583267723Stuexen char msg[SCTP_DIAG_INFO_LEN]; 5584163953Srrs int un_sent; 5585218129Srrs int cnt_ctrl_ready = 0; 5586239091Stuexen struct sctp_inpcb *inp = NULL, *inp_decr = NULL; 5587238003Stuexen struct sctp_tcb *stcb = NULL; 5588238087Stuexen struct sctp_nets *net = NULL; 5589163953Srrs 5590163953Srrs SCTP_STAT_INCR(sctps_recvdatagrams); 5591163953Srrs#ifdef SCTP_AUDITING_ENABLED 5592163953Srrs sctp_audit_log(0xE0, 1); 5593163953Srrs sctp_auditing(0, inp, stcb, net); 5594163953Srrs#endif 5595238003Stuexen#if !defined(SCTP_WITH_NO_CSUM) 5596238003Stuexen if (compute_crc != 0) { 5597238003Stuexen uint32_t check, calc_check; 5598163953Srrs 5599238003Stuexen check = sh->checksum; 5600238003Stuexen sh->checksum = 0; 5601238003Stuexen calc_check = sctp_calculate_cksum(m, iphlen); 5602238003Stuexen sh->checksum = check; 5603238003Stuexen if (calc_check != check) { 5604238003Stuexen SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n", 5605240148Stuexen calc_check, check, (void *)m, length, iphlen); 5606238003Stuexen stcb = sctp_findassociation_addr(m, offset, src, dst, 5607238003Stuexen sh, ch, &inp, &net, vrf_id); 5608270350Stuexen#if defined(INET) || defined(INET6) 5609238003Stuexen if ((net != NULL) && (port != 0)) { 5610238003Stuexen if (net->port == 0) { 5611238003Stuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 5612238003Stuexen } 5613238003Stuexen net->port = port; 5614238003Stuexen } 5615270350Stuexen#endif 5616238003Stuexen if ((net != NULL) && (use_mflowid != 0)) { 5617238003Stuexen net->flowid = mflowid; 5618238003Stuexen#ifdef INVARIANTS 5619238003Stuexen net->flowidset = 1; 5620238003Stuexen#endif 5621238003Stuexen } 5622238003Stuexen if ((inp != NULL) && (stcb != NULL)) { 5623238003Stuexen sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1); 5624238003Stuexen sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED); 5625238003Stuexen } else if ((inp != NULL) && (stcb == NULL)) { 5626238003Stuexen inp_decr = inp; 5627238003Stuexen } 5628238003Stuexen SCTP_STAT_INCR(sctps_badsum); 5629238003Stuexen SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors); 5630238003Stuexen goto out; 5631238003Stuexen } 5632238003Stuexen } 5633238003Stuexen#endif 5634238003Stuexen /* Destination port of 0 is illegal, based on RFC4960. */ 5635238003Stuexen if (sh->dest_port == 0) { 5636238003Stuexen SCTP_STAT_INCR(sctps_hdrops); 5637238003Stuexen goto out; 5638238003Stuexen } 5639238003Stuexen stcb = sctp_findassociation_addr(m, offset, src, dst, 5640238003Stuexen sh, ch, &inp, &net, vrf_id); 5641270350Stuexen#if defined(INET) || defined(INET6) 5642238003Stuexen if ((net != NULL) && (port != 0)) { 5643238003Stuexen if (net->port == 0) { 5644238003Stuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 5645238003Stuexen } 5646238003Stuexen net->port = port; 5647238003Stuexen } 5648270350Stuexen#endif 5649238003Stuexen if ((net != NULL) && (use_mflowid != 0)) { 5650238003Stuexen net->flowid = mflowid; 5651238003Stuexen#ifdef INVARIANTS 5652238003Stuexen net->flowidset = 1; 5653238003Stuexen#endif 5654238003Stuexen } 5655238003Stuexen if (inp == NULL) { 5656238003Stuexen SCTP_STAT_INCR(sctps_noport); 5657238003Stuexen if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) { 5658238003Stuexen goto out; 5659238003Stuexen } 5660238003Stuexen if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 5661238003Stuexen sctp_send_shutdown_complete2(src, dst, sh, 5662238003Stuexen use_mflowid, mflowid, 5663238003Stuexen vrf_id, port); 5664238003Stuexen goto out; 5665238003Stuexen } 5666238003Stuexen if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) { 5667238003Stuexen goto out; 5668238003Stuexen } 5669238003Stuexen if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) { 5670238003Stuexen if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || 5671238003Stuexen ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && 5672238003Stuexen (ch->chunk_type != SCTP_INIT))) { 5673267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5674267723Stuexen "Out of the blue"); 5675238003Stuexen sctp_send_abort(m, iphlen, src, dst, 5676267723Stuexen sh, 0, op_err, 5677238003Stuexen use_mflowid, mflowid, 5678238003Stuexen vrf_id, port); 5679238003Stuexen } 5680238003Stuexen } 5681238003Stuexen goto out; 5682238003Stuexen } else if (stcb == NULL) { 5683238003Stuexen inp_decr = inp; 5684238003Stuexen } 5685238003Stuexen#ifdef IPSEC 5686238003Stuexen /*- 5687238003Stuexen * I very much doubt any of the IPSEC stuff will work but I have no 5688238003Stuexen * idea, so I will leave it in place. 5689238003Stuexen */ 5690238003Stuexen if (inp != NULL) { 5691238003Stuexen switch (dst->sa_family) { 5692238003Stuexen#ifdef INET 5693238003Stuexen case AF_INET: 5694238003Stuexen if (ipsec4_in_reject(m, &inp->ip_inp.inp)) { 5695253571Sae IPSECSTAT_INC(ips_in_polvio); 5696238003Stuexen SCTP_STAT_INCR(sctps_hdrops); 5697238003Stuexen goto out; 5698238003Stuexen } 5699238003Stuexen break; 5700238003Stuexen#endif 5701238003Stuexen#ifdef INET6 5702238003Stuexen case AF_INET6: 5703238003Stuexen if (ipsec6_in_reject(m, &inp->ip_inp.inp)) { 5704253571Sae IPSEC6STAT_INC(ips_in_polvio); 5705238003Stuexen SCTP_STAT_INCR(sctps_hdrops); 5706238003Stuexen goto out; 5707238003Stuexen } 5708238003Stuexen break; 5709238003Stuexen#endif 5710238003Stuexen default: 5711238003Stuexen break; 5712238003Stuexen } 5713238003Stuexen } 5714238003Stuexen#endif 5715179783Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n", 5716240148Stuexen (void *)m, iphlen, offset, length, (void *)stcb); 5717163953Srrs if (stcb) { 5718163953Srrs /* always clear this before beginning a packet */ 5719163953Srrs stcb->asoc.authenticated = 0; 5720163953Srrs stcb->asoc.seen_a_sack_this_pkt = 0; 5721171990Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "stcb:%p state:%x\n", 5722240148Stuexen (void *)stcb, stcb->asoc.state); 5723171990Srrs 5724171943Srrs if ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) || 5725171943Srrs (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) { 5726171745Srrs /*- 5727171745Srrs * If we hit here, we had a ref count 5728171745Srrs * up when the assoc was aborted and the 5729171745Srrs * timer is clearing out the assoc, we should 5730171745Srrs * NOT respond to any packet.. its OOTB. 5731171745Srrs */ 5732171745Srrs SCTP_TCB_UNLOCK(stcb); 5733238003Stuexen stcb = NULL; 5734267723Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 5735267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5736267723Stuexen msg); 5737267723Stuexen sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 5738237049Stuexen use_mflowid, mflowid, 5739179157Srrs vrf_id, port); 5740238003Stuexen goto out; 5741171745Srrs } 5742163953Srrs } 5743163953Srrs if (IS_SCTP_CONTROL(ch)) { 5744163953Srrs /* process the control portion of the SCTP packet */ 5745169655Srrs /* sa_ignore NO_NULL_CHK */ 5746237715Stuexen stcb = sctp_process_control(m, iphlen, &offset, length, 5747237715Stuexen src, dst, sh, ch, 5748237049Stuexen inp, stcb, &net, &fwd_tsn_seen, 5749237049Stuexen use_mflowid, mflowid, 5750237049Stuexen vrf_id, port); 5751163953Srrs if (stcb) { 5752163953Srrs /* 5753163953Srrs * This covers us if the cookie-echo was there and 5754163953Srrs * it changes our INP. 5755163953Srrs */ 5756163953Srrs inp = stcb->sctp_ep; 5757270350Stuexen#if defined(INET) || defined(INET6) 5758179783Srrs if ((net) && (port)) { 5759179783Srrs if (net->port == 0) { 5760228653Stuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 5761179783Srrs } 5762179783Srrs net->port = port; 5763179783Srrs } 5764270350Stuexen#endif 5765163953Srrs } 5766163953Srrs } else { 5767163953Srrs /* 5768163953Srrs * no control chunks, so pre-process DATA chunks (these 5769163953Srrs * checks are taken care of by control processing) 5770163953Srrs */ 5771163953Srrs 5772163953Srrs /* 5773163953Srrs * if DATA only packet, and auth is required, then punt... 5774163953Srrs * can't have authenticated without any AUTH (control) 5775163953Srrs * chunks 5776163953Srrs */ 5777179783Srrs if ((stcb != NULL) && 5778179783Srrs !SCTP_BASE_SYSCTL(sctp_auth_disable) && 5779179783Srrs sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) { 5780163953Srrs /* "silently" ignore */ 5781163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 5782238003Stuexen goto out; 5783163953Srrs } 5784163953Srrs if (stcb == NULL) { 5785163953Srrs /* out of the blue DATA chunk */ 5786267723Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 5787267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5788267723Stuexen msg); 5789267723Stuexen sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 5790237049Stuexen use_mflowid, mflowid, 5791179157Srrs vrf_id, port); 5792238003Stuexen goto out; 5793163953Srrs } 5794163953Srrs if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) { 5795163953Srrs /* v_tag mismatch! */ 5796163953Srrs SCTP_STAT_INCR(sctps_badvtag); 5797238003Stuexen goto out; 5798163953Srrs } 5799163953Srrs } 5800163953Srrs 5801163953Srrs if (stcb == NULL) { 5802163953Srrs /* 5803163953Srrs * no valid TCB for this packet, or we found it's a bad 5804163953Srrs * packet while processing control, or we're done with this 5805163953Srrs * packet (done or skip rest of data), so we drop it... 5806163953Srrs */ 5807238003Stuexen goto out; 5808163953Srrs } 5809163953Srrs /* 5810163953Srrs * DATA chunk processing 5811163953Srrs */ 5812163953Srrs /* plow through the data chunks while length > offset */ 5813163953Srrs 5814163953Srrs /* 5815163953Srrs * Rest should be DATA only. Check authentication state if AUTH for 5816163953Srrs * DATA is required. 5817163953Srrs */ 5818179783Srrs if ((length > offset) && 5819179783Srrs (stcb != NULL) && 5820179783Srrs !SCTP_BASE_SYSCTL(sctp_auth_disable) && 5821179783Srrs sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) && 5822163953Srrs !stcb->asoc.authenticated) { 5823163953Srrs /* "silently" ignore */ 5824163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 5825169420Srrs SCTPDBG(SCTP_DEBUG_AUTH1, 5826169420Srrs "Data chunk requires AUTH, skipped\n"); 5827165220Srrs goto trigger_send; 5828163953Srrs } 5829163953Srrs if (length > offset) { 5830163953Srrs int retval; 5831163953Srrs 5832163953Srrs /* 5833163953Srrs * First check to make sure our state is correct. We would 5834163953Srrs * not get here unless we really did have a tag, so we don't 5835163953Srrs * abort if this happens, just dump the chunk silently. 5836163953Srrs */ 5837163953Srrs switch (SCTP_GET_STATE(&stcb->asoc)) { 5838163953Srrs case SCTP_STATE_COOKIE_ECHOED: 5839163953Srrs /* 5840163953Srrs * we consider data with valid tags in this state 5841163953Srrs * shows us the cookie-ack was lost. Imply it was 5842163953Srrs * there. 5843163953Srrs */ 5844179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5845171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5846171943Srrs stcb->asoc.overall_error_count, 5847171943Srrs 0, 5848171943Srrs SCTP_FROM_SCTP_INPUT, 5849171943Srrs __LINE__); 5850171943Srrs } 5851163953Srrs stcb->asoc.overall_error_count = 0; 5852163953Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, net); 5853163953Srrs break; 5854163953Srrs case SCTP_STATE_COOKIE_WAIT: 5855163953Srrs /* 5856163953Srrs * We consider OOTB any data sent during asoc setup. 5857163953Srrs */ 5858267723Stuexen snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); 5859267723Stuexen op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), 5860267723Stuexen msg); 5861267723Stuexen sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, 5862237049Stuexen use_mflowid, mflowid, 5863179157Srrs vrf_id, port); 5864238003Stuexen goto out; 5865171531Srrs /* sa_ignore NOTREACHED */ 5866163953Srrs break; 5867163953Srrs case SCTP_STATE_EMPTY: /* should not happen */ 5868163953Srrs case SCTP_STATE_INUSE: /* should not happen */ 5869163953Srrs case SCTP_STATE_SHUTDOWN_RECEIVED: /* This is a peer error */ 5870163953Srrs case SCTP_STATE_SHUTDOWN_ACK_SENT: 5871163953Srrs default: 5872238003Stuexen goto out; 5873171531Srrs /* sa_ignore NOTREACHED */ 5874163953Srrs break; 5875163953Srrs case SCTP_STATE_OPEN: 5876163953Srrs case SCTP_STATE_SHUTDOWN_SENT: 5877163953Srrs break; 5878163953Srrs } 5879163953Srrs /* plow through the data chunks while length > offset */ 5880237715Stuexen retval = sctp_process_data(mm, iphlen, &offset, length, 5881237715Stuexen src, dst, sh, 5882237049Stuexen inp, stcb, net, &high_tsn, 5883237049Stuexen use_mflowid, mflowid, 5884237049Stuexen vrf_id, port); 5885163953Srrs if (retval == 2) { 5886163953Srrs /* 5887163953Srrs * The association aborted, NO UNLOCK needed since 5888163953Srrs * the association is destroyed. 5889163953Srrs */ 5890238003Stuexen stcb = NULL; 5891238003Stuexen goto out; 5892163953Srrs } 5893163953Srrs data_processed = 1; 5894163953Srrs /* 5895163953Srrs * Anything important needs to have been m_copy'ed in 5896163953Srrs * process_data 5897163953Srrs */ 5898163953Srrs } 5899218129Srrs /* take care of ecn */ 5900228907Stuexen if ((data_processed == 1) && 5901228907Stuexen (stcb->asoc.ecn_allowed == 1) && 5902218235Stuexen ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) { 5903218129Srrs /* Yep, we need to add a ECNE */ 5904218129Srrs sctp_send_ecn_echo(stcb, net, high_tsn); 5905218129Srrs } 5906163953Srrs if ((data_processed == 0) && (fwd_tsn_seen)) { 5907216495Stuexen int was_a_gap; 5908216495Stuexen uint32_t highest_tsn; 5909163953Srrs 5910216825Stuexen if (SCTP_TSN_GT(stcb->asoc.highest_tsn_inside_nr_map, stcb->asoc.highest_tsn_inside_map)) { 5911216495Stuexen highest_tsn = stcb->asoc.highest_tsn_inside_nr_map; 5912216495Stuexen } else { 5913216495Stuexen highest_tsn = stcb->asoc.highest_tsn_inside_map; 5914163953Srrs } 5915216825Stuexen was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn); 5916190689Srrs stcb->asoc.send_sack = 1; 5917228653Stuexen sctp_sack_check(stcb, was_a_gap); 5918190689Srrs } else if (fwd_tsn_seen) { 5919190689Srrs stcb->asoc.send_sack = 1; 5920163953Srrs } 5921163953Srrs /* trigger send of any chunks in queue... */ 5922165220Srrstrigger_send: 5923163953Srrs#ifdef SCTP_AUDITING_ENABLED 5924163953Srrs sctp_audit_log(0xE0, 2); 5925163953Srrs sctp_auditing(1, inp, stcb, net); 5926163953Srrs#endif 5927169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 5928169420Srrs "Check for chunk output prw:%d tqe:%d tf=%d\n", 5929169420Srrs stcb->asoc.peers_rwnd, 5930169420Srrs TAILQ_EMPTY(&stcb->asoc.control_send_queue), 5931169420Srrs stcb->asoc.total_flight); 5932163953Srrs un_sent = (stcb->asoc.total_output_queue_size - stcb->asoc.total_flight); 5933218129Srrs if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 5934218129Srrs cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq; 5935218129Srrs } 5936218129Srrs if (cnt_ctrl_ready || 5937163953Srrs ((un_sent) && 5938163953Srrs (stcb->asoc.peers_rwnd > 0 || 5939163953Srrs (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) { 5940169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "Calling chunk OUTPUT\n"); 5941172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 5942169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "chunk OUTPUT returns\n"); 5943163953Srrs } 5944163953Srrs#ifdef SCTP_AUDITING_ENABLED 5945163953Srrs sctp_audit_log(0xE0, 3); 5946163953Srrs sctp_auditing(2, inp, stcb, net); 5947163953Srrs#endif 5948238003Stuexenout: 5949238003Stuexen if (stcb != NULL) { 5950238003Stuexen SCTP_TCB_UNLOCK(stcb); 5951238003Stuexen } 5952238003Stuexen if (inp_decr != NULL) { 5953238003Stuexen /* reduce ref-count */ 5954238003Stuexen SCTP_INP_WLOCK(inp_decr); 5955238003Stuexen SCTP_INP_DECR_REF(inp_decr); 5956238003Stuexen SCTP_INP_WUNLOCK(inp_decr); 5957238003Stuexen } 5958171440Srrs#ifdef INVARIANTS 5959238003Stuexen if (inp != NULL) { 5960238003Stuexen sctp_validate_no_locks(inp); 5961238003Stuexen } 5962171440Srrs#endif 5963169378Srrs return; 5964163953Srrs} 5965163953Srrs 5966185694Srrs#if 0 5967185694Srrsstatic void 5968185694Srrssctp_print_mbuf_chain(struct mbuf *m) 5969185694Srrs{ 5970185694Srrs for (; m; m = SCTP_BUF_NEXT(m)) { 5971240148Stuexen SCTP_PRINTF("%p: m_len = %ld\n", (void *)m, SCTP_BUF_LEN(m)); 5972185694Srrs if (SCTP_BUF_IS_EXTENDED(m)) 5973240148Stuexen SCTP_PRINTF("%p: extend_size = %d\n", (void *)m, SCTP_BUF_EXTEND_SIZE(m)); 5974185694Srrs } 5975185694Srrs} 5976163953Srrs 5977185694Srrs#endif 5978185694Srrs 5979221249Stuexen#ifdef INET 5980163953Srrsvoid 5981189004Srdivackysctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) 5982163953Srrs{ 5983165647Srrs struct mbuf *m; 5984163953Srrs int iphlen; 5985170181Srrs uint32_t vrf_id = 0; 5986163953Srrs uint8_t ecn_bits; 5987237715Stuexen struct sockaddr_in src, dst; 5988163953Srrs struct ip *ip; 5989163953Srrs struct sctphdr *sh; 5990237569Stuexen struct sctp_chunkhdr *ch; 5991237569Stuexen int length, offset; 5992163953Srrs 5993211969Stuexen#if !defined(SCTP_WITH_NO_CSUM) 5994238003Stuexen uint8_t compute_crc; 5995211969Stuexen 5996211969Stuexen#endif 5997238003Stuexen uint32_t mflowid; 5998238003Stuexen uint8_t use_mflowid; 5999211969Stuexen 6000237569Stuexen iphlen = off; 6001169352Srrs if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) { 6002169352Srrs SCTP_RELEASE_PKT(i_pak); 6003169352Srrs return; 6004169352Srrs } 6005165647Srrs m = SCTP_HEADER_TO_CHAIN(i_pak); 6006163953Srrs#ifdef SCTP_MBUF_LOGGING 6007163953Srrs /* Log in any input mbufs */ 6008179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 6009234461Stuexen struct mbuf *mat; 6010234461Stuexen 6011228907Stuexen for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) { 6012170744Srrs if (SCTP_BUF_IS_EXTENDED(mat)) { 6013170744Srrs sctp_log_mb(mat, SCTP_MBUF_INPUT); 6014170744Srrs } 6015163953Srrs } 6016163953Srrs } 6017163953Srrs#endif 6018237540Stuexen#ifdef SCTP_PACKET_LOGGING 6019237569Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { 6020237540Stuexen sctp_packet_log(m); 6021237569Stuexen } 6022170091Srrs#endif 6023238003Stuexen SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 6024254854Stuexen "sctp_input(): Packet of length %d received on %s with csum_flags 0x%b.\n", 6025238003Stuexen m->m_pkthdr.len, 6026238003Stuexen if_name(m->m_pkthdr.rcvif), 6027254854Stuexen (int)m->m_pkthdr.csum_flags, CSUM_BITS); 6028237049Stuexen if (m->m_flags & M_FLOWID) { 6029237049Stuexen mflowid = m->m_pkthdr.flowid; 6030237049Stuexen use_mflowid = 1; 6031237049Stuexen } else { 6032237049Stuexen mflowid = 0; 6033237049Stuexen use_mflowid = 0; 6034237049Stuexen } 6035237569Stuexen SCTP_STAT_INCR(sctps_recvpackets); 6036237569Stuexen SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 6037237569Stuexen /* Get IP, SCTP, and first chunk header together in the first mbuf. */ 6038237569Stuexen offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); 6039165647Srrs if (SCTP_BUF_LEN(m) < offset) { 6040237715Stuexen if ((m = m_pullup(m, offset)) == NULL) { 6041163953Srrs SCTP_STAT_INCR(sctps_hdrops); 6042163953Srrs return; 6043163953Srrs } 6044163953Srrs } 6045237715Stuexen ip = mtod(m, struct ip *); 6046237569Stuexen sh = (struct sctphdr *)((caddr_t)ip + iphlen); 6047237569Stuexen ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 6048237569Stuexen offset -= sizeof(struct sctp_chunkhdr); 6049237715Stuexen memset(&src, 0, sizeof(struct sockaddr_in)); 6050237715Stuexen src.sin_family = AF_INET; 6051237715Stuexen src.sin_len = sizeof(struct sockaddr_in); 6052237715Stuexen src.sin_port = sh->src_port; 6053237715Stuexen src.sin_addr = ip->ip_src; 6054237715Stuexen memset(&dst, 0, sizeof(struct sockaddr_in)); 6055237715Stuexen dst.sin_family = AF_INET; 6056237715Stuexen dst.sin_len = sizeof(struct sockaddr_in); 6057237715Stuexen dst.sin_port = sh->dest_port; 6058237715Stuexen dst.sin_addr = ip->ip_dst; 6059241923Sglebius length = ntohs(ip->ip_len); 6060237569Stuexen /* Validate mbuf chain length with IP payload length. */ 6061238003Stuexen if (SCTP_HEADER_LEN(m) != length) { 6062237569Stuexen SCTPDBG(SCTP_DEBUG_INPUT1, 6063238003Stuexen "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m)); 6064188067Srrs SCTP_STAT_INCR(sctps_hdrops); 6065238003Stuexen goto out; 6066188067Srrs } 6067163953Srrs /* SCTP does not allow broadcasts or multicasts */ 6068237715Stuexen if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { 6069238003Stuexen goto out; 6070163953Srrs } 6071237715Stuexen if (SCTP_IS_IT_BROADCAST(dst.sin_addr, m)) { 6072238003Stuexen goto out; 6073163953Srrs } 6074238003Stuexen ecn_bits = ip->ip_tos; 6075211969Stuexen#if defined(SCTP_WITH_NO_CSUM) 6076211969Stuexen SCTP_STAT_INCR(sctps_recvnocrc); 6077211969Stuexen#else 6078188067Srrs if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { 6079188067Srrs SCTP_STAT_INCR(sctps_recvhwcrc); 6080238003Stuexen compute_crc = 0; 6081238003Stuexen } else { 6082238003Stuexen SCTP_STAT_INCR(sctps_recvswcrc); 6083238003Stuexen compute_crc = 1; 6084188067Srrs } 6085218400Stuexen#endif 6086238003Stuexen sctp_common_input_processing(&m, iphlen, offset, length, 6087237715Stuexen (struct sockaddr *)&src, 6088237715Stuexen (struct sockaddr *)&dst, 6089238003Stuexen sh, ch, 6090238003Stuexen#if !defined(SCTP_WITH_NO_CSUM) 6091238003Stuexen compute_crc, 6092218400Stuexen#endif 6093238003Stuexen ecn_bits, 6094237049Stuexen use_mflowid, mflowid, 6095237049Stuexen vrf_id, port); 6096238003Stuexenout: 6097163953Srrs if (m) { 6098163953Srrs sctp_m_freem(m); 6099163953Srrs } 6100163953Srrs return; 6101163953Srrs} 6102218211Srrs 6103218269Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 6104218269Srrsextern int *sctp_cpuarry; 6105218211Srrs 6106218269Srrs#endif 6107218269Srrs 6108179157Srrsvoid 6109218211Srrssctp_input(struct mbuf *m, int off) 6110179157Srrs{ 6111218211Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 6112218211Srrs struct ip *ip; 6113218211Srrs struct sctphdr *sh; 6114218211Srrs int offset; 6115218211Srrs int cpu_to_use; 6116218371Srrs uint32_t flowid, tag; 6117218211Srrs 6118218269Srrs if (mp_ncpus > 1) { 6119218371Srrs if (m->m_flags & M_FLOWID) { 6120218371Srrs flowid = m->m_pkthdr.flowid; 6121218269Srrs } else { 6122218269Srrs /* 6123218371Srrs * No flow id built by lower layers fix it so we 6124218371Srrs * create one. 6125218269Srrs */ 6126237715Stuexen offset = off + sizeof(struct sctphdr); 6127218371Srrs if (SCTP_BUF_LEN(m) < offset) { 6128237715Stuexen if ((m = m_pullup(m, offset)) == NULL) { 6129218371Srrs SCTP_STAT_INCR(sctps_hdrops); 6130218371Srrs return; 6131218371Srrs } 6132218371Srrs } 6133237715Stuexen ip = mtod(m, struct ip *); 6134218371Srrs sh = (struct sctphdr *)((caddr_t)ip + off); 6135218371Srrs tag = htonl(sh->v_tag); 6136218371Srrs flowid = tag ^ ntohs(sh->dest_port) ^ ntohs(sh->src_port); 6137218371Srrs m->m_pkthdr.flowid = flowid; 6138218371Srrs m->m_flags |= M_FLOWID; 6139218269Srrs } 6140218371Srrs cpu_to_use = sctp_cpuarry[flowid % mp_ncpus]; 6141218211Srrs sctp_queue_to_mcore(m, off, cpu_to_use); 6142218211Srrs return; 6143218211Srrs } 6144218211Srrs#endif 6145218211Srrs sctp_input_with_port(m, off, 0); 6146179157Srrs} 6147221249Stuexen 6148221249Stuexen#endif 6149