sctp_input.c revision 237569
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: head/sys/netinet/sctp_input.c 237569 2012-06-25 19:13: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> 50179157Srrs#include <netinet/udp.h> 51218211Srrs#include <sys/smp.h> 52163953Srrs 53163953Srrs 54163953Srrs 55163953Srrsstatic void 56163953Srrssctp_stop_all_cookie_timers(struct sctp_tcb *stcb) 57163953Srrs{ 58163953Srrs struct sctp_nets *net; 59163953Srrs 60165220Srrs /* 61165220Srrs * This now not only stops all cookie timers it also stops any INIT 62165220Srrs * timers as well. This will make sure that the timers are stopped 63165220Srrs * in all collision cases. 64165220Srrs */ 65163953Srrs SCTP_TCB_LOCK_ASSERT(stcb); 66163953Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 67165220Srrs if (net->rxt_timer.type == SCTP_TIMER_TYPE_COOKIE) { 68163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, 69163953Srrs stcb->sctp_ep, 70163953Srrs stcb, 71165220Srrs net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_1); 72165220Srrs } else if (net->rxt_timer.type == SCTP_TIMER_TYPE_INIT) { 73165220Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, 74165220Srrs stcb->sctp_ep, 75165220Srrs stcb, 76165220Srrs net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_2); 77163953Srrs } 78163953Srrs } 79163953Srrs} 80163953Srrs 81163953Srrs/* INIT handler */ 82163953Srrsstatic void 83163953Srrssctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh, 84237049Stuexen struct sctp_init_chunk *cp, struct sctp_inpcb *inp, 85237049Stuexen struct sctp_tcb *stcb, int *abort_no_unlock, 86237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 87237049Stuexen uint32_t vrf_id, uint16_t port) 88163953Srrs{ 89163953Srrs struct sctp_init *init; 90163953Srrs struct mbuf *op_err; 91163953Srrs 92169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_init: handling INIT tcb:%p\n", 93169420Srrs stcb); 94172396Srrs if (stcb == NULL) { 95172396Srrs SCTP_INP_RLOCK(inp); 96172396Srrs } 97229774Stuexen /* validate length */ 98163953Srrs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) { 99163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 100169352Srrs sctp_abort_association(inp, stcb, m, iphlen, sh, op_err, 101237049Stuexen use_mflowid, mflowid, 102179157Srrs vrf_id, port); 103168299Srrs if (stcb) 104168299Srrs *abort_no_unlock = 1; 105172396Srrs goto outnow; 106163953Srrs } 107163953Srrs /* validate parameters */ 108229774Stuexen init = &cp->init; 109163953Srrs if (init->initiate_tag == 0) { 110163953Srrs /* protocol error... send abort */ 111163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 112169352Srrs sctp_abort_association(inp, stcb, m, iphlen, sh, op_err, 113237049Stuexen use_mflowid, mflowid, 114179157Srrs vrf_id, port); 115168299Srrs if (stcb) 116168299Srrs *abort_no_unlock = 1; 117172396Srrs goto outnow; 118163953Srrs } 119163953Srrs if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) { 120163953Srrs /* invalid parameter... send abort */ 121163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 122169352Srrs sctp_abort_association(inp, stcb, m, iphlen, sh, op_err, 123237049Stuexen use_mflowid, mflowid, 124179157Srrs vrf_id, port); 125171440Srrs if (stcb) 126171440Srrs *abort_no_unlock = 1; 127172396Srrs goto outnow; 128163953Srrs } 129163953Srrs if (init->num_inbound_streams == 0) { 130163953Srrs /* protocol error... send abort */ 131163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 132169352Srrs sctp_abort_association(inp, stcb, m, iphlen, sh, op_err, 133237049Stuexen use_mflowid, mflowid, 134179157Srrs vrf_id, port); 135168299Srrs if (stcb) 136168299Srrs *abort_no_unlock = 1; 137172396Srrs goto outnow; 138163953Srrs } 139163953Srrs if (init->num_outbound_streams == 0) { 140163953Srrs /* protocol error... send abort */ 141163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 142169352Srrs sctp_abort_association(inp, stcb, m, iphlen, sh, op_err, 143237049Stuexen use_mflowid, mflowid, 144179157Srrs vrf_id, port); 145168299Srrs if (stcb) 146168299Srrs *abort_no_unlock = 1; 147172396Srrs goto outnow; 148163953Srrs } 149163953Srrs if (sctp_validate_init_auth_params(m, offset + sizeof(*cp), 150229774Stuexen offset + ntohs(cp->ch.chunk_length))) { 151163953Srrs /* auth parameter(s) error... send abort */ 152237049Stuexen sctp_abort_association(inp, stcb, m, iphlen, sh, NULL, 153237049Stuexen use_mflowid, mflowid, 154237049Stuexen vrf_id, port); 155168299Srrs if (stcb) 156168299Srrs *abort_no_unlock = 1; 157172396Srrs goto outnow; 158163953Srrs } 159229774Stuexen /* 160229774Stuexen * We are only accepting if we have a socket with positive 161229774Stuexen * so_qlimit. 162229774Stuexen */ 163229774Stuexen if ((stcb == NULL) && 164229774Stuexen ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 165229774Stuexen (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 166229774Stuexen (inp->sctp_socket == NULL) || 167229774Stuexen (inp->sctp_socket->so_qlimit == 0))) { 168229774Stuexen /* 169229774Stuexen * FIX ME ?? What about TCP model and we have a 170229774Stuexen * match/restart case? Actually no fix is needed. the lookup 171229774Stuexen * will always find the existing assoc so stcb would not be 172229774Stuexen * NULL. It may be questionable to do this since we COULD 173229774Stuexen * just send back the INIT-ACK and hope that the app did 174229774Stuexen * accept()'s by the time the COOKIE was sent. But there is 175229774Stuexen * a price to pay for COOKIE generation and I don't want to 176229774Stuexen * pay it on the chance that the app will actually do some 177229774Stuexen * accepts(). The App just looses and should NOT be in this 178229774Stuexen * state :-) 179229774Stuexen */ 180229805Stuexen if (SCTP_BASE_SYSCTL(sctp_blackhole) == 0) { 181237049Stuexen sctp_send_abort(m, iphlen, sh, 0, NULL, 182237049Stuexen use_mflowid, mflowid, 183237049Stuexen vrf_id, port); 184229805Stuexen } 185229774Stuexen goto outnow; 186229774Stuexen } 187229774Stuexen if ((stcb != NULL) && 188229774Stuexen (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT)) { 189229774Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending SHUTDOWN-ACK\n"); 190229774Stuexen sctp_send_shutdown_ack(stcb, NULL); 191229774Stuexen sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 192229774Stuexen } else { 193229774Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n"); 194237049Stuexen sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, sh, cp, 195237049Stuexen use_mflowid, mflowid, 196237049Stuexen vrf_id, port, 197229774Stuexen ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED)); 198229774Stuexen } 199172396Srrsoutnow: 200172396Srrs if (stcb == NULL) { 201172396Srrs SCTP_INP_RUNLOCK(inp); 202172396Srrs } 203163953Srrs} 204163953Srrs 205163953Srrs/* 206163953Srrs * process peer "INIT/INIT-ACK" chunk returns value < 0 on error 207163953Srrs */ 208171158Srrs 209171158Srrsint 210221627Stuexensctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked 211221627Stuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 212221627Stuexen SCTP_UNUSED 213221627Stuexen#endif 214221627Stuexen) 215171158Srrs{ 216171158Srrs int unsent_data = 0; 217217760Stuexen unsigned int i; 218217760Stuexen struct sctp_stream_queue_pending *sp; 219171158Srrs struct sctp_association *asoc; 220171158Srrs 221171158Srrs /* 222171158Srrs * This function returns the number of streams that have true unsent 223171158Srrs * data on them. Note that as it looks through it will clean up any 224171158Srrs * places that have old data that has been sent but left at top of 225171158Srrs * stream queue. 226171158Srrs */ 227171158Srrs asoc = &stcb->asoc; 228171158Srrs SCTP_TCB_SEND_LOCK(stcb); 229217760Stuexen if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 230217760Stuexen /* Check to see if some data queued */ 231217760Stuexen for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 232217760Stuexen /* sa_ignore FREED_MEMORY */ 233217760Stuexen sp = TAILQ_FIRST(&stcb->asoc.strmout[i].outqueue); 234217760Stuexen if (sp == NULL) { 235217760Stuexen continue; 236217760Stuexen } 237171158Srrs if ((sp->msg_is_complete) && 238171158Srrs (sp->length == 0) && 239171158Srrs (sp->sender_all_done)) { 240171158Srrs /* 241171158Srrs * We are doing differed cleanup. Last time 242171158Srrs * through when we took all the data the 243171158Srrs * sender_all_done was not set. 244171158Srrs */ 245171158Srrs if (sp->put_last_out == 0) { 246171158Srrs SCTP_PRINTF("Gak, put out entire msg with NO end!-1\n"); 247171158Srrs SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d\n", 248171158Srrs sp->sender_all_done, 249171158Srrs sp->length, 250171158Srrs sp->msg_is_complete, 251171158Srrs sp->put_last_out); 252171158Srrs } 253217760Stuexen atomic_subtract_int(&stcb->asoc.stream_queue_cnt, 1); 254217760Stuexen TAILQ_REMOVE(&stcb->asoc.strmout[i].outqueue, sp, next); 255212712Stuexen if (sp->net) { 256212712Stuexen sctp_free_remote_addr(sp->net); 257212712Stuexen sp->net = NULL; 258212712Stuexen } 259171158Srrs if (sp->data) { 260171158Srrs sctp_m_freem(sp->data); 261171158Srrs sp->data = NULL; 262171158Srrs } 263221627Stuexen sctp_free_a_strmoq(stcb, sp, so_locked); 264171158Srrs } else { 265171158Srrs unsent_data++; 266216822Stuexen break; 267171158Srrs } 268171158Srrs } 269171158Srrs } 270171158Srrs SCTP_TCB_SEND_UNLOCK(stcb); 271171158Srrs return (unsent_data); 272171158Srrs} 273171158Srrs 274163953Srrsstatic int 275228653Stuexensctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) 276163953Srrs{ 277163953Srrs struct sctp_init *init; 278163953Srrs struct sctp_association *asoc; 279163953Srrs struct sctp_nets *lnet; 280163953Srrs unsigned int i; 281163953Srrs 282163953Srrs init = &cp->init; 283163953Srrs asoc = &stcb->asoc; 284163953Srrs /* save off parameters */ 285163953Srrs asoc->peer_vtag = ntohl(init->initiate_tag); 286163953Srrs asoc->peers_rwnd = ntohl(init->a_rwnd); 287218129Srrs /* init tsn's */ 288218129Srrs asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1; 289218129Srrs 290212712Stuexen if (!TAILQ_EMPTY(&asoc->nets)) { 291163953Srrs /* update any ssthresh's that may have a default */ 292163953Srrs TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) { 293163953Srrs lnet->ssthresh = asoc->peers_rwnd; 294179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) { 295170744Srrs sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_INITIALIZATION); 296170744Srrs } 297163953Srrs } 298163953Srrs } 299164181Srrs SCTP_TCB_SEND_LOCK(stcb); 300163953Srrs if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) { 301163953Srrs unsigned int newcnt; 302163953Srrs struct sctp_stream_out *outs; 303216822Stuexen struct sctp_stream_queue_pending *sp, *nsp; 304216822Stuexen struct sctp_tmit_chunk *chk, *nchk; 305163953Srrs 306196260Stuexen /* abandon the upper streams */ 307163953Srrs newcnt = ntohs(init->num_inbound_streams); 308216822Stuexen TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { 309216822Stuexen if (chk->rec.data.stream_number >= newcnt) { 310216822Stuexen TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); 311216822Stuexen asoc->send_queue_cnt--; 312216822Stuexen if (chk->data != NULL) { 313216822Stuexen sctp_free_bufspace(stcb, asoc, chk, 1); 314235416Stuexen sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 315235416Stuexen 0, chk, SCTP_SO_NOT_LOCKED); 316216822Stuexen if (chk->data) { 317216822Stuexen sctp_m_freem(chk->data); 318216822Stuexen chk->data = NULL; 319196260Stuexen } 320196260Stuexen } 321221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 322216822Stuexen /* sa_ignore FREED_MEMORY */ 323196260Stuexen } 324196260Stuexen } 325163953Srrs if (asoc->strmout) { 326163953Srrs for (i = newcnt; i < asoc->pre_open_streams; i++) { 327163953Srrs outs = &asoc->strmout[i]; 328216822Stuexen TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { 329196260Stuexen TAILQ_REMOVE(&outs->outqueue, sp, next); 330163953Srrs asoc->stream_queue_cnt--; 331163953Srrs sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, 332235416Stuexen stcb, 0, sp, SCTP_SO_NOT_LOCKED); 333163953Srrs if (sp->data) { 334163953Srrs sctp_m_freem(sp->data); 335163953Srrs sp->data = NULL; 336163953Srrs } 337212712Stuexen if (sp->net) { 338212712Stuexen sctp_free_remote_addr(sp->net); 339212712Stuexen sp->net = NULL; 340212712Stuexen } 341163953Srrs /* Free the chunk */ 342221627Stuexen sctp_free_a_strmoq(stcb, sp, SCTP_SO_NOT_LOCKED); 343169655Srrs /* sa_ignore FREED_MEMORY */ 344163953Srrs } 345163953Srrs } 346163953Srrs } 347196260Stuexen /* cut back the count */ 348163953Srrs asoc->pre_open_streams = newcnt; 349163953Srrs } 350164181Srrs SCTP_TCB_SEND_UNLOCK(stcb); 351188854Srrs asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams; 352218129Srrs 353185694Srrs /* EY - nr_sack: initialize highest tsn in nr_mapping_array */ 354185694Srrs asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 355179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 356170744Srrs sctp_log_map(0, 5, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 357170744Srrs } 358163953Srrs /* This is the next one we expect */ 359163953Srrs asoc->str_reset_seq_in = asoc->asconf_seq_in + 1; 360163953Srrs 361163953Srrs asoc->mapping_array_base_tsn = ntohl(init->initial_tsn); 362180955Srrs asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->asconf_seq_in; 363218129Srrs 364163953Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 365163953Srrs /* open the requested streams */ 366170091Srrs 367163953Srrs if (asoc->strmin != NULL) { 368163953Srrs /* Free the old ones */ 369216822Stuexen struct sctp_queued_to_read *ctl, *nctl; 370164181Srrs 371164181Srrs for (i = 0; i < asoc->streamincnt; i++) { 372216822Stuexen TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) { 373164181Srrs TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next); 374164181Srrs sctp_free_remote_addr(ctl->whoFrom); 375171158Srrs ctl->whoFrom = NULL; 376164181Srrs sctp_m_freem(ctl->data); 377164181Srrs ctl->data = NULL; 378164181Srrs sctp_free_a_readq(stcb, ctl); 379164181Srrs } 380164181Srrs } 381170091Srrs SCTP_FREE(asoc->strmin, SCTP_M_STRMI); 382163953Srrs } 383164181Srrs asoc->streamincnt = ntohs(init->num_outbound_streams); 384164181Srrs if (asoc->streamincnt > MAX_SCTP_STREAMS) { 385164181Srrs asoc->streamincnt = MAX_SCTP_STREAMS; 386164181Srrs } 387163953Srrs SCTP_MALLOC(asoc->strmin, struct sctp_stream_in *, asoc->streamincnt * 388170091Srrs sizeof(struct sctp_stream_in), SCTP_M_STRMI); 389163953Srrs if (asoc->strmin == NULL) { 390163953Srrs /* we didn't get memory for the streams! */ 391169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "process_init: couldn't get memory for the streams!\n"); 392163953Srrs return (-1); 393163953Srrs } 394163953Srrs for (i = 0; i < asoc->streamincnt; i++) { 395163953Srrs asoc->strmin[i].stream_no = i; 396163953Srrs asoc->strmin[i].last_sequence_delivered = 0xffff; 397163953Srrs /* 398163953Srrs * U-stream ranges will be set when the cookie is unpacked. 399163953Srrs * Or for the INIT sender they are un set (if pr-sctp not 400163953Srrs * supported) when the INIT-ACK arrives. 401163953Srrs */ 402163953Srrs TAILQ_INIT(&asoc->strmin[i].inqueue); 403168943Srrs asoc->strmin[i].delivery_started = 0; 404163953Srrs } 405163953Srrs /* 406163953Srrs * load_address_from_init will put the addresses into the 407163953Srrs * association when the COOKIE is processed or the INIT-ACK is 408163953Srrs * processed. Both types of COOKIE's existing and new call this 409163953Srrs * routine. It will remove addresses that are no longer in the 410163953Srrs * association (for the restarting case where addresses are 411163953Srrs * removed). Up front when the INIT arrives we will discard it if it 412163953Srrs * is a restart and new addresses have been added. 413163953Srrs */ 414169655Srrs /* sa_ignore MEMLEAK */ 415163953Srrs return (0); 416163953Srrs} 417163953Srrs 418163953Srrs/* 419163953Srrs * INIT-ACK message processing/consumption returns value < 0 on error 420163953Srrs */ 421163953Srrsstatic int 422237049Stuexensctp_process_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh, 423237049Stuexen struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 424237049Stuexen struct sctp_nets *net, int *abort_no_unlock, 425237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 426237049Stuexen uint32_t vrf_id) 427163953Srrs{ 428163953Srrs struct sctp_association *asoc; 429163953Srrs struct mbuf *op_err; 430163953Srrs int retval, abort_flag; 431163953Srrs uint32_t initack_limit; 432185694Srrs int nat_friendly = 0; 433163953Srrs 434163953Srrs /* First verify that we have no illegal param's */ 435163953Srrs abort_flag = 0; 436163953Srrs op_err = NULL; 437163953Srrs 438163953Srrs op_err = sctp_arethere_unrecognized_parameters(m, 439163953Srrs (offset + sizeof(struct sctp_init_chunk)), 440185694Srrs &abort_flag, (struct sctp_chunkhdr *)cp, &nat_friendly); 441163953Srrs if (abort_flag) { 442163953Srrs /* Send an abort and notify peer */ 443235360Stuexen sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 444170056Srrs *abort_no_unlock = 1; 445163953Srrs return (-1); 446163953Srrs } 447163953Srrs asoc = &stcb->asoc; 448185694Srrs asoc->peer_supports_nat = (uint8_t) nat_friendly; 449163953Srrs /* process the peer's parameters in the INIT-ACK */ 450228653Stuexen retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb); 451163953Srrs if (retval < 0) { 452163953Srrs return (retval); 453163953Srrs } 454163953Srrs initack_limit = offset + ntohs(cp->ch.chunk_length); 455163953Srrs /* load all addresses */ 456228653Stuexen if ((retval = sctp_load_addresses_from_init(stcb, m, 457163953Srrs (offset + sizeof(struct sctp_init_chunk)), initack_limit, sh, 458163953Srrs NULL))) { 459163953Srrs /* Huh, we should abort */ 460169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 461169420Srrs "Load addresses from INIT causes an abort %d\n", 462169420Srrs retval); 463237049Stuexen sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh, NULL, 464237049Stuexen use_mflowid, mflowid, 465237049Stuexen vrf_id, net->port); 466168299Srrs *abort_no_unlock = 1; 467163953Srrs return (-1); 468163953Srrs } 469171477Srrs /* if the peer doesn't support asconf, flush the asconf queue */ 470171477Srrs if (asoc->peer_supports_asconf == 0) { 471216822Stuexen struct sctp_asconf_addr *param, *nparam; 472171477Srrs 473216822Stuexen TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) { 474216822Stuexen TAILQ_REMOVE(&asoc->asconf_queue, param, next); 475216822Stuexen SCTP_FREE(param, SCTP_M_ASC_ADDR); 476171477Srrs } 477171477Srrs } 478163953Srrs stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs, 479163953Srrs stcb->asoc.local_hmacs); 480163953Srrs if (op_err) { 481163953Srrs sctp_queue_op_err(stcb, op_err); 482163953Srrs /* queuing will steal away the mbuf chain to the out queue */ 483163953Srrs op_err = NULL; 484163953Srrs } 485163953Srrs /* extract the cookie and queue it to "echo" it back... */ 486179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 487171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 488171943Srrs stcb->asoc.overall_error_count, 489171943Srrs 0, 490171943Srrs SCTP_FROM_SCTP_INPUT, 491171943Srrs __LINE__); 492171943Srrs } 493163953Srrs stcb->asoc.overall_error_count = 0; 494163953Srrs net->error_count = 0; 495163953Srrs 496163953Srrs /* 497163953Srrs * Cancel the INIT timer, We do this first before queueing the 498163953Srrs * cookie. We always cancel at the primary to assue that we are 499163953Srrs * canceling the timer started by the INIT which always goes to the 500163953Srrs * primary. 501163953Srrs */ 502163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb, 503165220Srrs asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4); 504163953Srrs 505165220Srrs /* calculate the RTO */ 506218186Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy, 507219397Srrs SCTP_RTT_FROM_NON_DATA); 508165220Srrs 509163953Srrs retval = sctp_send_cookie_echo(m, offset, stcb, net); 510163953Srrs if (retval < 0) { 511163953Srrs /* 512163953Srrs * No cookie, we probably should send a op error. But in any 513163953Srrs * case if there is no cookie in the INIT-ACK, we can 514163953Srrs * abandon the peer, its broke. 515163953Srrs */ 516163953Srrs if (retval == -3) { 517163953Srrs /* We abort with an error of missing mandatory param */ 518163953Srrs op_err = 519163953Srrs sctp_generate_invmanparam(SCTP_CAUSE_MISSING_PARAM); 520163953Srrs if (op_err) { 521163953Srrs /* 522163953Srrs * Expand beyond to include the mandatory 523163953Srrs * param cookie 524163953Srrs */ 525163953Srrs struct sctp_inv_mandatory_param *mp; 526163953Srrs 527165647Srrs SCTP_BUF_LEN(op_err) = 528163953Srrs sizeof(struct sctp_inv_mandatory_param); 529163953Srrs mp = mtod(op_err, 530163953Srrs struct sctp_inv_mandatory_param *); 531163953Srrs /* Subtract the reserved param */ 532163953Srrs mp->length = 533163953Srrs htons(sizeof(struct sctp_inv_mandatory_param) - 2); 534163953Srrs mp->num_param = htonl(1); 535163953Srrs mp->param = htons(SCTP_STATE_COOKIE); 536163953Srrs mp->resv = 0; 537163953Srrs } 538163953Srrs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 539237049Stuexen sh, op_err, 540237049Stuexen use_mflowid, mflowid, 541237049Stuexen vrf_id, net->port); 542168299Srrs *abort_no_unlock = 1; 543163953Srrs } 544163953Srrs return (retval); 545163953Srrs } 546163953Srrs return (0); 547163953Srrs} 548163953Srrs 549163953Srrsstatic void 550163953Srrssctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, 551163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 552163953Srrs{ 553163953Srrs struct sockaddr_storage store; 554212225Srrs struct sctp_nets *r_net, *f_net; 555163953Srrs struct timeval tv; 556172396Srrs int req_prim = 0; 557224641Stuexen uint16_t old_error_counter; 558163953Srrs 559221249Stuexen#ifdef INET 560221249Stuexen struct sockaddr_in *sin; 561221249Stuexen 562221249Stuexen#endif 563221249Stuexen#ifdef INET6 564221249Stuexen struct sockaddr_in6 *sin6; 565221249Stuexen 566221249Stuexen#endif 567221249Stuexen 568163953Srrs if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) { 569163953Srrs /* Invalid length */ 570163953Srrs return; 571163953Srrs } 572163953Srrs memset(&store, 0, sizeof(store)); 573221249Stuexen switch (cp->heartbeat.hb_info.addr_family) { 574221249Stuexen#ifdef INET 575221249Stuexen case AF_INET: 576221249Stuexen if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) { 577221249Stuexen sin = (struct sockaddr_in *)&store; 578221249Stuexen sin->sin_family = cp->heartbeat.hb_info.addr_family; 579221249Stuexen sin->sin_len = cp->heartbeat.hb_info.addr_len; 580221249Stuexen sin->sin_port = stcb->rport; 581221249Stuexen memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address, 582221249Stuexen sizeof(sin->sin_addr)); 583221249Stuexen } else { 584221249Stuexen return; 585221249Stuexen } 586221249Stuexen break; 587221249Stuexen#endif 588221249Stuexen#ifdef INET6 589221249Stuexen case AF_INET6: 590221249Stuexen if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) { 591221249Stuexen sin6 = (struct sockaddr_in6 *)&store; 592221249Stuexen sin6->sin6_family = cp->heartbeat.hb_info.addr_family; 593221249Stuexen sin6->sin6_len = cp->heartbeat.hb_info.addr_len; 594221249Stuexen sin6->sin6_port = stcb->rport; 595221249Stuexen memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address, 596221249Stuexen sizeof(sin6->sin6_addr)); 597221249Stuexen } else { 598221249Stuexen return; 599221249Stuexen } 600221249Stuexen break; 601221249Stuexen#endif 602221249Stuexen default: 603163953Srrs return; 604163953Srrs } 605221249Stuexen r_net = sctp_findnet(stcb, (struct sockaddr *)&store); 606163953Srrs if (r_net == NULL) { 607169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n"); 608163953Srrs return; 609163953Srrs } 610163953Srrs if ((r_net && (r_net->dest_state & SCTP_ADDR_UNCONFIRMED)) && 611163953Srrs (r_net->heartbeat_random1 == cp->heartbeat.hb_info.random_value1) && 612163953Srrs (r_net->heartbeat_random2 == cp->heartbeat.hb_info.random_value2)) { 613163953Srrs /* 614163953Srrs * If the its a HB and it's random value is correct when can 615163953Srrs * confirm the destination. 616163953Srrs */ 617163953Srrs r_net->dest_state &= ~SCTP_ADDR_UNCONFIRMED; 618167598Srrs if (r_net->dest_state & SCTP_ADDR_REQ_PRIMARY) { 619167598Srrs stcb->asoc.primary_destination = r_net; 620167598Srrs r_net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY; 621212225Srrs f_net = TAILQ_FIRST(&stcb->asoc.nets); 622212225Srrs if (f_net != r_net) { 623167598Srrs /* 624167598Srrs * first one on the list is NOT the primary 625167598Srrs * sctp_cmpaddr() is much more efficent if 626167598Srrs * the primary is the first on the list, 627167598Srrs * make it so. 628167598Srrs */ 629212225Srrs TAILQ_REMOVE(&stcb->asoc.nets, r_net, sctp_next); 630212225Srrs TAILQ_INSERT_HEAD(&stcb->asoc.nets, r_net, sctp_next); 631167598Srrs } 632172396Srrs req_prim = 1; 633167598Srrs } 634163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 635172090Srrs stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED); 636224641Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 637224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 638163953Srrs } 639224641Stuexen old_error_counter = r_net->error_count; 640163953Srrs r_net->error_count = 0; 641163953Srrs r_net->hb_responded = 1; 642163953Srrs tv.tv_sec = cp->heartbeat.hb_info.time_value_1; 643163953Srrs tv.tv_usec = cp->heartbeat.hb_info.time_value_2; 644224641Stuexen /* Now lets do a RTO with this */ 645224641Stuexen r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy, 646224641Stuexen SCTP_RTT_FROM_NON_DATA); 647224641Stuexen if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) { 648163953Srrs r_net->dest_state |= SCTP_ADDR_REACHABLE; 649163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 650235414Stuexen 0, (void *)r_net, SCTP_SO_NOT_LOCKED); 651163953Srrs } 652224641Stuexen if (r_net->dest_state & SCTP_ADDR_PF) { 653224641Stuexen r_net->dest_state &= ~SCTP_ADDR_PF; 654224641Stuexen stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net); 655224641Stuexen } 656224641Stuexen if (old_error_counter > 0) { 657224641Stuexen sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 658224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 659224641Stuexen } 660224641Stuexen if (r_net == stcb->asoc.primary_destination) { 661224641Stuexen if (stcb->asoc.alternate) { 662224641Stuexen /* release the alternate, primary is good */ 663224641Stuexen sctp_free_remote_addr(stcb->asoc.alternate); 664224641Stuexen stcb->asoc.alternate = NULL; 665171440Srrs } 666171440Srrs } 667172396Srrs /* Mobility adaptation */ 668172396Srrs if (req_prim) { 669172396Srrs if ((sctp_is_mobility_feature_on(stcb->sctp_ep, 670172396Srrs SCTP_MOBILITY_BASE) || 671172396Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 672172396Srrs SCTP_MOBILITY_FASTHANDOFF)) && 673172396Srrs sctp_is_mobility_feature_on(stcb->sctp_ep, 674172396Srrs SCTP_MOBILITY_PRIM_DELETED)) { 675172396Srrs 676172396Srrs sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7); 677172396Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 678172396Srrs SCTP_MOBILITY_FASTHANDOFF)) { 679172396Srrs sctp_assoc_immediate_retrans(stcb, 680172396Srrs stcb->asoc.primary_destination); 681172396Srrs } 682172396Srrs if (sctp_is_mobility_feature_on(stcb->sctp_ep, 683172396Srrs SCTP_MOBILITY_BASE)) { 684212712Stuexen sctp_move_chunks_from_net(stcb, 685212712Stuexen stcb->asoc.deleted_primary); 686172396Srrs } 687172396Srrs sctp_delete_prim_timer(stcb->sctp_ep, stcb, 688172396Srrs stcb->asoc.deleted_primary); 689172396Srrs } 690172396Srrs } 691163953Srrs} 692163953Srrs 693185694Srrsstatic int 694185694Srrssctp_handle_nat_colliding_state(struct sctp_tcb *stcb) 695185694Srrs{ 696185694Srrs /* 697185694Srrs * return 0 means we want you to proceed with the abort non-zero 698185694Srrs * means no abort processing 699185694Srrs */ 700185694Srrs struct sctpasochead *head; 701185694Srrs 702185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) { 703185694Srrs /* generate a new vtag and send init */ 704185694Srrs LIST_REMOVE(stcb, sctp_asocs); 705185694Srrs stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 706185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 707185694Srrs /* 708185694Srrs * put it in the bucket in the vtag hash of assoc's for the 709185694Srrs * system 710185694Srrs */ 711185694Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 712185694Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 713185694Srrs return (1); 714185694Srrs } 715185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 716185694Srrs /* 717185694Srrs * treat like a case where the cookie expired i.e.: - dump 718185694Srrs * current cookie. - generate a new vtag. - resend init. 719185694Srrs */ 720185694Srrs /* generate a new vtag and send init */ 721185694Srrs LIST_REMOVE(stcb, sctp_asocs); 722185694Srrs stcb->asoc.state &= ~SCTP_STATE_COOKIE_ECHOED; 723185694Srrs stcb->asoc.state |= SCTP_STATE_COOKIE_WAIT; 724185694Srrs sctp_stop_all_cookie_timers(stcb); 725185694Srrs sctp_toss_old_cookies(stcb, &stcb->asoc); 726185694Srrs stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 727185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 728185694Srrs /* 729185694Srrs * put it in the bucket in the vtag hash of assoc's for the 730185694Srrs * system 731185694Srrs */ 732185694Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 733185694Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 734185694Srrs return (1); 735185694Srrs } 736185694Srrs return (0); 737185694Srrs} 738185694Srrs 739185694Srrsstatic int 740185694Srrssctp_handle_nat_missing_state(struct sctp_tcb *stcb, 741185694Srrs struct sctp_nets *net) 742185694Srrs{ 743185694Srrs /* 744185694Srrs * return 0 means we want you to proceed with the abort non-zero 745185694Srrs * means no abort processing 746185694Srrs */ 747185694Srrs if (stcb->asoc.peer_supports_auth == 0) { 748185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n"); 749185694Srrs return (0); 750185694Srrs } 751185694Srrs sctp_asconf_send_nat_state_update(stcb, net); 752185694Srrs return (1); 753185694Srrs} 754185694Srrs 755185694Srrs 756163953Srrsstatic void 757235360Stuexensctp_handle_abort(struct sctp_abort_chunk *abort, 758163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 759163953Srrs{ 760237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 761172090Srrs struct socket *so; 762172090Srrs 763172090Srrs#endif 764185694Srrs uint16_t len; 765235360Stuexen uint16_t error; 766172090Srrs 767169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n"); 768163953Srrs if (stcb == NULL) 769163953Srrs return; 770163953Srrs 771235360Stuexen len = ntohs(abort->ch.chunk_length); 772185694Srrs if (len > sizeof(struct sctp_chunkhdr)) { 773185694Srrs /* 774185694Srrs * Need to check the cause codes for our two magic nat 775185694Srrs * aborts which don't kill the assoc necessarily. 776185694Srrs */ 777185694Srrs struct sctp_missing_nat_state *natc; 778185694Srrs 779235360Stuexen natc = (struct sctp_missing_nat_state *)(abort + 1); 780235360Stuexen error = ntohs(natc->cause); 781235360Stuexen if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) { 782185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 783235360Stuexen abort->ch.chunk_flags); 784185694Srrs if (sctp_handle_nat_colliding_state(stcb)) { 785185694Srrs return; 786185694Srrs } 787235360Stuexen } else if (error == SCTP_CAUSE_NAT_MISSING_STATE) { 788185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 789235360Stuexen abort->ch.chunk_flags); 790185694Srrs if (sctp_handle_nat_missing_state(stcb, net)) { 791185694Srrs return; 792185694Srrs } 793185694Srrs } 794235360Stuexen } else { 795235360Stuexen error = 0; 796185694Srrs } 797163953Srrs /* stop any receive timers */ 798171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_6); 799163953Srrs /* notify user of the abort and clean up... */ 800235403Stuexen sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED); 801163953Srrs /* free the tcb */ 802163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_aborted); 803163953Srrs if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 804163953Srrs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 805163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 806163953Srrs } 807168859Srrs#ifdef SCTP_ASOCLOG_OF_TSNS 808168859Srrs sctp_print_out_track_log(stcb); 809168859Srrs#endif 810237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 811172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 812172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 813172090Srrs SCTP_TCB_UNLOCK(stcb); 814172090Srrs SCTP_SOCKET_LOCK(so, 1); 815172090Srrs SCTP_TCB_LOCK(stcb); 816172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 817172090Srrs#endif 818171990Srrs stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 819171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 820171943Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_6); 821237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 822172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 823172090Srrs#endif 824169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n"); 825163953Srrs} 826163953Srrs 827163953Srrsstatic void 828224641Stuexensctp_start_net_timers(struct sctp_tcb *stcb) 829224641Stuexen{ 830224641Stuexen uint32_t cnt_hb_sent; 831224641Stuexen struct sctp_nets *net; 832224641Stuexen 833224641Stuexen cnt_hb_sent = 0; 834224641Stuexen TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 835224641Stuexen /* 836224641Stuexen * For each network start: 1) A pmtu timer. 2) A HB timer 3) 837224641Stuexen * If the dest in unconfirmed send a hb as well if under 838224641Stuexen * max_hb_burst have been sent. 839224641Stuexen */ 840224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net); 841224641Stuexen sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 842224641Stuexen if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) && 843224641Stuexen (cnt_hb_sent < SCTP_BASE_SYSCTL(sctp_hb_maxburst))) { 844224641Stuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 845224641Stuexen cnt_hb_sent++; 846224641Stuexen } 847224641Stuexen } 848224641Stuexen if (cnt_hb_sent) { 849224641Stuexen sctp_chunk_output(stcb->sctp_ep, stcb, 850224641Stuexen SCTP_OUTPUT_FROM_COOKIE_ACK, 851224641Stuexen SCTP_SO_NOT_LOCKED); 852224641Stuexen } 853224641Stuexen} 854224641Stuexen 855224641Stuexen 856224641Stuexenstatic void 857163953Srrssctp_handle_shutdown(struct sctp_shutdown_chunk *cp, 858163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag) 859163953Srrs{ 860163953Srrs struct sctp_association *asoc; 861163953Srrs int some_on_streamwheel; 862163953Srrs 863237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 864172090Srrs struct socket *so; 865172090Srrs 866172090Srrs#endif 867172090Srrs 868169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 869169420Srrs "sctp_handle_shutdown: handling SHUTDOWN\n"); 870163953Srrs if (stcb == NULL) 871163953Srrs return; 872165220Srrs asoc = &stcb->asoc; 873165220Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 874165220Srrs (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 875163953Srrs return; 876163953Srrs } 877163953Srrs if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) { 878163953Srrs /* Shutdown NOT the expected size */ 879163953Srrs return; 880163953Srrs } else { 881228653Stuexen sctp_update_acked(stcb, cp, abort_flag); 882199477Stuexen if (*abort_flag) { 883199477Stuexen return; 884199477Stuexen } 885163953Srrs } 886165220Srrs if (asoc->control_pdapi) { 887163953Srrs /* 888163953Srrs * With a normal shutdown we assume the end of last record. 889163953Srrs */ 890163953Srrs SCTP_INP_READ_LOCK(stcb->sctp_ep); 891165220Srrs asoc->control_pdapi->end_added = 1; 892165220Srrs asoc->control_pdapi->pdapi_aborted = 1; 893165220Srrs asoc->control_pdapi = NULL; 894163953Srrs SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 895237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 896172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 897172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 898172090Srrs SCTP_TCB_UNLOCK(stcb); 899172090Srrs SCTP_SOCKET_LOCK(so, 1); 900172090Srrs SCTP_TCB_LOCK(stcb); 901172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 902172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 903172090Srrs /* assoc was freed while we were unlocked */ 904172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 905172090Srrs return; 906172090Srrs } 907172090Srrs#endif 908163996Srrs sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 909237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 910172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 911172090Srrs#endif 912163953Srrs } 913163953Srrs /* goto SHUTDOWN_RECEIVED state to block new requests */ 914163953Srrs if (stcb->sctp_socket) { 915163953Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 916170056Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) && 917163953Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 918171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_RECEIVED); 919172703Srrs SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 920163953Srrs /* 921163953Srrs * notify upper layer that peer has initiated a 922163953Srrs * shutdown 923163953Srrs */ 924172090Srrs sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 925163953Srrs 926163953Srrs /* reset time */ 927169378Srrs (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 928163953Srrs } 929163953Srrs } 930163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) { 931163953Srrs /* 932163953Srrs * stop the shutdown timer, since we WILL move to 933163953Srrs * SHUTDOWN-ACK-SENT. 934163953Srrs */ 935171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_8); 936163953Srrs } 937171158Srrs /* Now is there unsent data on a stream somewhere? */ 938221627Stuexen some_on_streamwheel = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED); 939163953Srrs 940163953Srrs if (!TAILQ_EMPTY(&asoc->send_queue) || 941163953Srrs !TAILQ_EMPTY(&asoc->sent_queue) || 942163953Srrs some_on_streamwheel) { 943163953Srrs /* By returning we will push more data out */ 944163953Srrs return; 945163953Srrs } else { 946163953Srrs /* no outstanding data to send, so move on... */ 947163953Srrs /* send SHUTDOWN-ACK */ 948224641Stuexen sctp_send_shutdown_ack(stcb, net); 949163953Srrs /* move to SHUTDOWN-ACK-SENT state */ 950166675Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 951166675Srrs (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 952163953Srrs SCTP_STAT_DECR_GAUGE32(sctps_currestab); 953163953Srrs } 954171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); 955172703Srrs SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 956214918Stuexen sctp_stop_timers_for_shutdown(stcb); 957163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, 958163953Srrs stcb, net); 959163953Srrs } 960163953Srrs} 961163953Srrs 962163953Srrsstatic void 963228653Stuexensctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, 964204141Stuexen struct sctp_tcb *stcb, 965204141Stuexen struct sctp_nets *net) 966163953Srrs{ 967163953Srrs struct sctp_association *asoc; 968163953Srrs 969237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 970172090Srrs struct socket *so; 971172090Srrs 972172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 973172090Srrs#endif 974169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 975169420Srrs "sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n"); 976163953Srrs if (stcb == NULL) 977163953Srrs return; 978163953Srrs 979163953Srrs asoc = &stcb->asoc; 980163953Srrs /* process according to association state */ 981204141Stuexen if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 982204141Stuexen (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 983204141Stuexen /* unexpected SHUTDOWN-ACK... do OOTB handling... */ 984204141Stuexen sctp_send_shutdown_complete(stcb, net, 1); 985204141Stuexen SCTP_TCB_UNLOCK(stcb); 986204141Stuexen return; 987204141Stuexen } 988163953Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) && 989163953Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { 990163953Srrs /* unexpected SHUTDOWN-ACK... so ignore... */ 991163953Srrs SCTP_TCB_UNLOCK(stcb); 992163953Srrs return; 993163953Srrs } 994165220Srrs if (asoc->control_pdapi) { 995163953Srrs /* 996163953Srrs * With a normal shutdown we assume the end of last record. 997163953Srrs */ 998163953Srrs SCTP_INP_READ_LOCK(stcb->sctp_ep); 999165220Srrs asoc->control_pdapi->end_added = 1; 1000165220Srrs asoc->control_pdapi->pdapi_aborted = 1; 1001165220Srrs asoc->control_pdapi = NULL; 1002163953Srrs SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 1003237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1004172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1005172090Srrs SCTP_TCB_UNLOCK(stcb); 1006172090Srrs SCTP_SOCKET_LOCK(so, 1); 1007172090Srrs SCTP_TCB_LOCK(stcb); 1008172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1009172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1010172090Srrs /* assoc was freed while we were unlocked */ 1011172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1012172090Srrs return; 1013172090Srrs } 1014172090Srrs#endif 1015163996Srrs sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 1016237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1017172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1018172090Srrs#endif 1019163953Srrs } 1020163953Srrs /* are the queues empty? */ 1021163953Srrs if (!TAILQ_EMPTY(&asoc->send_queue) || 1022163953Srrs !TAILQ_EMPTY(&asoc->sent_queue) || 1023217760Stuexen !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 1024235416Stuexen sctp_report_all_outbound(stcb, 0, 0, SCTP_SO_NOT_LOCKED); 1025163953Srrs } 1026163953Srrs /* stop the timer */ 1027171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9); 1028163953Srrs /* send SHUTDOWN-COMPLETE */ 1029204141Stuexen sctp_send_shutdown_complete(stcb, net, 0); 1030163953Srrs /* notify upper layer protocol */ 1031163953Srrs if (stcb->sctp_socket) { 1032163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1033163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 1034229774Stuexen stcb->sctp_socket->so_snd.sb_cc = 0; 1035163953Srrs } 1036230379Stuexen sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1037163953Srrs } 1038163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 1039163953Srrs /* free the TCB but first save off the ep */ 1040237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1041172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1042172090Srrs SCTP_TCB_UNLOCK(stcb); 1043172090Srrs SCTP_SOCKET_LOCK(so, 1); 1044172090Srrs SCTP_TCB_LOCK(stcb); 1045172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1046172090Srrs#endif 1047171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 1048171440Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_10); 1049237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1050172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1051172090Srrs#endif 1052163953Srrs} 1053163953Srrs 1054163953Srrs/* 1055163953Srrs * Skip past the param header and then we will find the chunk that caused the 1056163953Srrs * problem. There are two possiblities ASCONF or FWD-TSN other than that and 1057163953Srrs * our peer must be broken. 1058163953Srrs */ 1059163953Srrsstatic void 1060163953Srrssctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr, 1061163953Srrs struct sctp_nets *net) 1062163953Srrs{ 1063163953Srrs struct sctp_chunkhdr *chk; 1064163953Srrs 1065163953Srrs chk = (struct sctp_chunkhdr *)((caddr_t)phdr + sizeof(*phdr)); 1066163953Srrs switch (chk->chunk_type) { 1067163953Srrs case SCTP_ASCONF_ACK: 1068163953Srrs case SCTP_ASCONF: 1069163953Srrs sctp_asconf_cleanup(stcb, net); 1070163953Srrs break; 1071163953Srrs case SCTP_FORWARD_CUM_TSN: 1072163953Srrs stcb->asoc.peer_supports_prsctp = 0; 1073163953Srrs break; 1074163953Srrs default: 1075169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1076169420Srrs "Peer does not support chunk type %d(%x)??\n", 1077169420Srrs chk->chunk_type, (uint32_t) chk->chunk_type); 1078163953Srrs break; 1079163953Srrs } 1080163953Srrs} 1081163953Srrs 1082163953Srrs/* 1083163953Srrs * Skip past the param header and then we will find the param that caused the 1084163953Srrs * problem. There are a number of param's in a ASCONF OR the prsctp param 1085163953Srrs * these will turn of specific features. 1086163953Srrs */ 1087163953Srrsstatic void 1088163953Srrssctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr) 1089163953Srrs{ 1090163953Srrs struct sctp_paramhdr *pbad; 1091163953Srrs 1092163953Srrs pbad = phdr + 1; 1093163953Srrs switch (ntohs(pbad->param_type)) { 1094163953Srrs /* pr-sctp draft */ 1095163953Srrs case SCTP_PRSCTP_SUPPORTED: 1096163953Srrs stcb->asoc.peer_supports_prsctp = 0; 1097163953Srrs break; 1098163953Srrs case SCTP_SUPPORTED_CHUNK_EXT: 1099163953Srrs break; 1100163953Srrs /* draft-ietf-tsvwg-addip-sctp */ 1101185694Srrs case SCTP_HAS_NAT_SUPPORT: 1102185694Srrs stcb->asoc.peer_supports_nat = 0; 1103185694Srrs break; 1104163953Srrs case SCTP_ADD_IP_ADDRESS: 1105163953Srrs case SCTP_DEL_IP_ADDRESS: 1106163953Srrs case SCTP_SET_PRIM_ADDR: 1107163953Srrs stcb->asoc.peer_supports_asconf = 0; 1108163953Srrs break; 1109163953Srrs case SCTP_SUCCESS_REPORT: 1110163953Srrs case SCTP_ERROR_CAUSE_IND: 1111169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support success? or error cause?\n"); 1112169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1113169420Srrs "Turning off ASCONF to this strange peer\n"); 1114163953Srrs stcb->asoc.peer_supports_asconf = 0; 1115163953Srrs break; 1116163953Srrs default: 1117169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1118169420Srrs "Peer does not support param type %d(%x)??\n", 1119169420Srrs pbad->param_type, (uint32_t) pbad->param_type); 1120163953Srrs break; 1121163953Srrs } 1122163953Srrs} 1123163953Srrs 1124163953Srrsstatic int 1125163953Srrssctp_handle_error(struct sctp_chunkhdr *ch, 1126163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 1127163953Srrs{ 1128163953Srrs int chklen; 1129163953Srrs struct sctp_paramhdr *phdr; 1130235418Stuexen uint16_t error, error_type; 1131163953Srrs uint16_t error_len; 1132163953Srrs struct sctp_association *asoc; 1133163953Srrs int adjust; 1134163953Srrs 1135237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1136172090Srrs struct socket *so; 1137172090Srrs 1138172090Srrs#endif 1139172090Srrs 1140163953Srrs /* parse through all of the errors and process */ 1141163953Srrs asoc = &stcb->asoc; 1142163953Srrs phdr = (struct sctp_paramhdr *)((caddr_t)ch + 1143163953Srrs sizeof(struct sctp_chunkhdr)); 1144163953Srrs chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr); 1145235418Stuexen error = 0; 1146163953Srrs while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) { 1147163953Srrs /* Process an Error Cause */ 1148163953Srrs error_type = ntohs(phdr->param_type); 1149163953Srrs error_len = ntohs(phdr->param_length); 1150163953Srrs if ((error_len > chklen) || (error_len == 0)) { 1151163953Srrs /* invalid param length for this param */ 1152169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Bogus length in error param- chunk left:%d errorlen:%d\n", 1153169420Srrs chklen, error_len); 1154163953Srrs return (0); 1155163953Srrs } 1156235418Stuexen if (error == 0) { 1157235418Stuexen /* report the first error cause */ 1158235418Stuexen error = error_type; 1159235418Stuexen } 1160163953Srrs switch (error_type) { 1161163953Srrs case SCTP_CAUSE_INVALID_STREAM: 1162163953Srrs case SCTP_CAUSE_MISSING_PARAM: 1163163953Srrs case SCTP_CAUSE_INVALID_PARAM: 1164163953Srrs case SCTP_CAUSE_NO_USER_DATA: 1165169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Software error we got a %d back? We have a bug :/ (or do they?)\n", 1166169420Srrs error_type); 1167163953Srrs break; 1168185694Srrs case SCTP_CAUSE_NAT_COLLIDING_STATE: 1169185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 1170185694Srrs ch->chunk_flags); 1171185694Srrs if (sctp_handle_nat_colliding_state(stcb)) { 1172185694Srrs return (0); 1173185694Srrs } 1174185694Srrs break; 1175185694Srrs case SCTP_CAUSE_NAT_MISSING_STATE: 1176185694Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 1177185694Srrs ch->chunk_flags); 1178185694Srrs if (sctp_handle_nat_missing_state(stcb, net)) { 1179185694Srrs return (0); 1180185694Srrs } 1181185694Srrs break; 1182163953Srrs case SCTP_CAUSE_STALE_COOKIE: 1183163953Srrs /* 1184163953Srrs * We only act if we have echoed a cookie and are 1185163953Srrs * waiting. 1186163953Srrs */ 1187163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 1188163953Srrs int *p; 1189163953Srrs 1190163953Srrs p = (int *)((caddr_t)phdr + sizeof(*phdr)); 1191163953Srrs /* Save the time doubled */ 1192163953Srrs asoc->cookie_preserve_req = ntohl(*p) << 1; 1193163953Srrs asoc->stale_cookie_count++; 1194163953Srrs if (asoc->stale_cookie_count > 1195163953Srrs asoc->max_init_times) { 1196235403Stuexen sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); 1197163953Srrs /* now free the asoc */ 1198237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1199172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1200172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1201172090Srrs SCTP_TCB_UNLOCK(stcb); 1202172090Srrs SCTP_SOCKET_LOCK(so, 1); 1203172090Srrs SCTP_TCB_LOCK(stcb); 1204172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 1205172090Srrs#endif 1206171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 1207171943Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_11); 1208237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1209172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1210172090Srrs#endif 1211163953Srrs return (-1); 1212163953Srrs } 1213163953Srrs /* blast back to INIT state */ 1214185694Srrs sctp_toss_old_cookies(stcb, &stcb->asoc); 1215163953Srrs asoc->state &= ~SCTP_STATE_COOKIE_ECHOED; 1216163953Srrs asoc->state |= SCTP_STATE_COOKIE_WAIT; 1217163953Srrs sctp_stop_all_cookie_timers(stcb); 1218172090Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 1219163953Srrs } 1220163953Srrs break; 1221163953Srrs case SCTP_CAUSE_UNRESOLVABLE_ADDR: 1222163953Srrs /* 1223163953Srrs * Nothing we can do here, we don't do hostname 1224163953Srrs * addresses so if the peer does not like my IPv6 1225163953Srrs * (or IPv4 for that matter) it does not matter. If 1226163953Srrs * they don't support that type of address, they can 1227163953Srrs * NOT possibly get that packet type... i.e. with no 1228163953Srrs * IPv6 you can't recieve a IPv6 packet. so we can 1229163953Srrs * safely ignore this one. If we ever added support 1230163953Srrs * for HOSTNAME Addresses, then we would need to do 1231163953Srrs * something here. 1232163953Srrs */ 1233163953Srrs break; 1234163953Srrs case SCTP_CAUSE_UNRECOG_CHUNK: 1235163953Srrs sctp_process_unrecog_chunk(stcb, phdr, net); 1236163953Srrs break; 1237163953Srrs case SCTP_CAUSE_UNRECOG_PARAM: 1238163953Srrs sctp_process_unrecog_param(stcb, phdr); 1239163953Srrs break; 1240163953Srrs case SCTP_CAUSE_COOKIE_IN_SHUTDOWN: 1241163953Srrs /* 1242163953Srrs * We ignore this since the timer will drive out a 1243163953Srrs * new cookie anyway and there timer will drive us 1244163953Srrs * to send a SHUTDOWN_COMPLETE. We can't send one 1245163953Srrs * here since we don't have their tag. 1246163953Srrs */ 1247163953Srrs break; 1248163953Srrs case SCTP_CAUSE_DELETING_LAST_ADDR: 1249163953Srrs case SCTP_CAUSE_RESOURCE_SHORTAGE: 1250163953Srrs case SCTP_CAUSE_DELETING_SRC_ADDR: 1251163953Srrs /* 1252163953Srrs * We should NOT get these here, but in a 1253166086Srrs * ASCONF-ACK. 1254163953Srrs */ 1255169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "Peer sends ASCONF errors in a Operational Error?<%d>?\n", 1256169420Srrs error_type); 1257163953Srrs break; 1258163953Srrs case SCTP_CAUSE_OUT_OF_RESC: 1259163953Srrs /* 1260163953Srrs * And what, pray tell do we do with the fact that 1261163953Srrs * the peer is out of resources? Not really sure we 1262166086Srrs * could do anything but abort. I suspect this 1263163953Srrs * should have came WITH an abort instead of in a 1264163953Srrs * OP-ERROR. 1265163953Srrs */ 1266163953Srrs break; 1267163953Srrs default: 1268169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_handle_error: unknown error type = 0x%xh\n", 1269169420Srrs error_type); 1270163953Srrs break; 1271163953Srrs } 1272163953Srrs adjust = SCTP_SIZE32(error_len); 1273163953Srrs chklen -= adjust; 1274163953Srrs phdr = (struct sctp_paramhdr *)((caddr_t)phdr + adjust); 1275163953Srrs } 1276235418Stuexen sctp_ulp_notify(SCTP_NOTIFY_REMOTE_ERROR, stcb, error, ch, SCTP_SO_NOT_LOCKED); 1277163953Srrs return (0); 1278163953Srrs} 1279163953Srrs 1280163953Srrsstatic int 1281237049Stuexensctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh, 1282237049Stuexen struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 1283237049Stuexen struct sctp_nets *net, int *abort_no_unlock, 1284237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 1285237049Stuexen uint32_t vrf_id) 1286163953Srrs{ 1287163953Srrs struct sctp_init_ack *init_ack; 1288163953Srrs struct mbuf *op_err; 1289163953Srrs 1290169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1291169420Srrs "sctp_handle_init_ack: handling INIT-ACK\n"); 1292169420Srrs 1293163953Srrs if (stcb == NULL) { 1294169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 1295169420Srrs "sctp_handle_init_ack: TCB is null\n"); 1296163953Srrs return (-1); 1297163953Srrs } 1298163953Srrs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) { 1299163953Srrs /* Invalid length */ 1300163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1301163953Srrs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh, 1302237049Stuexen op_err, 1303237049Stuexen use_mflowid, mflowid, 1304237049Stuexen vrf_id, net->port); 1305168299Srrs *abort_no_unlock = 1; 1306163953Srrs return (-1); 1307163953Srrs } 1308163953Srrs init_ack = &cp->init; 1309163953Srrs /* validate parameters */ 1310163953Srrs if (init_ack->initiate_tag == 0) { 1311163953Srrs /* protocol error... send an abort */ 1312163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1313163953Srrs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh, 1314237049Stuexen op_err, 1315237049Stuexen use_mflowid, mflowid, 1316237049Stuexen vrf_id, net->port); 1317168299Srrs *abort_no_unlock = 1; 1318163953Srrs return (-1); 1319163953Srrs } 1320163953Srrs if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) { 1321163953Srrs /* protocol error... send an abort */ 1322163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1323163953Srrs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh, 1324237049Stuexen op_err, 1325237049Stuexen use_mflowid, mflowid, 1326237049Stuexen vrf_id, net->port); 1327168299Srrs *abort_no_unlock = 1; 1328163953Srrs return (-1); 1329163953Srrs } 1330163953Srrs if (init_ack->num_inbound_streams == 0) { 1331163953Srrs /* protocol error... send an abort */ 1332163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1333163953Srrs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh, 1334237049Stuexen op_err, 1335237049Stuexen use_mflowid, mflowid, 1336237049Stuexen vrf_id, net->port); 1337168299Srrs *abort_no_unlock = 1; 1338163953Srrs return (-1); 1339163953Srrs } 1340163953Srrs if (init_ack->num_outbound_streams == 0) { 1341163953Srrs /* protocol error... send an abort */ 1342163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1343163953Srrs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh, 1344237049Stuexen op_err, 1345237049Stuexen use_mflowid, mflowid, 1346237049Stuexen vrf_id, net->port); 1347168299Srrs *abort_no_unlock = 1; 1348163953Srrs return (-1); 1349163953Srrs } 1350163953Srrs /* process according to association state... */ 1351171943Srrs switch (stcb->asoc.state & SCTP_STATE_MASK) { 1352163953Srrs case SCTP_STATE_COOKIE_WAIT: 1353163953Srrs /* this is the expected state for this chunk */ 1354163953Srrs /* process the INIT-ACK parameters */ 1355163953Srrs if (stcb->asoc.primary_destination->dest_state & 1356163953Srrs SCTP_ADDR_UNCONFIRMED) { 1357163953Srrs /* 1358163953Srrs * The primary is where we sent the INIT, we can 1359163953Srrs * always consider it confirmed when the INIT-ACK is 1360163953Srrs * returned. Do this before we load addresses 1361163953Srrs * though. 1362163953Srrs */ 1363163953Srrs stcb->asoc.primary_destination->dest_state &= 1364163953Srrs ~SCTP_ADDR_UNCONFIRMED; 1365163953Srrs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 1366172090Srrs stcb, 0, (void *)stcb->asoc.primary_destination, SCTP_SO_NOT_LOCKED); 1367163953Srrs } 1368169352Srrs if (sctp_process_init_ack(m, iphlen, offset, sh, cp, stcb, 1369237049Stuexen net, abort_no_unlock, 1370237049Stuexen use_mflowid, mflowid, 1371237049Stuexen vrf_id) < 0) { 1372163953Srrs /* error in parsing parameters */ 1373163953Srrs return (-1); 1374163953Srrs } 1375163953Srrs /* update our state */ 1376169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to COOKIE-ECHOED state\n"); 1377171943Srrs SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_ECHOED); 1378163953Srrs 1379163953Srrs /* reset the RTO calc */ 1380179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1381171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1382171943Srrs stcb->asoc.overall_error_count, 1383171943Srrs 0, 1384171943Srrs SCTP_FROM_SCTP_INPUT, 1385171943Srrs __LINE__); 1386171943Srrs } 1387163953Srrs stcb->asoc.overall_error_count = 0; 1388169378Srrs (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 1389163953Srrs /* 1390163953Srrs * collapse the init timer back in case of a exponential 1391165220Srrs * backoff 1392163953Srrs */ 1393163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep, 1394163953Srrs stcb, net); 1395163953Srrs /* 1396163953Srrs * the send at the end of the inbound data processing will 1397163953Srrs * cause the cookie to be sent 1398163953Srrs */ 1399163953Srrs break; 1400163953Srrs case SCTP_STATE_SHUTDOWN_SENT: 1401163953Srrs /* incorrect state... discard */ 1402163953Srrs break; 1403163953Srrs case SCTP_STATE_COOKIE_ECHOED: 1404163953Srrs /* incorrect state... discard */ 1405163953Srrs break; 1406163953Srrs case SCTP_STATE_OPEN: 1407163953Srrs /* incorrect state... discard */ 1408163953Srrs break; 1409163953Srrs case SCTP_STATE_EMPTY: 1410163953Srrs case SCTP_STATE_INUSE: 1411163953Srrs default: 1412163953Srrs /* incorrect state... discard */ 1413163953Srrs return (-1); 1414163953Srrs break; 1415163953Srrs } 1416169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Leaving handle-init-ack end\n"); 1417163953Srrs return (0); 1418163953Srrs} 1419163953Srrs 1420185694Srrsstatic struct sctp_tcb * 1421185694Srrssctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 1422185694Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 1423185694Srrs struct sctp_inpcb *inp, struct sctp_nets **netp, 1424185694Srrs struct sockaddr *init_src, int *notification, 1425185694Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1426237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 1427185694Srrs uint32_t vrf_id, uint16_t port); 1428163953Srrs 1429185694Srrs 1430163953Srrs/* 1431163953Srrs * handle a state cookie for an existing association m: input packet mbuf 1432163953Srrs * chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a 1433163953Srrs * "split" mbuf and the cookie signature does not exist offset: offset into 1434163953Srrs * mbuf to the cookie-echo chunk 1435163953Srrs */ 1436163953Srrsstatic struct sctp_tcb * 1437163953Srrssctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, 1438163953Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 1439185694Srrs struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp, 1440228653Stuexen struct sockaddr *init_src, int *notification, 1441237049Stuexen int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1442237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 1443237049Stuexen uint32_t vrf_id, uint16_t port) 1444163953Srrs{ 1445163953Srrs struct sctp_association *asoc; 1446163953Srrs struct sctp_init_chunk *init_cp, init_buf; 1447163953Srrs struct sctp_init_ack_chunk *initack_cp, initack_buf; 1448185694Srrs struct sctp_nets *net; 1449185694Srrs struct mbuf *op_err; 1450185694Srrs struct sctp_paramhdr *ph; 1451165220Srrs int init_offset, initack_offset, i; 1452163953Srrs int retval; 1453164205Srrs int spec_flag = 0; 1454170140Srrs uint32_t how_indx; 1455163953Srrs 1456185694Srrs net = *netp; 1457163953Srrs /* I know that the TCB is non-NULL from the caller */ 1458163953Srrs asoc = &stcb->asoc; 1459166675Srrs for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); how_indx++) { 1460166023Srrs if (asoc->cookie_how[how_indx] == 0) 1461166023Srrs break; 1462166023Srrs } 1463166023Srrs if (how_indx < sizeof(asoc->cookie_how)) { 1464166023Srrs asoc->cookie_how[how_indx] = 1; 1465166023Srrs } 1466163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 1467163953Srrs /* SHUTDOWN came in after sending INIT-ACK */ 1468163953Srrs sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination); 1469163953Srrs op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 1470165647Srrs 0, M_DONTWAIT, 1, MT_DATA); 1471163953Srrs if (op_err == NULL) { 1472163953Srrs /* FOOBAR */ 1473163953Srrs return (NULL); 1474163953Srrs } 1475163953Srrs /* Set the len */ 1476165647Srrs SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); 1477163953Srrs ph = mtod(op_err, struct sctp_paramhdr *); 1478163953Srrs ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN); 1479163953Srrs ph->param_length = htons(sizeof(struct sctp_paramhdr)); 1480236956Stuexen sctp_send_operr_to(m, sh, cookie->peers_vtag, op_err, 1481237049Stuexen use_mflowid, mflowid, 1482179157Srrs vrf_id, net->port); 1483166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1484166023Srrs asoc->cookie_how[how_indx] = 2; 1485163953Srrs return (NULL); 1486163953Srrs } 1487163953Srrs /* 1488163953Srrs * find and validate the INIT chunk in the cookie (peer's info) the 1489163953Srrs * INIT should start after the cookie-echo header struct (chunk 1490163953Srrs * header, state cookie header struct) 1491163953Srrs */ 1492163953Srrs init_offset = offset += sizeof(struct sctp_cookie_echo_chunk); 1493163953Srrs 1494163953Srrs init_cp = (struct sctp_init_chunk *) 1495163953Srrs sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 1496163953Srrs (uint8_t *) & init_buf); 1497163953Srrs if (init_cp == NULL) { 1498163953Srrs /* could not pull a INIT chunk in cookie */ 1499163953Srrs return (NULL); 1500163953Srrs } 1501163953Srrs if (init_cp->ch.chunk_type != SCTP_INITIATION) { 1502163953Srrs return (NULL); 1503163953Srrs } 1504163953Srrs /* 1505163953Srrs * find and validate the INIT-ACK chunk in the cookie (my info) the 1506163953Srrs * INIT-ACK follows the INIT chunk 1507163953Srrs */ 1508228907Stuexen initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 1509163953Srrs initack_cp = (struct sctp_init_ack_chunk *) 1510163953Srrs sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 1511163953Srrs (uint8_t *) & initack_buf); 1512163953Srrs if (initack_cp == NULL) { 1513163953Srrs /* could not pull INIT-ACK chunk in cookie */ 1514163953Srrs return (NULL); 1515163953Srrs } 1516163953Srrs if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 1517163953Srrs return (NULL); 1518163953Srrs } 1519163953Srrs if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1520163953Srrs (ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag)) { 1521163953Srrs /* 1522163953Srrs * case D in Section 5.2.4 Table 2: MMAA process accordingly 1523163953Srrs * to get into the OPEN state 1524163953Srrs */ 1525166023Srrs if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 1526172091Srrs /*- 1527172091Srrs * Opps, this means that we somehow generated two vtag's 1528172091Srrs * the same. I.e. we did: 1529172091Srrs * Us Peer 1530172091Srrs * <---INIT(tag=a)------ 1531172091Srrs * ----INIT-ACK(tag=t)--> 1532172091Srrs * ----INIT(tag=t)------> *1 1533172091Srrs * <---INIT-ACK(tag=a)--- 1534172091Srrs * <----CE(tag=t)------------- *2 1535172091Srrs * 1536172091Srrs * At point *1 we should be generating a different 1537172091Srrs * tag t'. Which means we would throw away the CE and send 1538172091Srrs * ours instead. Basically this is case C (throw away side). 1539172091Srrs */ 1540172091Srrs if (how_indx < sizeof(asoc->cookie_how)) 1541172091Srrs asoc->cookie_how[how_indx] = 17; 1542172091Srrs return (NULL); 1543172091Srrs 1544166023Srrs } 1545163953Srrs switch SCTP_GET_STATE 1546163953Srrs (asoc) { 1547163953Srrs case SCTP_STATE_COOKIE_WAIT: 1548166023Srrs case SCTP_STATE_COOKIE_ECHOED: 1549163953Srrs /* 1550169352Srrs * INIT was sent but got a COOKIE_ECHO with the 1551166023Srrs * correct tags... just accept it...but we must 1552166023Srrs * process the init so that we can make sure we have 1553166023Srrs * the right seq no's. 1554163953Srrs */ 1555163953Srrs /* First we must process the INIT !! */ 1556228653Stuexen retval = sctp_process_init(init_cp, stcb); 1557163953Srrs if (retval < 0) { 1558166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1559166023Srrs asoc->cookie_how[how_indx] = 3; 1560163953Srrs return (NULL); 1561163953Srrs } 1562163953Srrs /* we have already processed the INIT so no problem */ 1563163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, 1564171440Srrs net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_12); 1565171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_13); 1566163953Srrs /* update current state */ 1567166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 1568166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 1569166675Srrs else 1570166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1571171943Srrs 1572171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1573163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1574163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1575163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1576163953Srrs } 1577166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1578165220Srrs sctp_stop_all_cookie_timers(stcb); 1579163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1580163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1581163953Srrs (inp->sctp_socket->so_qlimit == 0) 1582163953Srrs ) { 1583237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1584172090Srrs struct socket *so; 1585172090Srrs 1586172090Srrs#endif 1587163953Srrs /* 1588163953Srrs * Here is where collision would go if we 1589163953Srrs * did a connect() and instead got a 1590163953Srrs * init/init-ack/cookie done before the 1591163953Srrs * init-ack came back.. 1592163953Srrs */ 1593163953Srrs stcb->sctp_ep->sctp_flags |= 1594163953Srrs SCTP_PCB_FLAGS_CONNECTED; 1595237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1596172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1597172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1598172090Srrs SCTP_TCB_UNLOCK(stcb); 1599172090Srrs SCTP_SOCKET_LOCK(so, 1); 1600172090Srrs SCTP_TCB_LOCK(stcb); 1601172090Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1602172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1603172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1604172090Srrs return (NULL); 1605172090Srrs } 1606172090Srrs#endif 1607172090Srrs soisconnected(stcb->sctp_socket); 1608237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1609172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1610172090Srrs#endif 1611163953Srrs } 1612163953Srrs /* notify upper layer */ 1613163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 1614163953Srrs /* 1615163953Srrs * since we did not send a HB make sure we don't 1616163953Srrs * double things 1617163953Srrs */ 1618163953Srrs net->hb_responded = 1; 1619170642Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, 1620218186Srrs &cookie->time_entered, 1621218186Srrs sctp_align_unsafe_makecopy, 1622219397Srrs SCTP_RTT_FROM_NON_DATA); 1623163953Srrs 1624163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 1625163953Srrs (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) { 1626163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 1627163953Srrs inp, stcb, NULL); 1628163953Srrs } 1629163953Srrs break; 1630163953Srrs default: 1631163953Srrs /* 1632163953Srrs * we're in the OPEN state (or beyond), so peer must 1633163953Srrs * have simply lost the COOKIE-ACK 1634163953Srrs */ 1635163953Srrs break; 1636163953Srrs } /* end switch */ 1637165220Srrs sctp_stop_all_cookie_timers(stcb); 1638163953Srrs /* 1639163953Srrs * We ignore the return code here.. not sure if we should 1640163953Srrs * somehow abort.. but we do have an existing asoc. This 1641163953Srrs * really should not fail. 1642163953Srrs */ 1643228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1644163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1645163953Srrs initack_offset, sh, init_src)) { 1646166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1647166023Srrs asoc->cookie_how[how_indx] = 4; 1648163953Srrs return (NULL); 1649163953Srrs } 1650163953Srrs /* respond with a COOKIE-ACK */ 1651165220Srrs sctp_toss_old_cookies(stcb, asoc); 1652163953Srrs sctp_send_cookie_ack(stcb); 1653166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1654166023Srrs asoc->cookie_how[how_indx] = 5; 1655163953Srrs return (stcb); 1656169352Srrs } 1657163953Srrs if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 1658163953Srrs ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag && 1659163953Srrs cookie->tie_tag_my_vtag == 0 && 1660163953Srrs cookie->tie_tag_peer_vtag == 0) { 1661163953Srrs /* 1662163953Srrs * case C in Section 5.2.4 Table 2: XMOO silently discard 1663163953Srrs */ 1664166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1665166023Srrs asoc->cookie_how[how_indx] = 6; 1666163953Srrs return (NULL); 1667163953Srrs } 1668185694Srrs /* 1669185694Srrs * If nat support, and the below and stcb is established, send back 1670185694Srrs * a ABORT(colliding state) if we are established. 1671185694Srrs */ 1672185694Srrs if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) && 1673185694Srrs (asoc->peer_supports_nat) && 1674185694Srrs ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1675185694Srrs ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 1676185694Srrs (asoc->peer_vtag == 0)))) { 1677163953Srrs /* 1678185694Srrs * Special case - Peer's support nat. We may have two init's 1679185694Srrs * that we gave out the same tag on since one was not 1680185694Srrs * established.. i.e. we get INIT from host-1 behind the nat 1681185694Srrs * and we respond tag-a, we get a INIT from host-2 behind 1682185694Srrs * the nat and we get tag-a again. Then we bring up host-1 1683185694Srrs * (or 2's) assoc, Then comes the cookie from hsot-2 (or 1). 1684185694Srrs * Now we have colliding state. We must send an abort here 1685185694Srrs * with colliding state indication. 1686185694Srrs */ 1687185694Srrs op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 1688185694Srrs 0, M_DONTWAIT, 1, MT_DATA); 1689185694Srrs if (op_err == NULL) { 1690185694Srrs /* FOOBAR */ 1691185694Srrs return (NULL); 1692185694Srrs } 1693185694Srrs /* pre-reserve some space */ 1694185694Srrs#ifdef INET6 1695185694Srrs SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); 1696185694Srrs#else 1697185694Srrs SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); 1698185694Srrs#endif 1699185694Srrs SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); 1700185694Srrs SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); 1701185694Srrs /* Set the len */ 1702185694Srrs SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); 1703185694Srrs ph = mtod(op_err, struct sctp_paramhdr *); 1704185694Srrs ph->param_type = htons(SCTP_CAUSE_NAT_COLLIDING_STATE); 1705185694Srrs ph->param_length = htons(sizeof(struct sctp_paramhdr)); 1706237049Stuexen sctp_send_abort(m, iphlen, sh, 0, op_err, 1707237049Stuexen use_mflowid, mflowid, 1708237049Stuexen vrf_id, port); 1709185694Srrs return (NULL); 1710185694Srrs } 1711185694Srrs if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1712185694Srrs ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 1713185694Srrs (asoc->peer_vtag == 0))) { 1714185694Srrs /* 1715163953Srrs * case B in Section 5.2.4 Table 2: MXAA or MOAA my info 1716163953Srrs * should be ok, re-accept peer info 1717163953Srrs */ 1718166023Srrs if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 1719166023Srrs /* 1720166023Srrs * Extension of case C. If we hit this, then the 1721166023Srrs * random number generator returned the same vtag 1722166023Srrs * when we first sent our INIT-ACK and when we later 1723166023Srrs * sent our INIT. The side with the seq numbers that 1724166023Srrs * are different will be the one that normnally 1725166023Srrs * would have hit case C. This in effect "extends" 1726166023Srrs * our vtags in this collision case to be 64 bits. 1727166023Srrs * The same collision could occur aka you get both 1728166023Srrs * vtag and seq number the same twice in a row.. but 1729166023Srrs * is much less likely. If it did happen then we 1730166023Srrs * would proceed through and bring up the assoc.. we 1731166023Srrs * may end up with the wrong stream setup however.. 1732166023Srrs * which would be bad.. but there is no way to 1733166023Srrs * tell.. until we send on a stream that does not 1734166023Srrs * exist :-) 1735166023Srrs */ 1736166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1737166023Srrs asoc->cookie_how[how_indx] = 7; 1738166023Srrs 1739166023Srrs return (NULL); 1740166023Srrs } 1741166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1742166023Srrs asoc->cookie_how[how_indx] = 8; 1743171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_14); 1744163953Srrs sctp_stop_all_cookie_timers(stcb); 1745163953Srrs /* 1746163953Srrs * since we did not send a HB make sure we don't double 1747163953Srrs * things 1748163953Srrs */ 1749163953Srrs net->hb_responded = 1; 1750163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 1751163953Srrs sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 1752163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, 1753163953Srrs NULL); 1754163953Srrs } 1755163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 1756164205Srrs asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 1757164205Srrs 1758164205Srrs if (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) { 1759164205Srrs /* 1760164205Srrs * Ok the peer probably discarded our data (if we 1761164205Srrs * echoed a cookie+data). So anything on the 1762164205Srrs * sent_queue should be marked for retransmit, we 1763164205Srrs * may not get something to kick us so it COULD 1764164205Srrs * still take a timeout to move these.. but it can't 1765164205Srrs * hurt to mark them. 1766164205Srrs */ 1767164205Srrs struct sctp_tmit_chunk *chk; 1768163953Srrs 1769164205Srrs TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 1770164205Srrs if (chk->sent < SCTP_DATAGRAM_RESEND) { 1771164205Srrs chk->sent = SCTP_DATAGRAM_RESEND; 1772171440Srrs sctp_flight_size_decrease(chk); 1773171440Srrs sctp_total_flight_decrease(stcb, chk); 1774168124Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1775164205Srrs spec_flag++; 1776164205Srrs } 1777164205Srrs } 1778164205Srrs 1779164205Srrs } 1780163953Srrs /* process the INIT info (peer's info) */ 1781228653Stuexen retval = sctp_process_init(init_cp, stcb); 1782163953Srrs if (retval < 0) { 1783166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1784166023Srrs asoc->cookie_how[how_indx] = 9; 1785163953Srrs return (NULL); 1786163953Srrs } 1787228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1788163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1789163953Srrs initack_offset, sh, init_src)) { 1790166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1791166023Srrs asoc->cookie_how[how_indx] = 10; 1792163953Srrs return (NULL); 1793163953Srrs } 1794163953Srrs if ((asoc->state & SCTP_STATE_COOKIE_WAIT) || 1795163953Srrs (asoc->state & SCTP_STATE_COOKIE_ECHOED)) { 1796163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 1797163953Srrs 1798163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1799163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1800163953Srrs (inp->sctp_socket->so_qlimit == 0)) { 1801237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1802172090Srrs struct socket *so; 1803172090Srrs 1804172090Srrs#endif 1805163953Srrs stcb->sctp_ep->sctp_flags |= 1806163953Srrs SCTP_PCB_FLAGS_CONNECTED; 1807237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1808172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 1809172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1810172090Srrs SCTP_TCB_UNLOCK(stcb); 1811172090Srrs SCTP_SOCKET_LOCK(so, 1); 1812172090Srrs SCTP_TCB_LOCK(stcb); 1813172090Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1814172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1815172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1816172090Srrs return (NULL); 1817172090Srrs } 1818172090Srrs#endif 1819172090Srrs soisconnected(stcb->sctp_socket); 1820237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1821172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 1822172090Srrs#endif 1823163953Srrs } 1824166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 1825166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 1826166675Srrs else 1827166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1828166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1829166675Srrs } else if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 1830166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_restartestab); 1831166675Srrs } else { 1832166675Srrs SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1833163953Srrs } 1834171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1835163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1836163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1837163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1838163953Srrs } 1839163953Srrs sctp_stop_all_cookie_timers(stcb); 1840165220Srrs sctp_toss_old_cookies(stcb, asoc); 1841163953Srrs sctp_send_cookie_ack(stcb); 1842164205Srrs if (spec_flag) { 1843164205Srrs /* 1844164205Srrs * only if we have retrans set do we do this. What 1845164205Srrs * this call does is get only the COOKIE-ACK out and 1846164205Srrs * then when we return the normal call to 1847164205Srrs * sctp_chunk_output will get the retrans out behind 1848164205Srrs * this. 1849164205Srrs */ 1850172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_COOKIE_ACK, SCTP_SO_NOT_LOCKED); 1851164205Srrs } 1852166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1853166023Srrs asoc->cookie_how[how_indx] = 11; 1854166023Srrs 1855163953Srrs return (stcb); 1856163953Srrs } 1857163953Srrs if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 1858163953Srrs ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) && 1859163953Srrs cookie->tie_tag_my_vtag == asoc->my_vtag_nonce && 1860163953Srrs cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce && 1861163953Srrs cookie->tie_tag_peer_vtag != 0) { 1862163953Srrs struct sctpasochead *head; 1863163953Srrs 1864185694Srrs if (asoc->peer_supports_nat) { 1865185694Srrs /* 1866185694Srrs * This is a gross gross hack. just call the 1867185694Srrs * cookie_new code since we are allowing a duplicate 1868185694Srrs * association. I hope this works... 1869185694Srrs */ 1870185694Srrs return (sctp_process_cookie_new(m, iphlen, offset, sh, cookie, cookie_len, 1871185694Srrs inp, netp, init_src, notification, 1872185694Srrs auth_skipped, auth_offset, auth_len, 1873237049Stuexen use_mflowid, mflowid, 1874185694Srrs vrf_id, port)); 1875185694Srrs } 1876163953Srrs /* 1877163953Srrs * case A in Section 5.2.4 Table 2: XXMM (peer restarted) 1878163953Srrs */ 1879165220Srrs /* temp code */ 1880166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1881166023Srrs asoc->cookie_how[how_indx] = 12; 1882171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_15); 1883171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); 1884165647Srrs 1885163953Srrs /* notify upper layer */ 1886163953Srrs *notification = SCTP_NOTIFY_ASSOC_RESTART; 1887165220Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 1888166675Srrs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN) && 1889166675Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 1890166675Srrs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 1891166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1892166675Srrs } 1893166675Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 1894166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_restartestab); 1895166675Srrs } else if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { 1896166675Srrs SCTP_STAT_INCR_GAUGE32(sctps_collisionestab); 1897166675Srrs } 1898165647Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1899171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1900165647Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1901165647Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 1902165647Srrs 1903165647Srrs } else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) { 1904165647Srrs /* move to OPEN state, if not in SHUTDOWN_SENT */ 1905171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1906165647Srrs } 1907165647Srrs asoc->pre_open_streams = 1908165647Srrs ntohs(initack_cp->init.num_outbound_streams); 1909165647Srrs asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 1910165647Srrs asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 1911179157Srrs asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 1912165647Srrs 1913165647Srrs asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 1914165647Srrs 1915165647Srrs asoc->str_reset_seq_in = asoc->init_seq_number; 1916165647Srrs 1917165647Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 1918170138Srrs if (asoc->mapping_array) { 1919165647Srrs memset(asoc->mapping_array, 0, 1920165647Srrs asoc->mapping_array_size); 1921170138Srrs } 1922205627Srrs if (asoc->nr_mapping_array) { 1923185694Srrs memset(asoc->nr_mapping_array, 0, 1924206137Stuexen asoc->mapping_array_size); 1925185694Srrs } 1926165220Srrs SCTP_TCB_UNLOCK(stcb); 1927165220Srrs SCTP_INP_INFO_WLOCK(); 1928165220Srrs SCTP_INP_WLOCK(stcb->sctp_ep); 1929165220Srrs SCTP_TCB_LOCK(stcb); 1930165220Srrs atomic_add_int(&stcb->asoc.refcnt, -1); 1931163953Srrs /* send up all the data */ 1932164205Srrs SCTP_TCB_SEND_LOCK(stcb); 1933165220Srrs 1934235416Stuexen sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_NOT_LOCKED); 1935165220Srrs for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 1936165220Srrs stcb->asoc.strmout[i].stream_no = i; 1937165220Srrs stcb->asoc.strmout[i].next_sequence_sent = 0; 1938165220Srrs stcb->asoc.strmout[i].last_msg_incomplete = 0; 1939165220Srrs } 1940163953Srrs /* process the INIT-ACK info (my info) */ 1941163953Srrs asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 1942163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 1943163953Srrs 1944163953Srrs /* pull from vtag hash */ 1945163953Srrs LIST_REMOVE(stcb, sctp_asocs); 1946163953Srrs /* re-insert to new vtag position */ 1947179783Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, 1948179783Srrs SCTP_BASE_INFO(hashasocmark))]; 1949163953Srrs /* 1950163953Srrs * put it in the bucket in the vtag hash of assoc's for the 1951163953Srrs * system 1952163953Srrs */ 1953163953Srrs LIST_INSERT_HEAD(head, stcb, sctp_asocs); 1954163953Srrs 1955163953Srrs /* process the INIT info (peer's info) */ 1956164205Srrs SCTP_TCB_SEND_UNLOCK(stcb); 1957165220Srrs SCTP_INP_WUNLOCK(stcb->sctp_ep); 1958165220Srrs SCTP_INP_INFO_WUNLOCK(); 1959165220Srrs 1960228653Stuexen retval = sctp_process_init(init_cp, stcb); 1961163953Srrs if (retval < 0) { 1962166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1963166023Srrs asoc->cookie_how[how_indx] = 13; 1964166023Srrs 1965163953Srrs return (NULL); 1966163953Srrs } 1967163953Srrs /* 1968163953Srrs * since we did not send a HB make sure we don't double 1969163953Srrs * things 1970163953Srrs */ 1971163953Srrs net->hb_responded = 1; 1972163953Srrs 1973228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 1974163953Srrs init_offset + sizeof(struct sctp_init_chunk), 1975163953Srrs initack_offset, sh, init_src)) { 1976166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1977166023Srrs asoc->cookie_how[how_indx] = 14; 1978166023Srrs 1979163953Srrs return (NULL); 1980163953Srrs } 1981163953Srrs /* respond with a COOKIE-ACK */ 1982163953Srrs sctp_stop_all_cookie_timers(stcb); 1983165220Srrs sctp_toss_old_cookies(stcb, asoc); 1984163953Srrs sctp_send_cookie_ack(stcb); 1985166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1986166023Srrs asoc->cookie_how[how_indx] = 15; 1987163953Srrs 1988163953Srrs return (stcb); 1989163953Srrs } 1990166023Srrs if (how_indx < sizeof(asoc->cookie_how)) 1991166023Srrs asoc->cookie_how[how_indx] = 16; 1992163953Srrs /* all other cases... */ 1993163953Srrs return (NULL); 1994163953Srrs} 1995163953Srrs 1996166086Srrs 1997163953Srrs/* 1998163953Srrs * handle a state cookie for a new association m: input packet mbuf chain-- 1999163953Srrs * assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a "split" mbuf 2000163953Srrs * and the cookie signature does not exist offset: offset into mbuf to the 2001163953Srrs * cookie-echo chunk length: length of the cookie chunk to: where the init 2002163953Srrs * was from returns a new TCB 2003163953Srrs */ 2004237049Stuexenstatic struct sctp_tcb * 2005163953Srrssctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 2006163953Srrs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 2007163953Srrs struct sctp_inpcb *inp, struct sctp_nets **netp, 2008163953Srrs struct sockaddr *init_src, int *notification, 2009169352Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 2010237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 2011179157Srrs uint32_t vrf_id, uint16_t port) 2012163953Srrs{ 2013163953Srrs struct sctp_tcb *stcb; 2014163953Srrs struct sctp_init_chunk *init_cp, init_buf; 2015163953Srrs struct sctp_init_ack_chunk *initack_cp, initack_buf; 2016163953Srrs struct sockaddr_storage sa_store; 2017163953Srrs struct sockaddr *initack_src = (struct sockaddr *)&sa_store; 2018163953Srrs struct sctp_association *asoc; 2019163953Srrs int init_offset, initack_offset, initack_limit; 2020163953Srrs int retval; 2021163953Srrs int error = 0; 2022166675Srrs uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE]; 2023163953Srrs 2024221249Stuexen#ifdef INET 2025221249Stuexen struct sockaddr_in *sin; 2026221249Stuexen 2027221249Stuexen#endif 2028221249Stuexen#ifdef INET6 2029221249Stuexen struct sockaddr_in6 *sin6; 2030221249Stuexen 2031221249Stuexen#endif 2032237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2033172090Srrs struct socket *so; 2034172090Srrs 2035172090Srrs so = SCTP_INP_SO(inp); 2036172090Srrs#endif 2037172090Srrs 2038163953Srrs /* 2039163953Srrs * find and validate the INIT chunk in the cookie (peer's info) the 2040163953Srrs * INIT should start after the cookie-echo header struct (chunk 2041163953Srrs * header, state cookie header struct) 2042163953Srrs */ 2043163953Srrs init_offset = offset + sizeof(struct sctp_cookie_echo_chunk); 2044163953Srrs init_cp = (struct sctp_init_chunk *) 2045163953Srrs sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 2046163953Srrs (uint8_t *) & init_buf); 2047163953Srrs if (init_cp == NULL) { 2048163953Srrs /* could not pull a INIT chunk in cookie */ 2049169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 2050169420Srrs "process_cookie_new: could not pull INIT chunk hdr\n"); 2051163953Srrs return (NULL); 2052163953Srrs } 2053163953Srrs if (init_cp->ch.chunk_type != SCTP_INITIATION) { 2054169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "HUH? process_cookie_new: could not find INIT chunk!\n"); 2055163953Srrs return (NULL); 2056163953Srrs } 2057228907Stuexen initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 2058163953Srrs /* 2059163953Srrs * find and validate the INIT-ACK chunk in the cookie (my info) the 2060163953Srrs * INIT-ACK follows the INIT chunk 2061163953Srrs */ 2062163953Srrs initack_cp = (struct sctp_init_ack_chunk *) 2063163953Srrs sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 2064163953Srrs (uint8_t *) & initack_buf); 2065163953Srrs if (initack_cp == NULL) { 2066163953Srrs /* could not pull INIT-ACK chunk in cookie */ 2067169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: could not pull INIT-ACK chunk hdr\n"); 2068163953Srrs return (NULL); 2069163953Srrs } 2070163953Srrs if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 2071163953Srrs return (NULL); 2072163953Srrs } 2073163953Srrs /* 2074163953Srrs * NOTE: We can't use the INIT_ACK's chk_length to determine the 2075163953Srrs * "initack_limit" value. This is because the chk_length field 2076163953Srrs * includes the length of the cookie, but the cookie is omitted when 2077163953Srrs * the INIT and INIT_ACK are tacked onto the cookie... 2078163953Srrs */ 2079163953Srrs initack_limit = offset + cookie_len; 2080163953Srrs 2081163953Srrs /* 2082163953Srrs * now that we know the INIT/INIT-ACK are in place, create a new TCB 2083163953Srrs * and popluate 2084163953Srrs */ 2085171531Srrs 2086171531Srrs /* 2087171531Srrs * Here we do a trick, we set in NULL for the proc/thread argument. 2088171531Srrs * We do this since in effect we only use the p argument when the 2089171531Srrs * socket is unbound and we must do an implicit bind. Since we are 2090171531Srrs * getting a cookie, we cannot be unbound. 2091171531Srrs */ 2092206137Stuexen stcb = sctp_aloc_assoc(inp, init_src, &error, 2093171531Srrs ntohl(initack_cp->init.initiate_tag), vrf_id, 2094171531Srrs (struct thread *)NULL 2095171531Srrs ); 2096163953Srrs if (stcb == NULL) { 2097163953Srrs struct mbuf *op_err; 2098163953Srrs 2099163953Srrs /* memory problem? */ 2100169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 2101169420Srrs "process_cookie_new: no room for another TCB!\n"); 2102163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); 2103170140Srrs 2104163953Srrs sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 2105237049Stuexen sh, op_err, 2106237049Stuexen use_mflowid, mflowid, 2107237049Stuexen vrf_id, port); 2108163953Srrs return (NULL); 2109163953Srrs } 2110163953Srrs /* get the correct sctp_nets */ 2111169420Srrs if (netp) 2112169420Srrs *netp = sctp_findnet(stcb, init_src); 2113169420Srrs 2114163953Srrs asoc = &stcb->asoc; 2115163953Srrs /* get scope variables out of cookie */ 2116163953Srrs asoc->ipv4_local_scope = cookie->ipv4_scope; 2117163953Srrs asoc->site_scope = cookie->site_scope; 2118163953Srrs asoc->local_scope = cookie->local_scope; 2119163953Srrs asoc->loopback_scope = cookie->loopback_scope; 2120163953Srrs 2121163953Srrs if ((asoc->ipv4_addr_legal != cookie->ipv4_addr_legal) || 2122163953Srrs (asoc->ipv6_addr_legal != cookie->ipv6_addr_legal)) { 2123163953Srrs struct mbuf *op_err; 2124163953Srrs 2125163953Srrs /* 2126163953Srrs * Houston we have a problem. The EP changed while the 2127163953Srrs * cookie was in flight. Only recourse is to abort the 2128163953Srrs * association. 2129163953Srrs */ 2130170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2131163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); 2132163953Srrs sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 2133237049Stuexen sh, op_err, 2134237049Stuexen use_mflowid, mflowid, 2135237049Stuexen vrf_id, port); 2136237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2137172090Srrs SCTP_TCB_UNLOCK(stcb); 2138172090Srrs SCTP_SOCKET_LOCK(so, 1); 2139172090Srrs SCTP_TCB_LOCK(stcb); 2140172090Srrs#endif 2141171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 2142171440Srrs SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); 2143237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2144172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2145172090Srrs#endif 2146172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2147163953Srrs return (NULL); 2148163953Srrs } 2149163953Srrs /* process the INIT-ACK info (my info) */ 2150185694Srrs asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 2151163953Srrs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 2152163953Srrs asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 2153163953Srrs asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 2154163953Srrs asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 2155179157Srrs asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 2156163953Srrs asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 2157163953Srrs asoc->str_reset_seq_in = asoc->init_seq_number; 2158163953Srrs 2159163953Srrs asoc->advanced_peer_ack_point = asoc->last_acked_seq; 2160163953Srrs 2161163953Srrs /* process the INIT info (peer's info) */ 2162169420Srrs if (netp) 2163228653Stuexen retval = sctp_process_init(init_cp, stcb); 2164169420Srrs else 2165169420Srrs retval = 0; 2166163953Srrs if (retval < 0) { 2167170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2168237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2169172090Srrs SCTP_TCB_UNLOCK(stcb); 2170172090Srrs SCTP_SOCKET_LOCK(so, 1); 2171172090Srrs SCTP_TCB_LOCK(stcb); 2172172090Srrs#endif 2173171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16); 2174237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2175172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2176172090Srrs#endif 2177172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2178163953Srrs return (NULL); 2179163953Srrs } 2180163953Srrs /* load all addresses */ 2181228653Stuexen if (sctp_load_addresses_from_init(stcb, m, 2182163953Srrs init_offset + sizeof(struct sctp_init_chunk), initack_offset, sh, 2183163953Srrs init_src)) { 2184170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2185237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2186172090Srrs SCTP_TCB_UNLOCK(stcb); 2187172090Srrs SCTP_SOCKET_LOCK(so, 1); 2188172090Srrs SCTP_TCB_LOCK(stcb); 2189172090Srrs#endif 2190171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_17); 2191237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2192172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2193172090Srrs#endif 2194172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2195163953Srrs return (NULL); 2196163953Srrs } 2197163953Srrs /* 2198163953Srrs * verify any preceding AUTH chunk that was skipped 2199163953Srrs */ 2200163953Srrs /* pull the local authentication parameters from the cookie/init-ack */ 2201163953Srrs sctp_auth_get_cookie_params(stcb, m, 2202163953Srrs initack_offset + sizeof(struct sctp_init_ack_chunk), 2203163953Srrs initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk))); 2204163953Srrs if (auth_skipped) { 2205163953Srrs struct sctp_auth_chunk *auth; 2206163953Srrs 2207163953Srrs auth = (struct sctp_auth_chunk *) 2208166675Srrs sctp_m_getptr(m, auth_offset, auth_len, auth_chunk_buf); 2209169420Srrs if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, auth_offset)) { 2210163953Srrs /* auth HMAC failed, dump the assoc and packet */ 2211169420Srrs SCTPDBG(SCTP_DEBUG_AUTH1, 2212169420Srrs "COOKIE-ECHO: AUTH failed\n"); 2213171440Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2214237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2215172090Srrs SCTP_TCB_UNLOCK(stcb); 2216172090Srrs SCTP_SOCKET_LOCK(so, 1); 2217172090Srrs SCTP_TCB_LOCK(stcb); 2218172090Srrs#endif 2219171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_18); 2220237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2221172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2222172090Srrs#endif 2223172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2224163953Srrs return (NULL); 2225163953Srrs } else { 2226163953Srrs /* remaining chunks checked... good to go */ 2227163953Srrs stcb->asoc.authenticated = 1; 2228163953Srrs } 2229163953Srrs } 2230163953Srrs /* update current state */ 2231169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 2232171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 2233163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 2234163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 2235163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 2236163953Srrs } 2237165220Srrs sctp_stop_all_cookie_timers(stcb); 2238163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_passiveestab); 2239163953Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 2240163953Srrs 2241163953Srrs /* 2242163953Srrs * if we're doing ASCONFs, check to see if we have any new local 2243163953Srrs * addresses that need to get added to the peer (eg. addresses 2244163953Srrs * changed while cookie echo in flight). This needs to be done 2245163953Srrs * after we go to the OPEN state to do the correct asconf 2246163953Srrs * processing. else, make sure we have the correct addresses in our 2247163953Srrs * lists 2248163953Srrs */ 2249163953Srrs 2250163953Srrs /* warning, we re-use sin, sin6, sa_store here! */ 2251163953Srrs /* pull in local_address (our "from" address) */ 2252221249Stuexen switch (cookie->laddr_type) { 2253221249Stuexen#ifdef INET 2254221249Stuexen case SCTP_IPV4_ADDRESS: 2255163953Srrs /* source addr is IPv4 */ 2256163953Srrs sin = (struct sockaddr_in *)initack_src; 2257163953Srrs memset(sin, 0, sizeof(*sin)); 2258163953Srrs sin->sin_family = AF_INET; 2259163953Srrs sin->sin_len = sizeof(struct sockaddr_in); 2260163953Srrs sin->sin_addr.s_addr = cookie->laddress[0]; 2261221249Stuexen break; 2262221249Stuexen#endif 2263221249Stuexen#ifdef INET6 2264221249Stuexen case SCTP_IPV6_ADDRESS: 2265163953Srrs /* source addr is IPv6 */ 2266163953Srrs sin6 = (struct sockaddr_in6 *)initack_src; 2267163953Srrs memset(sin6, 0, sizeof(*sin6)); 2268163953Srrs sin6->sin6_family = AF_INET6; 2269163953Srrs sin6->sin6_len = sizeof(struct sockaddr_in6); 2270163953Srrs sin6->sin6_scope_id = cookie->scope_id; 2271163953Srrs memcpy(&sin6->sin6_addr, cookie->laddress, 2272163953Srrs sizeof(sin6->sin6_addr)); 2273221249Stuexen break; 2274221249Stuexen#endif 2275221249Stuexen default: 2276170140Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2277237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2278172090Srrs SCTP_TCB_UNLOCK(stcb); 2279172090Srrs SCTP_SOCKET_LOCK(so, 1); 2280172090Srrs SCTP_TCB_LOCK(stcb); 2281172090Srrs#endif 2282171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_19); 2283237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2284172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2285172090Srrs#endif 2286172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2287163953Srrs return (NULL); 2288163953Srrs } 2289163953Srrs 2290163953Srrs /* set up to notify upper layer */ 2291163953Srrs *notification = SCTP_NOTIFY_ASSOC_UP; 2292163953Srrs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2293163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 2294163953Srrs (inp->sctp_socket->so_qlimit == 0)) { 2295163953Srrs /* 2296163953Srrs * This is an endpoint that called connect() how it got a 2297163953Srrs * cookie that is NEW is a bit of a mystery. It must be that 2298163953Srrs * the INIT was sent, but before it got there.. a complete 2299163953Srrs * INIT/INIT-ACK/COOKIE arrived. But of course then it 2300163953Srrs * should have went to the other code.. not here.. oh well.. 2301163953Srrs * a bit of protection is worth having.. 2302163953Srrs */ 2303163953Srrs stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 2304237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2305172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2306172090Srrs SCTP_TCB_UNLOCK(stcb); 2307172090Srrs SCTP_SOCKET_LOCK(so, 1); 2308172090Srrs SCTP_TCB_LOCK(stcb); 2309172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2310172090Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 2311172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2312172090Srrs return (NULL); 2313172090Srrs } 2314172090Srrs#endif 2315172090Srrs soisconnected(stcb->sctp_socket); 2316237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2317172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2318172090Srrs#endif 2319163953Srrs } else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 2320163953Srrs (inp->sctp_socket->so_qlimit)) { 2321163953Srrs /* 2322163953Srrs * We don't want to do anything with this one. Since it is 2323163953Srrs * the listening guy. The timer will get started for 2324163953Srrs * accepted connections in the caller. 2325163953Srrs */ 2326163953Srrs ; 2327163953Srrs } 2328163953Srrs /* since we did not send a HB make sure we don't double things */ 2329169420Srrs if ((netp) && (*netp)) 2330169420Srrs (*netp)->hb_responded = 1; 2331163953Srrs 2332163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 2333163953Srrs sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 2334163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL); 2335163953Srrs } 2336165220Srrs /* calculate the RTT */ 2337171440Srrs (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 2338170642Srrs if ((netp) && (*netp)) { 2339169420Srrs (*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp, 2340218186Srrs &cookie->time_entered, sctp_align_unsafe_makecopy, 2341219397Srrs SCTP_RTT_FROM_NON_DATA); 2342170642Srrs } 2343172190Srrs /* respond with a COOKIE-ACK */ 2344163953Srrs sctp_send_cookie_ack(stcb); 2345172190Srrs 2346172190Srrs /* 2347172190Srrs * check the address lists for any ASCONFs that need to be sent 2348172190Srrs * AFTER the cookie-ack is sent 2349172190Srrs */ 2350172190Srrs sctp_check_address_list(stcb, m, 2351172190Srrs initack_offset + sizeof(struct sctp_init_ack_chunk), 2352172190Srrs initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)), 2353172190Srrs initack_src, cookie->local_scope, cookie->site_scope, 2354172190Srrs cookie->ipv4_scope, cookie->loopback_scope); 2355172190Srrs 2356172190Srrs 2357163953Srrs return (stcb); 2358163953Srrs} 2359163953Srrs 2360185694Srrs/* 2361185694Srrs * CODE LIKE THIS NEEDS TO RUN IF the peer supports the NAT extension, i.e 2362185694Srrs * we NEED to make sure we are not already using the vtag. If so we 2363185694Srrs * need to send back an ABORT-TRY-AGAIN-WITH-NEW-TAG No middle box bit! 2364185694Srrs head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag, 2365185694Srrs SCTP_BASE_INFO(hashasocmark))]; 2366185694Srrs LIST_FOREACH(stcb, head, sctp_asocs) { 2367185694Srrs if ((stcb->asoc.my_vtag == tag) && (stcb->rport == rport) && (inp == stcb->sctp_ep)) { 2368185694Srrs -- SEND ABORT - TRY AGAIN -- 2369185694Srrs } 2370185694Srrs } 2371185694Srrs*/ 2372163953Srrs 2373163953Srrs/* 2374163953Srrs * handles a COOKIE-ECHO message stcb: modified to either a new or left as 2375163953Srrs * existing (non-NULL) TCB 2376163953Srrs */ 2377163953Srrsstatic struct mbuf * 2378163953Srrssctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, 2379163953Srrs struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp, 2380163953Srrs struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp, 2381169352Srrs int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 2382237049Stuexen struct sctp_tcb **locked_tcb, 2383237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 2384237049Stuexen uint32_t vrf_id, uint16_t port) 2385163953Srrs{ 2386163953Srrs struct sctp_state_cookie *cookie; 2387163953Srrs struct sctp_tcb *l_stcb = *stcb; 2388163953Srrs struct sctp_inpcb *l_inp; 2389163953Srrs struct sockaddr *to; 2390163953Srrs struct sctp_pcb *ep; 2391163953Srrs struct mbuf *m_sig; 2392163953Srrs uint8_t calc_sig[SCTP_SIGNATURE_SIZE], tmp_sig[SCTP_SIGNATURE_SIZE]; 2393163953Srrs uint8_t *sig; 2394163953Srrs uint8_t cookie_ok = 0; 2395237541Stuexen unsigned int sig_offset, cookie_offset; 2396163953Srrs unsigned int cookie_len; 2397163953Srrs struct timeval now; 2398163953Srrs struct timeval time_expires; 2399163953Srrs struct sockaddr_storage dest_store; 2400163953Srrs struct sockaddr *localep_sa = (struct sockaddr *)&dest_store; 2401163953Srrs struct ip *iph; 2402163953Srrs int notification = 0; 2403163953Srrs struct sctp_nets *netl; 2404163953Srrs int had_a_existing_tcb = 0; 2405216887Stuexen int send_int_conf = 0; 2406163953Srrs 2407221249Stuexen#ifdef INET 2408221249Stuexen struct sockaddr_in sin; 2409221249Stuexen 2410221249Stuexen#endif 2411221249Stuexen#ifdef INET6 2412221249Stuexen struct sockaddr_in6 sin6; 2413221249Stuexen 2414221249Stuexen#endif 2415221249Stuexen 2416169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2417169420Srrs "sctp_handle_cookie: handling COOKIE-ECHO\n"); 2418163953Srrs 2419163953Srrs if (inp_p == NULL) { 2420163953Srrs return (NULL); 2421163953Srrs } 2422163953Srrs /* First get the destination address setup too. */ 2423163953Srrs iph = mtod(m, struct ip *); 2424178251Srrs switch (iph->ip_v) { 2425221249Stuexen#ifdef INET 2426178251Srrs case IPVERSION: 2427178251Srrs { 2428178251Srrs /* its IPv4 */ 2429178251Srrs struct sockaddr_in *lsin; 2430163953Srrs 2431178251Srrs lsin = (struct sockaddr_in *)(localep_sa); 2432178251Srrs memset(lsin, 0, sizeof(*lsin)); 2433178251Srrs lsin->sin_family = AF_INET; 2434178251Srrs lsin->sin_len = sizeof(*lsin); 2435178251Srrs lsin->sin_port = sh->dest_port; 2436178251Srrs lsin->sin_addr.s_addr = iph->ip_dst.s_addr; 2437178251Srrs break; 2438178251Srrs } 2439221249Stuexen#endif 2440178251Srrs#ifdef INET6 2441178251Srrs case IPV6_VERSION >> 4: 2442178251Srrs { 2443178251Srrs /* its IPv6 */ 2444178251Srrs struct ip6_hdr *ip6; 2445178251Srrs struct sockaddr_in6 *lsin6; 2446163953Srrs 2447178251Srrs lsin6 = (struct sockaddr_in6 *)(localep_sa); 2448178251Srrs memset(lsin6, 0, sizeof(*lsin6)); 2449178251Srrs lsin6->sin6_family = AF_INET6; 2450178251Srrs lsin6->sin6_len = sizeof(struct sockaddr_in6); 2451178251Srrs ip6 = mtod(m, struct ip6_hdr *); 2452178251Srrs lsin6->sin6_port = sh->dest_port; 2453178251Srrs lsin6->sin6_addr = ip6->ip6_dst; 2454178251Srrs break; 2455178251Srrs } 2456178251Srrs#endif 2457178251Srrs default: 2458163953Srrs return (NULL); 2459163953Srrs } 2460163953Srrs 2461163953Srrs cookie = &cp->cookie; 2462163953Srrs cookie_offset = offset + sizeof(struct sctp_chunkhdr); 2463163953Srrs cookie_len = ntohs(cp->ch.chunk_length); 2464163953Srrs 2465163953Srrs if ((cookie->peerport != sh->src_port) && 2466163953Srrs (cookie->myport != sh->dest_port) && 2467163953Srrs (cookie->my_vtag != sh->v_tag)) { 2468163953Srrs /* 2469163953Srrs * invalid ports or bad tag. Note that we always leave the 2470163953Srrs * v_tag in the header in network order and when we stored 2471163953Srrs * it in the my_vtag slot we also left it in network order. 2472169352Srrs * This maintains the match even though it may be in the 2473163953Srrs * opposite byte order of the machine :-> 2474163953Srrs */ 2475163953Srrs return (NULL); 2476163953Srrs } 2477237541Stuexen if (cookie_len < sizeof(struct sctp_cookie_echo_chunk) + 2478163953Srrs sizeof(struct sctp_init_chunk) + 2479163953Srrs sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) { 2480237541Stuexen /* cookie too small */ 2481163953Srrs return (NULL); 2482163953Srrs } 2483163953Srrs /* 2484163953Srrs * split off the signature into its own mbuf (since it should not be 2485163953Srrs * calculated in the sctp_hmac_m() call). 2486163953Srrs */ 2487163953Srrs sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE; 2488163953Srrs m_sig = m_split(m, sig_offset, M_DONTWAIT); 2489163953Srrs if (m_sig == NULL) { 2490163953Srrs /* out of memory or ?? */ 2491163953Srrs return (NULL); 2492163953Srrs } 2493178202Srrs#ifdef SCTP_MBUF_LOGGING 2494179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 2495178202Srrs struct mbuf *mat; 2496178202Srrs 2497234461Stuexen for (mat = m_sig; mat; mat = SCTP_BUF_NEXT(mat)) { 2498178202Srrs if (SCTP_BUF_IS_EXTENDED(mat)) { 2499178202Srrs sctp_log_mb(mat, SCTP_MBUF_SPLIT); 2500178202Srrs } 2501178202Srrs } 2502178202Srrs } 2503178202Srrs#endif 2504178202Srrs 2505163953Srrs /* 2506163953Srrs * compute the signature/digest for the cookie 2507163953Srrs */ 2508163953Srrs ep = &(*inp_p)->sctp_ep; 2509163953Srrs l_inp = *inp_p; 2510163953Srrs if (l_stcb) { 2511163953Srrs SCTP_TCB_UNLOCK(l_stcb); 2512163953Srrs } 2513163953Srrs SCTP_INP_RLOCK(l_inp); 2514163953Srrs if (l_stcb) { 2515163953Srrs SCTP_TCB_LOCK(l_stcb); 2516163953Srrs } 2517163953Srrs /* which cookie is it? */ 2518163953Srrs if ((cookie->time_entered.tv_sec < (long)ep->time_of_secret_change) && 2519163953Srrs (ep->current_secret_number != ep->last_secret_number)) { 2520163953Srrs /* it's the old cookie */ 2521169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2522163953Srrs (uint8_t *) ep->secret_key[(int)ep->last_secret_number], 2523170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2524163953Srrs } else { 2525163953Srrs /* it's the current cookie */ 2526169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2527163953Srrs (uint8_t *) ep->secret_key[(int)ep->current_secret_number], 2528170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2529163953Srrs } 2530163953Srrs /* get the signature */ 2531163953Srrs SCTP_INP_RUNLOCK(l_inp); 2532163953Srrs sig = (uint8_t *) sctp_m_getptr(m_sig, 0, SCTP_SIGNATURE_SIZE, (uint8_t *) & tmp_sig); 2533163953Srrs if (sig == NULL) { 2534163953Srrs /* couldn't find signature */ 2535164085Srrs sctp_m_freem(m_sig); 2536163953Srrs return (NULL); 2537163953Srrs } 2538163953Srrs /* compare the received digest with the computed digest */ 2539163953Srrs if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) != 0) { 2540163953Srrs /* try the old cookie? */ 2541163953Srrs if ((cookie->time_entered.tv_sec == (long)ep->time_of_secret_change) && 2542163953Srrs (ep->current_secret_number != ep->last_secret_number)) { 2543163953Srrs /* compute digest with old */ 2544169378Srrs (void)sctp_hmac_m(SCTP_HMAC, 2545163953Srrs (uint8_t *) ep->secret_key[(int)ep->last_secret_number], 2546170462Srrs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 2547163953Srrs /* compare */ 2548163953Srrs if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) == 0) 2549163953Srrs cookie_ok = 1; 2550163953Srrs } 2551163953Srrs } else { 2552163953Srrs cookie_ok = 1; 2553163953Srrs } 2554163953Srrs 2555163953Srrs /* 2556163953Srrs * Now before we continue we must reconstruct our mbuf so that 2557163953Srrs * normal processing of any other chunks will work. 2558163953Srrs */ 2559163953Srrs { 2560163953Srrs struct mbuf *m_at; 2561163953Srrs 2562163953Srrs m_at = m; 2563165647Srrs while (SCTP_BUF_NEXT(m_at) != NULL) { 2564165647Srrs m_at = SCTP_BUF_NEXT(m_at); 2565163953Srrs } 2566165647Srrs SCTP_BUF_NEXT(m_at) = m_sig; 2567163953Srrs } 2568163953Srrs 2569163953Srrs if (cookie_ok == 0) { 2570169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "handle_cookie_echo: cookie signature validation failed!\n"); 2571169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2572169420Srrs "offset = %u, cookie_offset = %u, sig_offset = %u\n", 2573169420Srrs (uint32_t) offset, cookie_offset, sig_offset); 2574163953Srrs return (NULL); 2575163953Srrs } 2576163953Srrs /* 2577163953Srrs * check the cookie timestamps to be sure it's not stale 2578163953Srrs */ 2579169378Srrs (void)SCTP_GETTIME_TIMEVAL(&now); 2580163953Srrs /* Expire time is in Ticks, so we convert to seconds */ 2581169655Srrs time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life); 2582163953Srrs time_expires.tv_usec = cookie->time_entered.tv_usec; 2583180387Srrs /* 2584180387Srrs * TODO sctp_constants.h needs alternative time macros when _KERNEL 2585180387Srrs * is undefined. 2586180387Srrs */ 2587163953Srrs if (timevalcmp(&now, &time_expires, >)) { 2588163953Srrs /* cookie is stale! */ 2589163953Srrs struct mbuf *op_err; 2590163953Srrs struct sctp_stale_cookie_msg *scm; 2591163953Srrs uint32_t tim; 2592163953Srrs 2593163953Srrs op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg), 2594165647Srrs 0, M_DONTWAIT, 1, MT_DATA); 2595163953Srrs if (op_err == NULL) { 2596163953Srrs /* FOOBAR */ 2597163953Srrs return (NULL); 2598163953Srrs } 2599163953Srrs /* Set the len */ 2600165647Srrs SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg); 2601163953Srrs scm = mtod(op_err, struct sctp_stale_cookie_msg *); 2602163953Srrs scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE); 2603163953Srrs scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) + 2604163953Srrs (sizeof(uint32_t)))); 2605163953Srrs /* seconds to usec */ 2606163953Srrs tim = (now.tv_sec - time_expires.tv_sec) * 1000000; 2607163953Srrs /* add in usec */ 2608163953Srrs if (tim == 0) 2609163953Srrs tim = now.tv_usec - cookie->time_entered.tv_usec; 2610163953Srrs scm->time_usec = htonl(tim); 2611236956Stuexen sctp_send_operr_to(m, sh, cookie->peers_vtag, op_err, 2612237049Stuexen use_mflowid, mflowid, 2613179157Srrs vrf_id, port); 2614163953Srrs return (NULL); 2615163953Srrs } 2616163953Srrs /* 2617163953Srrs * Now we must see with the lookup address if we have an existing 2618163953Srrs * asoc. This will only happen if we were in the COOKIE-WAIT state 2619163953Srrs * and a INIT collided with us and somewhere the peer sent the 2620163953Srrs * cookie on another address besides the single address our assoc 2621163953Srrs * had for him. In this case we will have one of the tie-tags set at 2622163953Srrs * least AND the address field in the cookie can be used to look it 2623163953Srrs * up. 2624163953Srrs */ 2625163953Srrs to = NULL; 2626221249Stuexen switch (cookie->addr_type) { 2627221249Stuexen#ifdef INET6 2628221249Stuexen case SCTP_IPV6_ADDRESS: 2629163953Srrs memset(&sin6, 0, sizeof(sin6)); 2630163953Srrs sin6.sin6_family = AF_INET6; 2631163953Srrs sin6.sin6_len = sizeof(sin6); 2632163953Srrs sin6.sin6_port = sh->src_port; 2633163953Srrs sin6.sin6_scope_id = cookie->scope_id; 2634163953Srrs memcpy(&sin6.sin6_addr.s6_addr, cookie->address, 2635163953Srrs sizeof(sin6.sin6_addr.s6_addr)); 2636163953Srrs to = (struct sockaddr *)&sin6; 2637221249Stuexen break; 2638221249Stuexen#endif 2639221249Stuexen#ifdef INET 2640221249Stuexen case SCTP_IPV4_ADDRESS: 2641163953Srrs memset(&sin, 0, sizeof(sin)); 2642163953Srrs sin.sin_family = AF_INET; 2643163953Srrs sin.sin_len = sizeof(sin); 2644163953Srrs sin.sin_port = sh->src_port; 2645163953Srrs sin.sin_addr.s_addr = cookie->address[0]; 2646163953Srrs to = (struct sockaddr *)&sin; 2647221249Stuexen break; 2648221249Stuexen#endif 2649221249Stuexen default: 2650169420Srrs /* This should not happen */ 2651169420Srrs return (NULL); 2652163953Srrs } 2653163953Srrs if ((*stcb == NULL) && to) { 2654163953Srrs /* Yep, lets check */ 2655163953Srrs *stcb = sctp_findassociation_ep_addr(inp_p, to, netp, localep_sa, NULL); 2656163953Srrs if (*stcb == NULL) { 2657163953Srrs /* 2658163953Srrs * We should have only got back the same inp. If we 2659163953Srrs * got back a different ep we have a problem. The 2660163953Srrs * original findep got back l_inp and now 2661163953Srrs */ 2662163953Srrs if (l_inp != *inp_p) { 2663169420Srrs SCTP_PRINTF("Bad problem find_ep got a diff inp then special_locate?\n"); 2664163953Srrs } 2665165220Srrs } else { 2666165220Srrs if (*locked_tcb == NULL) { 2667165220Srrs /* 2668165220Srrs * In this case we found the assoc only 2669165220Srrs * after we locked the create lock. This 2670165220Srrs * means we are in a colliding case and we 2671165220Srrs * must make sure that we unlock the tcb if 2672165220Srrs * its one of the cases where we throw away 2673165220Srrs * the incoming packets. 2674165220Srrs */ 2675165220Srrs *locked_tcb = *stcb; 2676165220Srrs 2677165220Srrs /* 2678165220Srrs * We must also increment the inp ref count 2679165220Srrs * since the ref_count flags was set when we 2680165220Srrs * did not find the TCB, now we found it 2681165220Srrs * which reduces the refcount.. we must 2682165220Srrs * raise it back out to balance it all :-) 2683165220Srrs */ 2684165220Srrs SCTP_INP_INCR_REF((*stcb)->sctp_ep); 2685165220Srrs if ((*stcb)->sctp_ep != l_inp) { 2686169420Srrs SCTP_PRINTF("Huh? ep:%p diff then l_inp:%p?\n", 2687165220Srrs (*stcb)->sctp_ep, l_inp); 2688165220Srrs } 2689165220Srrs } 2690163953Srrs } 2691163953Srrs } 2692188067Srrs if (to == NULL) { 2693169420Srrs return (NULL); 2694188067Srrs } 2695163953Srrs cookie_len -= SCTP_SIGNATURE_SIZE; 2696163953Srrs if (*stcb == NULL) { 2697163953Srrs /* this is the "normal" case... get a new TCB */ 2698163953Srrs *stcb = sctp_process_cookie_new(m, iphlen, offset, sh, cookie, 2699163953Srrs cookie_len, *inp_p, netp, to, ¬ification, 2700237049Stuexen auth_skipped, auth_offset, auth_len, 2701237049Stuexen use_mflowid, mflowid, 2702237049Stuexen vrf_id, port); 2703163953Srrs } else { 2704163953Srrs /* this is abnormal... cookie-echo on existing TCB */ 2705163953Srrs had_a_existing_tcb = 1; 2706163953Srrs *stcb = sctp_process_cookie_existing(m, iphlen, offset, sh, 2707185694Srrs cookie, cookie_len, *inp_p, *stcb, netp, to, 2708237049Stuexen ¬ification, auth_skipped, auth_offset, auth_len, 2709237049Stuexen use_mflowid, mflowid, 2710237049Stuexen vrf_id, port); 2711163953Srrs } 2712163953Srrs 2713163953Srrs if (*stcb == NULL) { 2714163953Srrs /* still no TCB... must be bad cookie-echo */ 2715163953Srrs return (NULL); 2716163953Srrs } 2717237049Stuexen if ((*netp != NULL) && (use_mflowid != 0)) { 2718237049Stuexen (*netp)->flowid = mflowid; 2719218400Stuexen#ifdef INVARIANTS 2720218392Srrs (*netp)->flowidset = 1; 2721218400Stuexen#endif 2722218335Stuexen } 2723163953Srrs /* 2724163953Srrs * Ok, we built an association so confirm the address we sent the 2725163953Srrs * INIT-ACK to. 2726163953Srrs */ 2727163953Srrs netl = sctp_findnet(*stcb, to); 2728163953Srrs /* 2729163953Srrs * This code should in theory NOT run but 2730163953Srrs */ 2731163953Srrs if (netl == NULL) { 2732163953Srrs /* TSNH! Huh, why do I need to add this address here? */ 2733228907Stuexen if (sctp_add_remote_addr(*stcb, to, NULL, SCTP_DONOT_SETSCOPE, SCTP_IN_COOKIE_PROC)) { 2734228907Stuexen return (NULL); 2735228907Stuexen } 2736163953Srrs netl = sctp_findnet(*stcb, to); 2737163953Srrs } 2738163953Srrs if (netl) { 2739163953Srrs if (netl->dest_state & SCTP_ADDR_UNCONFIRMED) { 2740163953Srrs netl->dest_state &= ~SCTP_ADDR_UNCONFIRMED; 2741169420Srrs (void)sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL, 2742163953Srrs netl); 2743216887Stuexen send_int_conf = 1; 2744163953Srrs } 2745163953Srrs } 2746224641Stuexen sctp_start_net_timers(*stcb); 2747163953Srrs if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) { 2748163953Srrs if (!had_a_existing_tcb || 2749163953Srrs (((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) { 2750163953Srrs /* 2751163953Srrs * If we have a NEW cookie or the connect never 2752163953Srrs * reached the connected state during collision we 2753163953Srrs * must do the TCP accept thing. 2754163953Srrs */ 2755163953Srrs struct socket *so, *oso; 2756163953Srrs struct sctp_inpcb *inp; 2757163953Srrs 2758163953Srrs if (notification == SCTP_NOTIFY_ASSOC_RESTART) { 2759163953Srrs /* 2760163953Srrs * For a restart we will keep the same 2761163953Srrs * socket, no need to do anything. I THINK!! 2762163953Srrs */ 2763228653Stuexen sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2764216887Stuexen if (send_int_conf) { 2765216887Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2766216887Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2767216887Stuexen } 2768163953Srrs return (m); 2769163953Srrs } 2770163953Srrs oso = (*inp_p)->sctp_socket; 2771171858Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2772163953Srrs SCTP_TCB_UNLOCK((*stcb)); 2773218757Sbz CURVNET_SET(oso->so_vnet); 2774166086Srrs so = sonewconn(oso, 0 2775163953Srrs ); 2776218757Sbz CURVNET_RESTORE(); 2777163953Srrs SCTP_TCB_LOCK((*stcb)); 2778171858Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2779171858Srrs 2780163953Srrs if (so == NULL) { 2781163953Srrs struct mbuf *op_err; 2782163953Srrs 2783237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2784172090Srrs struct socket *pcb_so; 2785172090Srrs 2786172090Srrs#endif 2787163953Srrs /* Too many sockets */ 2788169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n"); 2789163953Srrs op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); 2790163953Srrs sctp_abort_association(*inp_p, NULL, m, iphlen, 2791237049Stuexen sh, op_err, 2792237049Stuexen use_mflowid, mflowid, 2793237049Stuexen vrf_id, port); 2794237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2795172090Srrs pcb_so = SCTP_INP_SO(*inp_p); 2796172090Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2797172090Srrs SCTP_TCB_UNLOCK((*stcb)); 2798172090Srrs SCTP_SOCKET_LOCK(pcb_so, 1); 2799172090Srrs SCTP_TCB_LOCK((*stcb)); 2800172090Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2801172090Srrs#endif 2802171943Srrs (void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_20); 2803237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2804172090Srrs SCTP_SOCKET_UNLOCK(pcb_so, 1); 2805172090Srrs#endif 2806163953Srrs return (NULL); 2807163953Srrs } 2808163953Srrs inp = (struct sctp_inpcb *)so->so_pcb; 2809166086Srrs SCTP_INP_INCR_REF(inp); 2810166086Srrs /* 2811166086Srrs * We add the unbound flag here so that if we get an 2812166086Srrs * soabort() before we get the move_pcb done, we 2813166086Srrs * will properly cleanup. 2814166086Srrs */ 2815163953Srrs inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | 2816163953Srrs SCTP_PCB_FLAGS_CONNECTED | 2817163953Srrs SCTP_PCB_FLAGS_IN_TCPPOOL | 2818166086Srrs SCTP_PCB_FLAGS_UNBOUND | 2819163953Srrs (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) | 2820163953Srrs SCTP_PCB_FLAGS_DONT_WAKE); 2821163953Srrs inp->sctp_features = (*inp_p)->sctp_features; 2822172091Srrs inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features; 2823163953Srrs inp->sctp_socket = so; 2824163953Srrs inp->sctp_frag_point = (*inp_p)->sctp_frag_point; 2825211944Stuexen inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off; 2826218235Stuexen inp->sctp_ecn_enable = (*inp_p)->sctp_ecn_enable; 2827163953Srrs inp->partial_delivery_point = (*inp_p)->partial_delivery_point; 2828163953Srrs inp->sctp_context = (*inp_p)->sctp_context; 2829233660Srrs inp->local_strreset_support = (*inp_p)->local_strreset_support; 2830163953Srrs inp->inp_starting_point_for_iterator = NULL; 2831163953Srrs /* 2832163953Srrs * copy in the authentication parameters from the 2833163953Srrs * original endpoint 2834163953Srrs */ 2835163953Srrs if (inp->sctp_ep.local_hmacs) 2836163953Srrs sctp_free_hmaclist(inp->sctp_ep.local_hmacs); 2837163953Srrs inp->sctp_ep.local_hmacs = 2838163953Srrs sctp_copy_hmaclist((*inp_p)->sctp_ep.local_hmacs); 2839163953Srrs if (inp->sctp_ep.local_auth_chunks) 2840163953Srrs sctp_free_chunklist(inp->sctp_ep.local_auth_chunks); 2841163953Srrs inp->sctp_ep.local_auth_chunks = 2842163953Srrs sctp_copy_chunklist((*inp_p)->sctp_ep.local_auth_chunks); 2843163953Srrs 2844163953Srrs /* 2845163953Srrs * Now we must move it from one hash table to 2846163953Srrs * another and get the tcb in the right place. 2847163953Srrs */ 2848207924Srrs 2849207924Srrs /* 2850207924Srrs * This is where the one-2-one socket is put into 2851207924Srrs * the accept state waiting for the accept! 2852207924Srrs */ 2853207924Srrs if (*stcb) { 2854207924Srrs (*stcb)->asoc.state |= SCTP_STATE_IN_ACCEPT_QUEUE; 2855207924Srrs } 2856163953Srrs sctp_move_pcb_and_assoc(*inp_p, inp, *stcb); 2857170056Srrs 2858170056Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2859170056Srrs SCTP_TCB_UNLOCK((*stcb)); 2860170056Srrs 2861175845Srwatson sctp_pull_off_control_to_new_inp((*inp_p), inp, *stcb, 2862175845Srwatson 0); 2863170056Srrs SCTP_TCB_LOCK((*stcb)); 2864170056Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2865163953Srrs 2866170056Srrs 2867166086Srrs /* 2868166086Srrs * now we must check to see if we were aborted while 2869166086Srrs * the move was going on and the lock/unlock 2870166086Srrs * happened. 2871166086Srrs */ 2872166086Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 2873166086Srrs /* 2874166086Srrs * yep it was, we leave the assoc attached 2875166086Srrs * to the socket since the sctp_inpcb_free() 2876166086Srrs * call will send an abort for us. 2877166086Srrs */ 2878166086Srrs SCTP_INP_DECR_REF(inp); 2879166086Srrs return (NULL); 2880166086Srrs } 2881166086Srrs SCTP_INP_DECR_REF(inp); 2882163953Srrs /* Switch over to the new guy */ 2883163953Srrs *inp_p = inp; 2884172090Srrs sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2885216887Stuexen if (send_int_conf) { 2886216887Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2887216887Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2888216887Stuexen } 2889166086Srrs /* 2890166086Srrs * Pull it from the incomplete queue and wake the 2891166086Srrs * guy 2892166086Srrs */ 2893237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2894172090Srrs atomic_add_int(&(*stcb)->asoc.refcnt, 1); 2895172090Srrs SCTP_TCB_UNLOCK((*stcb)); 2896172090Srrs SCTP_SOCKET_LOCK(so, 1); 2897172090Srrs#endif 2898166086Srrs soisconnected(so); 2899237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2900172118Srrs SCTP_TCB_LOCK((*stcb)); 2901172118Srrs atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 2902172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2903172090Srrs#endif 2904163953Srrs return (m); 2905163953Srrs } 2906163953Srrs } 2907216887Stuexen if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) { 2908216887Stuexen if (notification) { 2909216887Stuexen sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2910216887Stuexen } 2911216887Stuexen if (send_int_conf) { 2912216887Stuexen sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 2913216887Stuexen (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 2914216887Stuexen } 2915163953Srrs } 2916163953Srrs return (m); 2917163953Srrs} 2918163953Srrs 2919163953Srrsstatic void 2920228653Stuexensctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED, 2921163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 2922163953Srrs{ 2923163953Srrs /* cp must not be used, others call this without a c-ack :-) */ 2924163953Srrs struct sctp_association *asoc; 2925163953Srrs 2926169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 2927169420Srrs "sctp_handle_cookie_ack: handling COOKIE-ACK\n"); 2928163953Srrs if (stcb == NULL) 2929163953Srrs return; 2930163953Srrs 2931163953Srrs asoc = &stcb->asoc; 2932163953Srrs 2933163953Srrs sctp_stop_all_cookie_timers(stcb); 2934163953Srrs /* process according to association state */ 2935163953Srrs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 2936163953Srrs /* state change only needed when I am in right state */ 2937169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 2938171943Srrs SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 2939224641Stuexen sctp_start_net_timers(stcb); 2940163953Srrs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 2941163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 2942163953Srrs stcb->sctp_ep, stcb, asoc->primary_destination); 2943163953Srrs 2944163953Srrs } 2945163953Srrs /* update RTO */ 2946163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 2947163953Srrs SCTP_STAT_INCR_GAUGE32(sctps_currestab); 2948163953Srrs if (asoc->overall_error_count == 0) { 2949163953Srrs net->RTO = sctp_calculate_rto(stcb, asoc, net, 2950218186Srrs &asoc->time_entered, sctp_align_safe_nocopy, 2951219397Srrs SCTP_RTT_FROM_NON_DATA); 2952163953Srrs } 2953169378Srrs (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 2954172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 2955163953Srrs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 2956163953Srrs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 2957237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2958172090Srrs struct socket *so; 2959172090Srrs 2960172090Srrs#endif 2961163953Srrs stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 2962237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2963172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 2964172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 2965172090Srrs SCTP_TCB_UNLOCK(stcb); 2966172090Srrs SCTP_SOCKET_LOCK(so, 1); 2967172090Srrs SCTP_TCB_LOCK(stcb); 2968172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 2969218641Srrs#endif 2970218641Srrs if ((stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) == 0) { 2971218641Srrs soisconnected(stcb->sctp_socket); 2972172090Srrs } 2973237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 2974172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 2975172090Srrs#endif 2976163953Srrs } 2977163953Srrs /* 2978163953Srrs * since we did not send a HB make sure we don't double 2979163953Srrs * things 2980163953Srrs */ 2981163953Srrs net->hb_responded = 1; 2982163953Srrs 2983218641Srrs if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 2984218641Srrs /* 2985218641Srrs * We don't need to do the asconf thing, nor hb or 2986218641Srrs * autoclose if the socket is closed. 2987218641Srrs */ 2988218641Srrs goto closed_socket; 2989218641Srrs } 2990218641Srrs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, 2991218641Srrs stcb, net); 2992218641Srrs 2993218641Srrs 2994163953Srrs if (stcb->asoc.sctp_autoclose_ticks && 2995163953Srrs sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTOCLOSE)) { 2996163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 2997163953Srrs stcb->sctp_ep, stcb, NULL); 2998163953Srrs } 2999163953Srrs /* 3000171572Srrs * send ASCONF if parameters are pending and ASCONFs are 3001171572Srrs * allowed (eg. addresses changed when init/cookie echo were 3002171572Srrs * in flight) 3003163953Srrs */ 3004163953Srrs if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) && 3005163953Srrs (stcb->asoc.peer_supports_asconf) && 3006163953Srrs (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) { 3007171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF 3008163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 3009163953Srrs stcb->sctp_ep, stcb, 3010163953Srrs stcb->asoc.primary_destination); 3011171572Srrs#else 3012172190Srrs sctp_send_asconf(stcb, stcb->asoc.primary_destination, 3013172190Srrs SCTP_ADDR_NOT_LOCKED); 3014171572Srrs#endif 3015163953Srrs } 3016163953Srrs } 3017218641Srrsclosed_socket: 3018163953Srrs /* Toss the cookie if I can */ 3019163953Srrs sctp_toss_old_cookies(stcb, asoc); 3020163953Srrs if (!TAILQ_EMPTY(&asoc->sent_queue)) { 3021163953Srrs /* Restart the timer if we have pending data */ 3022163953Srrs struct sctp_tmit_chunk *chk; 3023163953Srrs 3024163953Srrs chk = TAILQ_FIRST(&asoc->sent_queue); 3025216822Stuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 3026163953Srrs } 3027163953Srrs} 3028163953Srrs 3029163953Srrsstatic void 3030163953Srrssctp_handle_ecn_echo(struct sctp_ecne_chunk *cp, 3031163953Srrs struct sctp_tcb *stcb) 3032163953Srrs{ 3033163953Srrs struct sctp_nets *net; 3034163953Srrs struct sctp_tmit_chunk *lchk; 3035218072Srrs struct sctp_ecne_chunk bkup; 3036228907Stuexen uint8_t override_bit; 3037218072Srrs uint32_t tsn, window_data_tsn; 3038218072Srrs int len; 3039218232Srrs unsigned int pkt_cnt; 3040163953Srrs 3041218072Srrs len = ntohs(cp->ch.chunk_length); 3042218072Srrs if ((len != sizeof(struct sctp_ecne_chunk)) && 3043218072Srrs (len != sizeof(struct old_sctp_ecne_chunk))) { 3044163953Srrs return; 3045163953Srrs } 3046218072Srrs if (len == sizeof(struct old_sctp_ecne_chunk)) { 3047218072Srrs /* Its the old format */ 3048218072Srrs memcpy(&bkup, cp, sizeof(struct old_sctp_ecne_chunk)); 3049218072Srrs bkup.num_pkts_since_cwr = htonl(1); 3050218072Srrs cp = &bkup; 3051218072Srrs } 3052163953Srrs SCTP_STAT_INCR(sctps_recvecne); 3053163953Srrs tsn = ntohl(cp->tsn); 3054218072Srrs pkt_cnt = ntohl(cp->num_pkts_since_cwr); 3055218072Srrs lchk = TAILQ_LAST(&stcb->asoc.send_queue, sctpchunk_listhead); 3056163953Srrs if (lchk == NULL) { 3057218129Srrs window_data_tsn = stcb->asoc.sending_seq - 1; 3058163953Srrs } else { 3059218129Srrs window_data_tsn = lchk->rec.data.TSN_seq; 3060163953Srrs } 3061163953Srrs 3062218072Srrs /* Find where it was sent to if possible. */ 3063163953Srrs net = NULL; 3064216822Stuexen TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) { 3065163953Srrs if (lchk->rec.data.TSN_seq == tsn) { 3066163953Srrs net = lchk->whoTo; 3067218186Srrs net->ecn_prev_cwnd = lchk->rec.data.cwnd_at_send; 3068163953Srrs break; 3069163953Srrs } 3070216825Stuexen if (SCTP_TSN_GT(lchk->rec.data.TSN_seq, tsn)) { 3071163953Srrs break; 3072216825Stuexen } 3073163953Srrs } 3074218072Srrs if (net == NULL) { 3075163953Srrs /* 3076218072Srrs * What to do. A previous send of a CWR was possibly lost. 3077218072Srrs * See how old it is, we may have it marked on the actual 3078218072Srrs * net. 3079218072Srrs */ 3080218072Srrs TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 3081218072Srrs if (tsn == net->last_cwr_tsn) { 3082218072Srrs /* Found him, send it off */ 3083228907Stuexen break; 3084218072Srrs } 3085218072Srrs } 3086228907Stuexen if (net == NULL) { 3087228907Stuexen /* 3088228907Stuexen * If we reach here, we need to send a special CWR 3089228907Stuexen * that says hey, we did this a long time ago and 3090228907Stuexen * you lost the response. 3091228907Stuexen */ 3092228907Stuexen net = TAILQ_FIRST(&stcb->asoc.nets); 3093228907Stuexen if (net == NULL) { 3094228907Stuexen /* TSNH */ 3095228907Stuexen return; 3096228907Stuexen } 3097228907Stuexen override_bit = SCTP_CWR_REDUCE_OVERRIDE; 3098228907Stuexen } else { 3099228907Stuexen override_bit = 0; 3100228907Stuexen } 3101228907Stuexen } else { 3102228907Stuexen override_bit = 0; 3103218072Srrs } 3104218129Srrs if (SCTP_TSN_GT(tsn, net->cwr_window_tsn) && 3105218129Srrs ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 3106218072Srrs /* 3107171440Srrs * JRS - Use the congestion control given in the pluggable 3108171440Srrs * CC module 3109171440Srrs */ 3110218129Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 0, pkt_cnt); 3111171440Srrs /* 3112218072Srrs * We reduce once every RTT. So we will only lower cwnd at 3113218072Srrs * the next sending seq i.e. the window_data_tsn 3114163953Srrs */ 3115218072Srrs net->cwr_window_tsn = window_data_tsn; 3116218072Srrs net->ecn_ce_pkt_cnt += pkt_cnt; 3117218072Srrs net->lost_cnt = pkt_cnt; 3118218072Srrs net->last_cwr_tsn = tsn; 3119218072Srrs } else { 3120218072Srrs override_bit |= SCTP_CWR_IN_SAME_WINDOW; 3121218129Srrs if (SCTP_TSN_GT(tsn, net->last_cwr_tsn) && 3122218129Srrs ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 3123218072Srrs /* 3124218129Srrs * Another loss in the same window update how many 3125218129Srrs * marks/packets lost we have had. 3126218072Srrs */ 3127218129Srrs int cnt = 1; 3128218072Srrs 3129218072Srrs if (pkt_cnt > net->lost_cnt) { 3130218072Srrs /* Should be the case */ 3131218129Srrs cnt = (pkt_cnt - net->lost_cnt); 3132218129Srrs net->ecn_ce_pkt_cnt += cnt; 3133218072Srrs } 3134218129Srrs net->lost_cnt = pkt_cnt; 3135218072Srrs net->last_cwr_tsn = tsn; 3136218129Srrs /* 3137218129Srrs * Most CC functions will ignore this call, since we 3138218129Srrs * are in-window yet of the initial CE the peer saw. 3139218129Srrs */ 3140218129Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 1, cnt); 3141218072Srrs } 3142163953Srrs } 3143163953Srrs /* 3144163953Srrs * We always send a CWR this way if our previous one was lost our 3145163953Srrs * peer will get an update, or if it is not time again to reduce we 3146218072Srrs * still get the cwr to the peer. Note we set the override when we 3147218072Srrs * could not find the TSN on the chunk or the destination network. 3148163953Srrs */ 3149218072Srrs sctp_send_cwr(stcb, net, net->last_cwr_tsn, override_bit); 3150163953Srrs} 3151163953Srrs 3152163953Srrsstatic void 3153218072Srrssctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sctp_nets *net) 3154163953Srrs{ 3155163953Srrs /* 3156163953Srrs * Here we get a CWR from the peer. We must look in the outqueue and 3157163953Srrs * make sure that we have a covered ECNE in teh control chunk part. 3158163953Srrs * If so remove it. 3159163953Srrs */ 3160163953Srrs struct sctp_tmit_chunk *chk; 3161163953Srrs struct sctp_ecne_chunk *ecne; 3162218072Srrs int override; 3163218072Srrs uint32_t cwr_tsn; 3164163953Srrs 3165218072Srrs cwr_tsn = ntohl(cp->tsn); 3166218072Srrs 3167218072Srrs override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE; 3168163953Srrs TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 3169163953Srrs if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) { 3170163953Srrs continue; 3171163953Srrs } 3172218072Srrs if ((override == 0) && (chk->whoTo != net)) { 3173218072Srrs /* Must be from the right src unless override is set */ 3174218072Srrs continue; 3175218072Srrs } 3176163953Srrs ecne = mtod(chk->data, struct sctp_ecne_chunk *); 3177218072Srrs if (SCTP_TSN_GE(cwr_tsn, ntohl(ecne->tsn))) { 3178163953Srrs /* this covers this ECNE, we can remove it */ 3179163953Srrs stcb->asoc.ecn_echo_cnt_onq--; 3180163953Srrs TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk, 3181163953Srrs sctp_next); 3182163953Srrs if (chk->data) { 3183163953Srrs sctp_m_freem(chk->data); 3184163953Srrs chk->data = NULL; 3185163953Srrs } 3186163953Srrs stcb->asoc.ctrl_queue_cnt--; 3187221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 3188218072Srrs if (override == 0) { 3189218072Srrs break; 3190218072Srrs } 3191163953Srrs } 3192163953Srrs } 3193163953Srrs} 3194163953Srrs 3195163953Srrsstatic void 3196228653Stuexensctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSED, 3197163953Srrs struct sctp_tcb *stcb, struct sctp_nets *net) 3198163953Srrs{ 3199163953Srrs struct sctp_association *asoc; 3200163953Srrs 3201237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3202172090Srrs struct socket *so; 3203172090Srrs 3204172090Srrs#endif 3205172090Srrs 3206169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3207169420Srrs "sctp_handle_shutdown_complete: handling SHUTDOWN-COMPLETE\n"); 3208163953Srrs if (stcb == NULL) 3209163953Srrs return; 3210163953Srrs 3211163953Srrs asoc = &stcb->asoc; 3212163953Srrs /* process according to association state */ 3213163953Srrs if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) { 3214163953Srrs /* unexpected SHUTDOWN-COMPLETE... so ignore... */ 3215171990Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3216171990Srrs "sctp_handle_shutdown_complete: not in SCTP_STATE_SHUTDOWN_ACK_SENT --- ignore\n"); 3217163953Srrs SCTP_TCB_UNLOCK(stcb); 3218163953Srrs return; 3219163953Srrs } 3220163953Srrs /* notify upper layer protocol */ 3221163953Srrs if (stcb->sctp_socket) { 3222172090Srrs sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 3223163953Srrs /* are the queues empty? they should be */ 3224163953Srrs if (!TAILQ_EMPTY(&asoc->send_queue) || 3225163953Srrs !TAILQ_EMPTY(&asoc->sent_queue) || 3226217760Stuexen !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 3227235416Stuexen sctp_report_all_outbound(stcb, 0, 0, SCTP_SO_NOT_LOCKED); 3228163953Srrs } 3229163953Srrs } 3230163953Srrs /* stop the timer */ 3231178202Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_22); 3232163953Srrs SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 3233163953Srrs /* free the TCB */ 3234171990Srrs SCTPDBG(SCTP_DEBUG_INPUT2, 3235171990Srrs "sctp_handle_shutdown_complete: calls free-asoc\n"); 3236237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3237172090Srrs so = SCTP_INP_SO(stcb->sctp_ep); 3238172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 3239172090Srrs SCTP_TCB_UNLOCK(stcb); 3240172090Srrs SCTP_SOCKET_LOCK(so, 1); 3241172090Srrs SCTP_TCB_LOCK(stcb); 3242172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 3243172090Srrs#endif 3244171943Srrs (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_23); 3245237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 3246172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 3247172090Srrs#endif 3248163953Srrs return; 3249163953Srrs} 3250163953Srrs 3251163953Srrsstatic int 3252163953Srrsprocess_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, 3253163953Srrs struct sctp_nets *net, uint8_t flg) 3254163953Srrs{ 3255163953Srrs switch (desc->chunk_type) { 3256211969Stuexen case SCTP_DATA: 3257163953Srrs /* find the tsn to resend (possibly */ 3258163953Srrs { 3259163953Srrs uint32_t tsn; 3260163953Srrs struct sctp_tmit_chunk *tp1; 3261163953Srrs 3262163953Srrs tsn = ntohl(desc->tsn_ifany); 3263216822Stuexen TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3264163953Srrs if (tp1->rec.data.TSN_seq == tsn) { 3265163953Srrs /* found it */ 3266163953Srrs break; 3267163953Srrs } 3268216825Stuexen if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, tsn)) { 3269163953Srrs /* not found */ 3270163953Srrs tp1 = NULL; 3271163953Srrs break; 3272163953Srrs } 3273163953Srrs } 3274163953Srrs if (tp1 == NULL) { 3275163953Srrs /* 3276163953Srrs * Do it the other way , aka without paying 3277163953Srrs * attention to queue seq order. 3278163953Srrs */ 3279163953Srrs SCTP_STAT_INCR(sctps_pdrpdnfnd); 3280216822Stuexen TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3281163953Srrs if (tp1->rec.data.TSN_seq == tsn) { 3282163953Srrs /* found it */ 3283163953Srrs break; 3284163953Srrs } 3285163953Srrs } 3286163953Srrs } 3287163953Srrs if (tp1 == NULL) { 3288163953Srrs SCTP_STAT_INCR(sctps_pdrptsnnf); 3289163953Srrs } 3290163953Srrs if ((tp1) && (tp1->sent < SCTP_DATAGRAM_ACKED)) { 3291163953Srrs uint8_t *ddp; 3292163953Srrs 3293214877Stuexen if (((flg & SCTP_BADCRC) == 0) && 3294214877Stuexen ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 3295214877Stuexen return (0); 3296214877Stuexen } 3297163953Srrs if ((stcb->asoc.peers_rwnd == 0) && 3298163953Srrs ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 3299163953Srrs SCTP_STAT_INCR(sctps_pdrpdiwnp); 3300163953Srrs return (0); 3301163953Srrs } 3302163953Srrs if (stcb->asoc.peers_rwnd == 0 && 3303163953Srrs (flg & SCTP_FROM_MIDDLE_BOX)) { 3304163953Srrs SCTP_STAT_INCR(sctps_pdrpdizrw); 3305163953Srrs return (0); 3306163953Srrs } 3307163953Srrs ddp = (uint8_t *) (mtod(tp1->data, caddr_t)+ 3308163953Srrs sizeof(struct sctp_data_chunk)); 3309163953Srrs { 3310163953Srrs unsigned int iii; 3311163953Srrs 3312163953Srrs for (iii = 0; iii < sizeof(desc->data_bytes); 3313163953Srrs iii++) { 3314163953Srrs if (ddp[iii] != desc->data_bytes[iii]) { 3315163953Srrs SCTP_STAT_INCR(sctps_pdrpbadd); 3316163953Srrs return (-1); 3317163953Srrs } 3318163953Srrs } 3319163953Srrs } 3320163953Srrs 3321163953Srrs if (tp1->do_rtt) { 3322163953Srrs /* 3323163953Srrs * this guy had a RTO calculation 3324163953Srrs * pending on it, cancel it 3325163953Srrs */ 3326219397Srrs if (tp1->whoTo->rto_needed == 0) { 3327219397Srrs tp1->whoTo->rto_needed = 1; 3328219397Srrs } 3329163953Srrs tp1->do_rtt = 0; 3330163953Srrs } 3331163953Srrs SCTP_STAT_INCR(sctps_pdrpmark); 3332163953Srrs if (tp1->sent != SCTP_DATAGRAM_RESEND) 3333163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3334163953Srrs /* 3335163953Srrs * mark it as if we were doing a FR, since 3336163953Srrs * we will be getting gap ack reports behind 3337163953Srrs * the info from the router. 3338163953Srrs */ 3339163953Srrs tp1->rec.data.doing_fast_retransmit = 1; 3340163953Srrs /* 3341163953Srrs * mark the tsn with what sequences can 3342163953Srrs * cause a new FR. 3343163953Srrs */ 3344163953Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue)) { 3345163953Srrs tp1->rec.data.fast_retran_tsn = stcb->asoc.sending_seq; 3346163953Srrs } else { 3347163953Srrs tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq; 3348163953Srrs } 3349163953Srrs 3350163953Srrs /* restart the timer */ 3351163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 3352171440Srrs stcb, tp1->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_24); 3353163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 3354163953Srrs stcb, tp1->whoTo); 3355163953Srrs 3356163953Srrs /* fix counts and things */ 3357179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 3358170744Srrs sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP, 3359170744Srrs tp1->whoTo->flight_size, 3360170744Srrs tp1->book_size, 3361170744Srrs (uintptr_t) stcb, 3362170744Srrs tp1->rec.data.TSN_seq); 3363170744Srrs } 3364190689Srrs if (tp1->sent < SCTP_DATAGRAM_RESEND) { 3365190689Srrs sctp_flight_size_decrease(tp1); 3366190689Srrs sctp_total_flight_decrease(stcb, tp1); 3367190689Srrs } 3368216502Stuexen tp1->sent = SCTP_DATAGRAM_RESEND; 3369163953Srrs } { 3370163953Srrs /* audit code */ 3371163953Srrs unsigned int audit; 3372163953Srrs 3373163953Srrs audit = 0; 3374163953Srrs TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 3375163953Srrs if (tp1->sent == SCTP_DATAGRAM_RESEND) 3376163953Srrs audit++; 3377163953Srrs } 3378163953Srrs TAILQ_FOREACH(tp1, &stcb->asoc.control_send_queue, 3379163953Srrs sctp_next) { 3380163953Srrs if (tp1->sent == SCTP_DATAGRAM_RESEND) 3381163953Srrs audit++; 3382163953Srrs } 3383163953Srrs if (audit != stcb->asoc.sent_queue_retran_cnt) { 3384169420Srrs SCTP_PRINTF("**Local Audit finds cnt:%d asoc cnt:%d\n", 3385163953Srrs audit, stcb->asoc.sent_queue_retran_cnt); 3386163953Srrs#ifndef SCTP_AUDITING_ENABLED 3387163953Srrs stcb->asoc.sent_queue_retran_cnt = audit; 3388163953Srrs#endif 3389163953Srrs } 3390163953Srrs } 3391163953Srrs } 3392163953Srrs break; 3393163953Srrs case SCTP_ASCONF: 3394163953Srrs { 3395163953Srrs struct sctp_tmit_chunk *asconf; 3396163953Srrs 3397163953Srrs TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue, 3398163953Srrs sctp_next) { 3399163953Srrs if (asconf->rec.chunk_id.id == SCTP_ASCONF) { 3400163953Srrs break; 3401163953Srrs } 3402163953Srrs } 3403163953Srrs if (asconf) { 3404163953Srrs if (asconf->sent != SCTP_DATAGRAM_RESEND) 3405163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3406163953Srrs asconf->sent = SCTP_DATAGRAM_RESEND; 3407163953Srrs asconf->snd_count--; 3408163953Srrs } 3409163953Srrs } 3410163953Srrs break; 3411163953Srrs case SCTP_INITIATION: 3412163953Srrs /* resend the INIT */ 3413163953Srrs stcb->asoc.dropped_special_cnt++; 3414163953Srrs if (stcb->asoc.dropped_special_cnt < SCTP_RETRY_DROPPED_THRESH) { 3415163953Srrs /* 3416163953Srrs * If we can get it in, in a few attempts we do 3417163953Srrs * this, otherwise we let the timer fire. 3418163953Srrs */ 3419163953Srrs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, 3420171440Srrs stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_25); 3421172090Srrs sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 3422163953Srrs } 3423163953Srrs break; 3424163953Srrs case SCTP_SELECTIVE_ACK: 3425206137Stuexen case SCTP_NR_SELECTIVE_ACK: 3426163953Srrs /* resend the sack */ 3427221627Stuexen sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 3428163953Srrs break; 3429163953Srrs case SCTP_HEARTBEAT_REQUEST: 3430163953Srrs /* resend a demand HB */ 3431171440Srrs if ((stcb->asoc.overall_error_count + 3) < stcb->asoc.max_send_times) { 3432171440Srrs /* 3433171440Srrs * Only retransmit if we KNOW we wont destroy the 3434171440Srrs * tcb 3435171440Srrs */ 3436224641Stuexen sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 3437171440Srrs } 3438163953Srrs break; 3439163953Srrs case SCTP_SHUTDOWN: 3440163953Srrs sctp_send_shutdown(stcb, net); 3441163953Srrs break; 3442163953Srrs case SCTP_SHUTDOWN_ACK: 3443163953Srrs sctp_send_shutdown_ack(stcb, net); 3444163953Srrs break; 3445163953Srrs case SCTP_COOKIE_ECHO: 3446163953Srrs { 3447163953Srrs struct sctp_tmit_chunk *cookie; 3448163953Srrs 3449163953Srrs cookie = NULL; 3450163953Srrs TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, 3451163953Srrs sctp_next) { 3452163953Srrs if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) { 3453163953Srrs break; 3454163953Srrs } 3455163953Srrs } 3456163953Srrs if (cookie) { 3457163953Srrs if (cookie->sent != SCTP_DATAGRAM_RESEND) 3458163953Srrs sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 3459163953Srrs cookie->sent = SCTP_DATAGRAM_RESEND; 3460163953Srrs sctp_stop_all_cookie_timers(stcb); 3461163953Srrs } 3462163953Srrs } 3463163953Srrs break; 3464163953Srrs case SCTP_COOKIE_ACK: 3465163953Srrs sctp_send_cookie_ack(stcb); 3466163953Srrs break; 3467163953Srrs case SCTP_ASCONF_ACK: 3468163953Srrs /* resend last asconf ack */ 3469171990Srrs sctp_send_asconf_ack(stcb); 3470163953Srrs break; 3471163953Srrs case SCTP_FORWARD_CUM_TSN: 3472163953Srrs send_forward_tsn(stcb, &stcb->asoc); 3473163953Srrs break; 3474163953Srrs /* can't do anything with these */ 3475163953Srrs case SCTP_PACKET_DROPPED: 3476163953Srrs case SCTP_INITIATION_ACK: /* this should not happen */ 3477163953Srrs case SCTP_HEARTBEAT_ACK: 3478163953Srrs case SCTP_ABORT_ASSOCIATION: 3479163953Srrs case SCTP_OPERATION_ERROR: 3480163953Srrs case SCTP_SHUTDOWN_COMPLETE: 3481163953Srrs case SCTP_ECN_ECHO: 3482163953Srrs case SCTP_ECN_CWR: 3483163953Srrs default: 3484163953Srrs break; 3485163953Srrs } 3486163953Srrs return (0); 3487163953Srrs} 3488163953Srrs 3489163953Srrsvoid 3490163953Srrssctp_reset_in_stream(struct sctp_tcb *stcb, int number_entries, uint16_t * list) 3491163953Srrs{ 3492163953Srrs int i; 3493163953Srrs uint16_t temp; 3494163953Srrs 3495163953Srrs /* 3496163953Srrs * We set things to 0xffff since this is the last delivered sequence 3497163953Srrs * and we will be sending in 0 after the reset. 3498163953Srrs */ 3499163953Srrs 3500163953Srrs if (number_entries) { 3501163953Srrs for (i = 0; i < number_entries; i++) { 3502163953Srrs temp = ntohs(list[i]); 3503163953Srrs if (temp >= stcb->asoc.streamincnt) { 3504163953Srrs continue; 3505163953Srrs } 3506163953Srrs stcb->asoc.strmin[temp].last_sequence_delivered = 0xffff; 3507163953Srrs } 3508163953Srrs } else { 3509163953Srrs list = NULL; 3510163953Srrs for (i = 0; i < stcb->asoc.streamincnt; i++) { 3511163953Srrs stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 3512163953Srrs } 3513163953Srrs } 3514172090Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 3515163953Srrs} 3516163953Srrs 3517163953Srrsstatic void 3518163953Srrssctp_reset_out_streams(struct sctp_tcb *stcb, int number_entries, uint16_t * list) 3519163953Srrs{ 3520163953Srrs int i; 3521163953Srrs 3522163953Srrs if (number_entries == 0) { 3523163953Srrs for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 3524163953Srrs stcb->asoc.strmout[i].next_sequence_sent = 0; 3525163953Srrs } 3526163953Srrs } else if (number_entries) { 3527163953Srrs for (i = 0; i < number_entries; i++) { 3528163953Srrs uint16_t temp; 3529163953Srrs 3530163953Srrs temp = ntohs(list[i]); 3531163953Srrs if (temp >= stcb->asoc.streamoutcnt) { 3532163953Srrs /* no such stream */ 3533163953Srrs continue; 3534163953Srrs } 3535163953Srrs stcb->asoc.strmout[temp].next_sequence_sent = 0; 3536163953Srrs } 3537163953Srrs } 3538172090Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 3539163953Srrs} 3540163953Srrs 3541163953Srrs 3542163953Srrsstruct sctp_stream_reset_out_request * 3543163953Srrssctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk) 3544163953Srrs{ 3545163953Srrs struct sctp_association *asoc; 3546163953Srrs struct sctp_stream_reset_out_req *req; 3547163953Srrs struct sctp_stream_reset_out_request *r; 3548163953Srrs struct sctp_tmit_chunk *chk; 3549163953Srrs int len, clen; 3550163953Srrs 3551163953Srrs asoc = &stcb->asoc; 3552163953Srrs if (TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 3553169208Srrs asoc->stream_reset_outstanding = 0; 3554163953Srrs return (NULL); 3555163953Srrs } 3556163953Srrs if (stcb->asoc.str_reset == NULL) { 3557169208Srrs asoc->stream_reset_outstanding = 0; 3558163953Srrs return (NULL); 3559163953Srrs } 3560163953Srrs chk = stcb->asoc.str_reset; 3561163953Srrs if (chk->data == NULL) { 3562163953Srrs return (NULL); 3563163953Srrs } 3564163953Srrs if (bchk) { 3565163953Srrs /* he wants a copy of the chk pointer */ 3566163953Srrs *bchk = chk; 3567163953Srrs } 3568163953Srrs clen = chk->send_size; 3569163953Srrs req = mtod(chk->data, struct sctp_stream_reset_out_req *); 3570163953Srrs r = &req->sr_req; 3571163953Srrs if (ntohl(r->request_seq) == seq) { 3572163953Srrs /* found it */ 3573163953Srrs return (r); 3574163953Srrs } 3575163953Srrs len = SCTP_SIZE32(ntohs(r->ph.param_length)); 3576163953Srrs if (clen > (len + (int)sizeof(struct sctp_chunkhdr))) { 3577163953Srrs /* move to the next one, there can only be a max of two */ 3578163953Srrs r = (struct sctp_stream_reset_out_request *)((caddr_t)r + len); 3579163953Srrs if (ntohl(r->request_seq) == seq) { 3580163953Srrs return (r); 3581163953Srrs } 3582163953Srrs } 3583163953Srrs /* that seq is not here */ 3584163953Srrs return (NULL); 3585163953Srrs} 3586163953Srrs 3587163953Srrsstatic void 3588163953Srrssctp_clean_up_stream_reset(struct sctp_tcb *stcb) 3589163953Srrs{ 3590163953Srrs struct sctp_association *asoc; 3591163953Srrs struct sctp_tmit_chunk *chk = stcb->asoc.str_reset; 3592163953Srrs 3593163953Srrs if (stcb->asoc.str_reset == NULL) { 3594163953Srrs return; 3595163953Srrs } 3596166675Srrs asoc = &stcb->asoc; 3597166675Srrs 3598171440Srrs sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_26); 3599163953Srrs TAILQ_REMOVE(&asoc->control_send_queue, 3600163953Srrs chk, 3601163953Srrs sctp_next); 3602163953Srrs if (chk->data) { 3603163953Srrs sctp_m_freem(chk->data); 3604163953Srrs chk->data = NULL; 3605163953Srrs } 3606163953Srrs asoc->ctrl_queue_cnt--; 3607221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 3608172156Srrs /* sa_ignore NO_NULL_CHK */ 3609163953Srrs stcb->asoc.str_reset = NULL; 3610163953Srrs} 3611163953Srrs 3612163953Srrs 3613163953Srrsstatic int 3614163953Srrssctp_handle_stream_reset_response(struct sctp_tcb *stcb, 3615163953Srrs uint32_t seq, uint32_t action, 3616164139Srrs struct sctp_stream_reset_response *respin) 3617163953Srrs{ 3618163953Srrs uint16_t type; 3619163953Srrs int lparm_len; 3620163953Srrs struct sctp_association *asoc = &stcb->asoc; 3621163953Srrs struct sctp_tmit_chunk *chk; 3622163953Srrs struct sctp_stream_reset_out_request *srparam; 3623163953Srrs int number_entries; 3624163953Srrs 3625163953Srrs if (asoc->stream_reset_outstanding == 0) { 3626163953Srrs /* duplicate */ 3627163953Srrs return (0); 3628163953Srrs } 3629163953Srrs if (seq == stcb->asoc.str_reset_seq_out) { 3630163953Srrs srparam = sctp_find_stream_reset(stcb, seq, &chk); 3631163953Srrs if (srparam) { 3632163953Srrs stcb->asoc.str_reset_seq_out++; 3633163953Srrs type = ntohs(srparam->ph.param_type); 3634163953Srrs lparm_len = ntohs(srparam->ph.param_length); 3635163953Srrs if (type == SCTP_STR_RESET_OUT_REQUEST) { 3636164139Srrs number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t); 3637163953Srrs asoc->stream_reset_out_is_outstanding = 0; 3638163953Srrs if (asoc->stream_reset_outstanding) 3639163953Srrs asoc->stream_reset_outstanding--; 3640235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3641163953Srrs /* do it */ 3642163953Srrs sctp_reset_out_streams(stcb, number_entries, srparam->list_of_streams); 3643235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3644235066Stuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 3645163953Srrs } else { 3646172090Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 3647163953Srrs } 3648163953Srrs } else if (type == SCTP_STR_RESET_IN_REQUEST) { 3649163953Srrs /* Answered my request */ 3650164139Srrs number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t); 3651163953Srrs if (asoc->stream_reset_outstanding) 3652163953Srrs asoc->stream_reset_outstanding--; 3653235066Stuexen if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3654235066Stuexen sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_IN, stcb, 3655235066Stuexen number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 3656235066Stuexen } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 3657233660Srrs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb, 3658233660Srrs number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 3659163953Srrs } 3660233660Srrs } else if (type == SCTP_STR_RESET_ADD_OUT_STREAMS) { 3661188854Srrs /* Ok we now may have more streams */ 3662233660Srrs int num_stream; 3663233660Srrs 3664233660Srrs num_stream = stcb->asoc.strm_pending_add_size; 3665233660Srrs if (num_stream > (stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt)) { 3666233660Srrs /* TSNH */ 3667233660Srrs num_stream = stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt; 3668233660Srrs } 3669233660Srrs stcb->asoc.strm_pending_add_size = 0; 3670189121Srrs if (asoc->stream_reset_outstanding) 3671189121Srrs asoc->stream_reset_outstanding--; 3672235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3673188854Srrs /* Put the new streams into effect */ 3674233660Srrs stcb->asoc.streamoutcnt += num_stream; 3675233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 3676235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3677235066Stuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3678235066Stuexen SCTP_STREAM_CHANGE_DENIED); 3679188854Srrs } else { 3680233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3681235066Stuexen SCTP_STREAM_CHANGE_FAILED); 3682188854Srrs } 3683233660Srrs } else if (type == SCTP_STR_RESET_ADD_IN_STREAMS) { 3684233660Srrs if (asoc->stream_reset_outstanding) 3685233660Srrs asoc->stream_reset_outstanding--; 3686235066Stuexen if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3687233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3688235066Stuexen SCTP_STREAM_CHANGE_DENIED); 3689235066Stuexen } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 3690235066Stuexen sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 3691235066Stuexen SCTP_STREAM_CHANGE_FAILED); 3692233660Srrs } 3693163953Srrs } else if (type == SCTP_STR_RESET_TSN_REQUEST) { 3694163953Srrs /** 3695163953Srrs * a) Adopt the new in tsn. 3696163953Srrs * b) reset the map 3697163953Srrs * c) Adopt the new out-tsn 3698163953Srrs */ 3699163953Srrs struct sctp_stream_reset_response_tsn *resp; 3700163953Srrs struct sctp_forward_tsn_chunk fwdtsn; 3701163953Srrs int abort_flag = 0; 3702163953Srrs 3703163953Srrs if (respin == NULL) { 3704163953Srrs /* huh ? */ 3705163953Srrs return (0); 3706163953Srrs } 3707235064Stuexen if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 3708163953Srrs resp = (struct sctp_stream_reset_response_tsn *)respin; 3709163953Srrs asoc->stream_reset_outstanding--; 3710163953Srrs fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 3711163953Srrs fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 3712163953Srrs fwdtsn.new_cumulative_tsn = htonl(ntohl(resp->senders_next_tsn) - 1); 3713170992Srrs sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 3714163953Srrs if (abort_flag) { 3715163953Srrs return (1); 3716163953Srrs } 3717163953Srrs stcb->asoc.highest_tsn_inside_map = (ntohl(resp->senders_next_tsn) - 1); 3718179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 3719179783Srrs sctp_log_map(0, 7, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 3720179783Srrs } 3721180955Srrs stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map; 3722163953Srrs stcb->asoc.mapping_array_base_tsn = ntohl(resp->senders_next_tsn); 3723163953Srrs memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); 3724185694Srrs 3725205627Srrs stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; 3726206137Stuexen memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size); 3727205627Srrs 3728163953Srrs stcb->asoc.sending_seq = ntohl(resp->receivers_next_tsn); 3729163953Srrs stcb->asoc.last_acked_seq = stcb->asoc.cumulative_tsn; 3730163953Srrs 3731163953Srrs sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 3732163953Srrs sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 3733233660Srrs sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 0); 3734235066Stuexen } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 3735235066Stuexen sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 3736235066Stuexen SCTP_ASSOC_RESET_DENIED); 3737233660Srrs } else { 3738233660Srrs sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 3739235066Stuexen SCTP_ASSOC_RESET_FAILED); 3740163953Srrs } 3741163953Srrs } 3742163953Srrs /* get rid of the request and get the request flags */ 3743163953Srrs if (asoc->stream_reset_outstanding == 0) { 3744163953Srrs sctp_clean_up_stream_reset(stcb); 3745163953Srrs } 3746163953Srrs } 3747163953Srrs } 3748163953Srrs return (0); 3749163953Srrs} 3750163953Srrs 3751163953Srrsstatic void 3752163953Srrssctp_handle_str_reset_request_in(struct sctp_tcb *stcb, 3753163953Srrs struct sctp_tmit_chunk *chk, 3754170992Srrs struct sctp_stream_reset_in_request *req, int trunc) 3755163953Srrs{ 3756163953Srrs uint32_t seq; 3757163953Srrs int len, i; 3758163953Srrs int number_entries; 3759163953Srrs uint16_t temp; 3760163953Srrs 3761163953Srrs /* 3762163953Srrs * peer wants me to send a str-reset to him for my outgoing seq's if 3763163953Srrs * seq_in is right. 3764163953Srrs */ 3765163953Srrs struct sctp_association *asoc = &stcb->asoc; 3766163953Srrs 3767163953Srrs seq = ntohl(req->request_seq); 3768163953Srrs if (asoc->str_reset_seq_in == seq) { 3769235064Stuexen asoc->last_reset_action[1] = asoc->last_reset_action[0]; 3770235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 3771235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3772235064Stuexen } else if (trunc) { 3773170992Srrs /* Can't do it, since they exceeded our buffer size */ 3774235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3775170992Srrs } else if (stcb->asoc.stream_reset_out_is_outstanding == 0) { 3776163953Srrs len = ntohs(req->ph.param_length); 3777163953Srrs number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t)); 3778163953Srrs for (i = 0; i < number_entries; i++) { 3779163953Srrs temp = ntohs(req->list_of_streams[i]); 3780163953Srrs req->list_of_streams[i] = temp; 3781163953Srrs } 3782235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3783163953Srrs sctp_add_stream_reset_out(chk, number_entries, req->list_of_streams, 3784163953Srrs asoc->str_reset_seq_out, 3785163953Srrs seq, (asoc->sending_seq - 1)); 3786163953Srrs asoc->stream_reset_out_is_outstanding = 1; 3787163953Srrs asoc->str_reset = chk; 3788163953Srrs sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); 3789163953Srrs stcb->asoc.stream_reset_outstanding++; 3790163953Srrs } else { 3791163953Srrs /* Can't do it, since we have sent one out */ 3792235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 3793163953Srrs } 3794233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3795163953Srrs asoc->str_reset_seq_in++; 3796163953Srrs } else if (asoc->str_reset_seq_in - 1 == seq) { 3797163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3798163953Srrs } else if (asoc->str_reset_seq_in - 2 == seq) { 3799163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 3800163953Srrs } else { 3801235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3802163953Srrs } 3803163953Srrs} 3804163953Srrs 3805163953Srrsstatic int 3806163953Srrssctp_handle_str_reset_request_tsn(struct sctp_tcb *stcb, 3807163953Srrs struct sctp_tmit_chunk *chk, 3808163953Srrs struct sctp_stream_reset_tsn_request *req) 3809163953Srrs{ 3810163953Srrs /* reset all in and out and update the tsn */ 3811163953Srrs /* 3812163953Srrs * A) reset my str-seq's on in and out. B) Select a receive next, 3813163953Srrs * and set cum-ack to it. Also process this selected number as a 3814163953Srrs * fwd-tsn as well. C) set in the response my next sending seq. 3815163953Srrs */ 3816163953Srrs struct sctp_forward_tsn_chunk fwdtsn; 3817163953Srrs struct sctp_association *asoc = &stcb->asoc; 3818163953Srrs int abort_flag = 0; 3819163953Srrs uint32_t seq; 3820163953Srrs 3821163953Srrs seq = ntohl(req->request_seq); 3822163953Srrs if (asoc->str_reset_seq_in == seq) { 3823235283Stuexen asoc->last_reset_action[1] = stcb->asoc.last_reset_action[0]; 3824235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 3825235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3826235283Stuexen } else { 3827235064Stuexen fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 3828235283Stuexen fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 3829235283Stuexen fwdtsn.ch.chunk_flags = 0; 3830235283Stuexen fwdtsn.new_cumulative_tsn = htonl(stcb->asoc.highest_tsn_inside_map + 1); 3831235283Stuexen sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 3832235283Stuexen if (abort_flag) { 3833235283Stuexen return (1); 3834235283Stuexen } 3835235283Stuexen asoc->highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA; 3836235283Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 3837235283Stuexen sctp_log_map(0, 10, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 3838235283Stuexen } 3839235283Stuexen asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->highest_tsn_inside_map; 3840235283Stuexen asoc->mapping_array_base_tsn = asoc->highest_tsn_inside_map + 1; 3841235283Stuexen memset(asoc->mapping_array, 0, asoc->mapping_array_size); 3842235283Stuexen asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 3843235283Stuexen memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size); 3844235283Stuexen atomic_add_int(&asoc->sending_seq, 1); 3845235283Stuexen /* save off historical data for retrans */ 3846235283Stuexen asoc->last_sending_seq[1] = asoc->last_sending_seq[0]; 3847235283Stuexen asoc->last_sending_seq[0] = asoc->sending_seq; 3848235283Stuexen asoc->last_base_tsnsent[1] = asoc->last_base_tsnsent[0]; 3849235283Stuexen asoc->last_base_tsnsent[0] = asoc->mapping_array_base_tsn; 3850235283Stuexen sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 3851235283Stuexen sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 3852235283Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3853235283Stuexen sctp_notify_stream_reset_tsn(stcb, asoc->sending_seq, (asoc->mapping_array_base_tsn + 1), 0); 3854163953Srrs } 3855235283Stuexen sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 3856235283Stuexen asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 3857163953Srrs asoc->str_reset_seq_in++; 3858163953Srrs } else if (asoc->str_reset_seq_in - 1 == seq) { 3859163953Srrs sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 3860235064Stuexen asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 3861163953Srrs } else if (asoc->str_reset_seq_in - 2 == seq) { 3862163953Srrs sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[1], 3863235064Stuexen asoc->last_sending_seq[1], asoc->last_base_tsnsent[1]); 3864163953Srrs } else { 3865235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3866163953Srrs } 3867163953Srrs return (0); 3868163953Srrs} 3869163953Srrs 3870163953Srrsstatic void 3871163953Srrssctp_handle_str_reset_request_out(struct sctp_tcb *stcb, 3872163953Srrs struct sctp_tmit_chunk *chk, 3873170992Srrs struct sctp_stream_reset_out_request *req, int trunc) 3874163953Srrs{ 3875163953Srrs uint32_t seq, tsn; 3876163953Srrs int number_entries, len; 3877163953Srrs struct sctp_association *asoc = &stcb->asoc; 3878163953Srrs 3879163953Srrs seq = ntohl(req->request_seq); 3880163953Srrs 3881163953Srrs /* now if its not a duplicate we process it */ 3882163953Srrs if (asoc->str_reset_seq_in == seq) { 3883163953Srrs len = ntohs(req->ph.param_length); 3884163953Srrs number_entries = ((len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t)); 3885163953Srrs /* 3886163953Srrs * the sender is resetting, handle the list issue.. we must 3887163953Srrs * a) verify if we can do the reset, if so no problem b) If 3888163953Srrs * we can't do the reset we must copy the request. c) queue 3889163953Srrs * it, and setup the data in processor to trigger it off 3890163953Srrs * when needed and dequeue all the queued data. 3891163953Srrs */ 3892163953Srrs tsn = ntohl(req->send_reset_at_tsn); 3893163953Srrs 3894163953Srrs /* move the reset action back one */ 3895163953Srrs asoc->last_reset_action[1] = asoc->last_reset_action[0]; 3896235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 3897235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3898235064Stuexen } else if (trunc) { 3899235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3900216825Stuexen } else if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) { 3901163953Srrs /* we can do it now */ 3902163953Srrs sctp_reset_in_stream(stcb, number_entries, req->list_of_streams); 3903235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3904163953Srrs } else { 3905163953Srrs /* 3906163953Srrs * we must queue it up and thus wait for the TSN's 3907163953Srrs * to arrive that are at or before tsn 3908163953Srrs */ 3909163953Srrs struct sctp_stream_reset_list *liste; 3910163953Srrs int siz; 3911163953Srrs 3912163953Srrs siz = sizeof(struct sctp_stream_reset_list) + (number_entries * sizeof(uint16_t)); 3913163953Srrs SCTP_MALLOC(liste, struct sctp_stream_reset_list *, 3914170091Srrs siz, SCTP_M_STRESET); 3915163953Srrs if (liste == NULL) { 3916163953Srrs /* gak out of memory */ 3917235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3918235064Stuexen sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3919163953Srrs return; 3920163953Srrs } 3921163953Srrs liste->tsn = tsn; 3922163953Srrs liste->number_entries = number_entries; 3923163953Srrs memcpy(&liste->req, req, 3924163953Srrs (sizeof(struct sctp_stream_reset_out_request) + (number_entries * sizeof(uint16_t)))); 3925163953Srrs TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp); 3926235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 3927163953Srrs } 3928233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3929163953Srrs asoc->str_reset_seq_in++; 3930163953Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 3931163953Srrs /* 3932163953Srrs * one seq back, just echo back last action since my 3933163953Srrs * response was lost. 3934163953Srrs */ 3935163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 3936163953Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 3937163953Srrs /* 3938163953Srrs * two seq back, just echo back last action since my 3939163953Srrs * response was lost. 3940163953Srrs */ 3941163953Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 3942163953Srrs } else { 3943235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 3944163953Srrs } 3945163953Srrs} 3946163953Srrs 3947188854Srrsstatic void 3948188854Srrssctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 3949188854Srrs struct sctp_stream_reset_add_strm *str_add) 3950188854Srrs{ 3951188854Srrs /* 3952188854Srrs * Peer is requesting to add more streams. If its within our 3953188854Srrs * max-streams we will allow it. 3954188854Srrs */ 3955233660Srrs uint32_t num_stream, i; 3956188854Srrs uint32_t seq; 3957189121Srrs struct sctp_association *asoc = &stcb->asoc; 3958216822Stuexen struct sctp_queued_to_read *ctl, *nctl; 3959188854Srrs 3960188854Srrs /* Get the number. */ 3961188854Srrs seq = ntohl(str_add->request_seq); 3962188854Srrs num_stream = ntohs(str_add->number_of_streams); 3963188854Srrs /* Now what would be the new total? */ 3964189121Srrs if (asoc->str_reset_seq_in == seq) { 3965189121Srrs num_stream += stcb->asoc.streamincnt; 3966235064Stuexen stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 3967235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 3968235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3969235064Stuexen } else if ((num_stream > stcb->asoc.max_inbound_streams) || 3970233660Srrs (num_stream > 0xffff)) { 3971189121Srrs /* We must reject it they ask for to many */ 3972189121Srrs denied: 3973235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 3974189121Srrs } else { 3975189121Srrs /* Ok, we can do that :-) */ 3976189121Srrs struct sctp_stream_in *oldstrm; 3977189121Srrs 3978189121Srrs /* save off the old */ 3979189121Srrs oldstrm = stcb->asoc.strmin; 3980189121Srrs SCTP_MALLOC(stcb->asoc.strmin, struct sctp_stream_in *, 3981189121Srrs (num_stream * sizeof(struct sctp_stream_in)), 3982189121Srrs SCTP_M_STRMI); 3983189121Srrs if (stcb->asoc.strmin == NULL) { 3984189121Srrs stcb->asoc.strmin = oldstrm; 3985189121Srrs goto denied; 3986189121Srrs } 3987189121Srrs /* copy off the old data */ 3988189121Srrs for (i = 0; i < stcb->asoc.streamincnt; i++) { 3989189121Srrs TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 3990189121Srrs stcb->asoc.strmin[i].stream_no = i; 3991189121Srrs stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered; 3992189121Srrs stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started; 3993189121Srrs /* now anything on those queues? */ 3994216822Stuexen TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next, nctl) { 3995189121Srrs TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next); 3996189121Srrs TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next); 3997189121Srrs } 3998189121Srrs } 3999189121Srrs /* Init the new streams */ 4000189121Srrs for (i = stcb->asoc.streamincnt; i < num_stream; i++) { 4001189121Srrs TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 4002189121Srrs stcb->asoc.strmin[i].stream_no = i; 4003189121Srrs stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 4004189121Srrs stcb->asoc.strmin[i].delivery_started = 0; 4005189121Srrs } 4006189121Srrs SCTP_FREE(oldstrm, SCTP_M_STRMI); 4007189121Srrs /* update the size */ 4008189121Srrs stcb->asoc.streamincnt = num_stream; 4009235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 4010233660Srrs sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 4011189121Srrs } 4012233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 4013233660Srrs asoc->str_reset_seq_in++; 4014189121Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 4015189121Srrs /* 4016189121Srrs * one seq back, just echo back last action since my 4017189121Srrs * response was lost. 4018189121Srrs */ 4019189121Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 4020189121Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 4021189121Srrs /* 4022189121Srrs * two seq back, just echo back last action since my 4023189121Srrs * response was lost. 4024189121Srrs */ 4025189121Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 4026188854Srrs } else { 4027235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 4028188854Srrs 4029188854Srrs } 4030188854Srrs} 4031188854Srrs 4032233660Srrsstatic void 4033233660Srrssctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 4034233660Srrs struct sctp_stream_reset_add_strm *str_add) 4035233660Srrs{ 4036233660Srrs /* 4037233660Srrs * Peer is requesting to add more streams. If its within our 4038233660Srrs * max-streams we will allow it. 4039233660Srrs */ 4040233660Srrs uint16_t num_stream; 4041233660Srrs uint32_t seq; 4042233660Srrs struct sctp_association *asoc = &stcb->asoc; 4043233660Srrs 4044233660Srrs /* Get the number. */ 4045233660Srrs seq = ntohl(str_add->request_seq); 4046233660Srrs num_stream = ntohs(str_add->number_of_streams); 4047233660Srrs /* Now what would be the new total? */ 4048233660Srrs if (asoc->str_reset_seq_in == seq) { 4049235064Stuexen stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 4050235064Stuexen if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 4051235064Stuexen asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4052235064Stuexen } else if (stcb->asoc.stream_reset_outstanding) { 4053233660Srrs /* We must reject it we have something pending */ 4054235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 4055233660Srrs } else { 4056233660Srrs /* Ok, we can do that :-) */ 4057233660Srrs int mychk; 4058233660Srrs 4059233660Srrs mychk = stcb->asoc.streamoutcnt; 4060233660Srrs mychk += num_stream; 4061233660Srrs if (mychk < 0x10000) { 4062235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 4063233660Srrs if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, 1, num_stream, 0, 1)) { 4064235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4065233660Srrs } 4066233660Srrs } else { 4067235064Stuexen stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 4068233660Srrs } 4069233660Srrs } 4070233660Srrs sctp_add_stream_reset_result(chk, seq, stcb->asoc.last_reset_action[0]); 4071233660Srrs asoc->str_reset_seq_in++; 4072233660Srrs } else if ((asoc->str_reset_seq_in - 1) == seq) { 4073233660Srrs /* 4074233660Srrs * one seq back, just echo back last action since my 4075233660Srrs * response was lost. 4076233660Srrs */ 4077233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 4078233660Srrs } else if ((asoc->str_reset_seq_in - 2) == seq) { 4079233660Srrs /* 4080233660Srrs * two seq back, just echo back last action since my 4081233660Srrs * response was lost. 4082233660Srrs */ 4083233660Srrs sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 4084233660Srrs } else { 4085235064Stuexen sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 4086233660Srrs } 4087233660Srrs} 4088233660Srrs 4089170992Srrs#ifdef __GNUC__ 4090170992Srrs__attribute__((noinline)) 4091170992Srrs#endif 4092170992Srrs static int 4093170992Srrs sctp_handle_stream_reset(struct sctp_tcb *stcb, struct mbuf *m, int offset, 4094170992Srrs struct sctp_stream_reset_out_req *sr_req) 4095163953Srrs{ 4096163953Srrs int chk_length, param_len, ptype; 4097170992Srrs struct sctp_paramhdr pstore; 4098170992Srrs uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE]; 4099233660Srrs uint32_t seq = 0; 4100163953Srrs int num_req = 0; 4101170992Srrs int trunc = 0; 4102163953Srrs struct sctp_tmit_chunk *chk; 4103163953Srrs struct sctp_chunkhdr *ch; 4104163953Srrs struct sctp_paramhdr *ph; 4105166675Srrs int ret_code = 0; 4106166675Srrs int num_param = 0; 4107163953Srrs 4108163953Srrs /* now it may be a reset or a reset-response */ 4109163953Srrs chk_length = ntohs(sr_req->ch.chunk_length); 4110163953Srrs 4111163953Srrs /* setup for adding the response */ 4112163953Srrs sctp_alloc_a_chunk(stcb, chk); 4113163953Srrs if (chk == NULL) { 4114163953Srrs return (ret_code); 4115163953Srrs } 4116163953Srrs chk->rec.chunk_id.id = SCTP_STREAM_RESET; 4117169208Srrs chk->rec.chunk_id.can_take_data = 0; 4118163953Srrs chk->asoc = &stcb->asoc; 4119163953Srrs chk->no_fr_allowed = 0; 4120163953Srrs chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr); 4121166023Srrs chk->book_size_scale = 0; 4122165647Srrs chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); 4123163953Srrs if (chk->data == NULL) { 4124163953Srrsstrres_nochunk: 4125163953Srrs if (chk->data) { 4126163953Srrs sctp_m_freem(chk->data); 4127163953Srrs chk->data = NULL; 4128163953Srrs } 4129221627Stuexen sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 4130163953Srrs return (ret_code); 4131163953Srrs } 4132165647Srrs SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); 4133163953Srrs 4134163953Srrs /* setup chunk parameters */ 4135163953Srrs chk->sent = SCTP_DATAGRAM_UNSENT; 4136163953Srrs chk->snd_count = 0; 4137224641Stuexen chk->whoTo = NULL; 4138163953Srrs 4139163953Srrs ch = mtod(chk->data, struct sctp_chunkhdr *); 4140163953Srrs ch->chunk_type = SCTP_STREAM_RESET; 4141163953Srrs ch->chunk_flags = 0; 4142163953Srrs ch->chunk_length = htons(chk->send_size); 4143165647Srrs SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size); 4144170992Srrs offset += sizeof(struct sctp_chunkhdr); 4145163953Srrs while ((size_t)chk_length >= sizeof(struct sctp_stream_reset_tsn_request)) { 4146170992Srrs ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(pstore), (uint8_t *) & pstore); 4147170992Srrs if (ph == NULL) 4148170992Srrs break; 4149163953Srrs param_len = ntohs(ph->param_length); 4150163953Srrs if (param_len < (int)sizeof(struct sctp_stream_reset_tsn_request)) { 4151163953Srrs /* bad param */ 4152163953Srrs break; 4153163953Srrs } 4154170994Srrs ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, (int)sizeof(cstore)), 4155170992Srrs (uint8_t *) & cstore); 4156163953Srrs ptype = ntohs(ph->param_type); 4157163953Srrs num_param++; 4158170994Srrs if (param_len > (int)sizeof(cstore)) { 4159170992Srrs trunc = 1; 4160170992Srrs } else { 4161170992Srrs trunc = 0; 4162170992Srrs } 4163163953Srrs if (num_param > SCTP_MAX_RESET_PARAMS) { 4164163953Srrs /* hit the max of parameters already sorry.. */ 4165163953Srrs break; 4166163953Srrs } 4167163953Srrs if (ptype == SCTP_STR_RESET_OUT_REQUEST) { 4168163953Srrs struct sctp_stream_reset_out_request *req_out; 4169163953Srrs 4170163953Srrs req_out = (struct sctp_stream_reset_out_request *)ph; 4171163953Srrs num_req++; 4172163953Srrs if (stcb->asoc.stream_reset_outstanding) { 4173163953Srrs seq = ntohl(req_out->response_seq); 4174163953Srrs if (seq == stcb->asoc.str_reset_seq_out) { 4175163953Srrs /* implicit ack */ 4176235064Stuexen (void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_RESULT_PERFORMED, NULL); 4177163953Srrs } 4178163953Srrs } 4179170992Srrs sctp_handle_str_reset_request_out(stcb, chk, req_out, trunc); 4180233660Srrs } else if (ptype == SCTP_STR_RESET_ADD_OUT_STREAMS) { 4181188854Srrs struct sctp_stream_reset_add_strm *str_add; 4182188854Srrs 4183188854Srrs str_add = (struct sctp_stream_reset_add_strm *)ph; 4184188854Srrs num_req++; 4185188854Srrs sctp_handle_str_reset_add_strm(stcb, chk, str_add); 4186233660Srrs } else if (ptype == SCTP_STR_RESET_ADD_IN_STREAMS) { 4187233660Srrs struct sctp_stream_reset_add_strm *str_add; 4188233660Srrs 4189233660Srrs str_add = (struct sctp_stream_reset_add_strm *)ph; 4190233660Srrs num_req++; 4191233660Srrs sctp_handle_str_reset_add_out_strm(stcb, chk, str_add); 4192163953Srrs } else if (ptype == SCTP_STR_RESET_IN_REQUEST) { 4193163953Srrs struct sctp_stream_reset_in_request *req_in; 4194163953Srrs 4195163953Srrs num_req++; 4196163953Srrs req_in = (struct sctp_stream_reset_in_request *)ph; 4197170992Srrs sctp_handle_str_reset_request_in(stcb, chk, req_in, trunc); 4198163953Srrs } else if (ptype == SCTP_STR_RESET_TSN_REQUEST) { 4199163953Srrs struct sctp_stream_reset_tsn_request *req_tsn; 4200163953Srrs 4201163953Srrs num_req++; 4202163953Srrs req_tsn = (struct sctp_stream_reset_tsn_request *)ph; 4203163953Srrs if (sctp_handle_str_reset_request_tsn(stcb, chk, req_tsn)) { 4204163953Srrs ret_code = 1; 4205163953Srrs goto strres_nochunk; 4206163953Srrs } 4207163953Srrs /* no more */ 4208163953Srrs break; 4209163953Srrs } else if (ptype == SCTP_STR_RESET_RESPONSE) { 4210163953Srrs struct sctp_stream_reset_response *resp; 4211163953Srrs uint32_t result; 4212163953Srrs 4213163953Srrs resp = (struct sctp_stream_reset_response *)ph; 4214163953Srrs seq = ntohl(resp->response_seq); 4215163953Srrs result = ntohl(resp->result); 4216163953Srrs if (sctp_handle_stream_reset_response(stcb, seq, result, resp)) { 4217163953Srrs ret_code = 1; 4218163953Srrs goto strres_nochunk; 4219163953Srrs } 4220163953Srrs } else { 4221163953Srrs break; 4222163953Srrs } 4223170992Srrs offset += SCTP_SIZE32(param_len); 4224163953Srrs chk_length -= SCTP_SIZE32(param_len); 4225163953Srrs } 4226163953Srrs if (num_req == 0) { 4227163953Srrs /* we have no response free the stuff */ 4228163953Srrs goto strres_nochunk; 4229163953Srrs } 4230163953Srrs /* ok we have a chunk to link in */ 4231163953Srrs TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue, 4232163953Srrs chk, 4233163953Srrs sctp_next); 4234163953Srrs stcb->asoc.ctrl_queue_cnt++; 4235163953Srrs return (ret_code); 4236163953Srrs} 4237163953Srrs 4238163953Srrs/* 4239163953Srrs * Handle a router or endpoints report of a packet loss, there are two ways 4240163953Srrs * to handle this, either we get the whole packet and must disect it 4241163953Srrs * ourselves (possibly with truncation and or corruption) or it is a summary 4242163953Srrs * from a middle box that did the disectting for us. 4243163953Srrs */ 4244163953Srrsstatic void 4245163953Srrssctp_handle_packet_dropped(struct sctp_pktdrop_chunk *cp, 4246170781Srrs struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t limit) 4247163953Srrs{ 4248163953Srrs uint32_t bottle_bw, on_queue; 4249163953Srrs uint16_t trunc_len; 4250163953Srrs unsigned int chlen; 4251163953Srrs unsigned int at; 4252163953Srrs struct sctp_chunk_desc desc; 4253163953Srrs struct sctp_chunkhdr *ch; 4254163953Srrs 4255163953Srrs chlen = ntohs(cp->ch.chunk_length); 4256163953Srrs chlen -= sizeof(struct sctp_pktdrop_chunk); 4257163953Srrs /* XXX possible chlen underflow */ 4258163953Srrs if (chlen == 0) { 4259163953Srrs ch = NULL; 4260163953Srrs if (cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) 4261163953Srrs SCTP_STAT_INCR(sctps_pdrpbwrpt); 4262163953Srrs } else { 4263163953Srrs ch = (struct sctp_chunkhdr *)(cp->data + sizeof(struct sctphdr)); 4264163953Srrs chlen -= sizeof(struct sctphdr); 4265163953Srrs /* XXX possible chlen underflow */ 4266163953Srrs memset(&desc, 0, sizeof(desc)); 4267163953Srrs } 4268163953Srrs trunc_len = (uint16_t) ntohs(cp->trunc_len); 4269170781Srrs if (trunc_len > limit) { 4270170781Srrs trunc_len = limit; 4271170781Srrs } 4272163953Srrs /* now the chunks themselves */ 4273163953Srrs while ((ch != NULL) && (chlen >= sizeof(struct sctp_chunkhdr))) { 4274163953Srrs desc.chunk_type = ch->chunk_type; 4275163953Srrs /* get amount we need to move */ 4276163953Srrs at = ntohs(ch->chunk_length); 4277163953Srrs if (at < sizeof(struct sctp_chunkhdr)) { 4278163953Srrs /* corrupt chunk, maybe at the end? */ 4279163953Srrs SCTP_STAT_INCR(sctps_pdrpcrupt); 4280163953Srrs break; 4281163953Srrs } 4282163953Srrs if (trunc_len == 0) { 4283163953Srrs /* we are supposed to have all of it */ 4284163953Srrs if (at > chlen) { 4285163953Srrs /* corrupt skip it */ 4286163953Srrs SCTP_STAT_INCR(sctps_pdrpcrupt); 4287163953Srrs break; 4288163953Srrs } 4289163953Srrs } else { 4290163953Srrs /* is there enough of it left ? */ 4291163953Srrs if (desc.chunk_type == SCTP_DATA) { 4292163953Srrs if (chlen < (sizeof(struct sctp_data_chunk) + 4293163953Srrs sizeof(desc.data_bytes))) { 4294163953Srrs break; 4295163953Srrs } 4296163953Srrs } else { 4297163953Srrs if (chlen < sizeof(struct sctp_chunkhdr)) { 4298163953Srrs break; 4299163953Srrs } 4300163953Srrs } 4301163953Srrs } 4302163953Srrs if (desc.chunk_type == SCTP_DATA) { 4303163953Srrs /* can we get out the tsn? */ 4304163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 4305163953Srrs SCTP_STAT_INCR(sctps_pdrpmbda); 4306163953Srrs 4307163953Srrs if (chlen >= (sizeof(struct sctp_data_chunk) + sizeof(uint32_t))) { 4308163953Srrs /* yep */ 4309163953Srrs struct sctp_data_chunk *dcp; 4310163953Srrs uint8_t *ddp; 4311163953Srrs unsigned int iii; 4312163953Srrs 4313163953Srrs dcp = (struct sctp_data_chunk *)ch; 4314163953Srrs ddp = (uint8_t *) (dcp + 1); 4315163953Srrs for (iii = 0; iii < sizeof(desc.data_bytes); iii++) { 4316163953Srrs desc.data_bytes[iii] = ddp[iii]; 4317163953Srrs } 4318163953Srrs desc.tsn_ifany = dcp->dp.tsn; 4319163953Srrs } else { 4320163953Srrs /* nope we are done. */ 4321163953Srrs SCTP_STAT_INCR(sctps_pdrpnedat); 4322163953Srrs break; 4323163953Srrs } 4324163953Srrs } else { 4325163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 4326163953Srrs SCTP_STAT_INCR(sctps_pdrpmbct); 4327163953Srrs } 4328163953Srrs 4329163953Srrs if (process_chunk_drop(stcb, &desc, net, cp->ch.chunk_flags)) { 4330163953Srrs SCTP_STAT_INCR(sctps_pdrppdbrk); 4331163953Srrs break; 4332163953Srrs } 4333163953Srrs if (SCTP_SIZE32(at) > chlen) { 4334163953Srrs break; 4335163953Srrs } 4336163953Srrs chlen -= SCTP_SIZE32(at); 4337163953Srrs if (chlen < sizeof(struct sctp_chunkhdr)) { 4338163953Srrs /* done, none left */ 4339163953Srrs break; 4340163953Srrs } 4341163953Srrs ch = (struct sctp_chunkhdr *)((caddr_t)ch + SCTP_SIZE32(at)); 4342163953Srrs } 4343163953Srrs /* Now update any rwnd --- possibly */ 4344163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) == 0) { 4345163953Srrs /* From a peer, we get a rwnd report */ 4346163953Srrs uint32_t a_rwnd; 4347163953Srrs 4348163953Srrs SCTP_STAT_INCR(sctps_pdrpfehos); 4349163953Srrs 4350163953Srrs bottle_bw = ntohl(cp->bottle_bw); 4351163953Srrs on_queue = ntohl(cp->current_onq); 4352163953Srrs if (bottle_bw && on_queue) { 4353163953Srrs /* a rwnd report is in here */ 4354163953Srrs if (bottle_bw > on_queue) 4355163953Srrs a_rwnd = bottle_bw - on_queue; 4356163953Srrs else 4357163953Srrs a_rwnd = 0; 4358163953Srrs 4359163953Srrs if (a_rwnd == 0) 4360163953Srrs stcb->asoc.peers_rwnd = 0; 4361163953Srrs else { 4362163953Srrs if (a_rwnd > stcb->asoc.total_flight) { 4363163953Srrs stcb->asoc.peers_rwnd = 4364163953Srrs a_rwnd - stcb->asoc.total_flight; 4365163953Srrs } else { 4366163953Srrs stcb->asoc.peers_rwnd = 0; 4367163953Srrs } 4368163953Srrs if (stcb->asoc.peers_rwnd < 4369163953Srrs stcb->sctp_ep->sctp_ep.sctp_sws_sender) { 4370163953Srrs /* SWS sender side engages */ 4371163953Srrs stcb->asoc.peers_rwnd = 0; 4372163953Srrs } 4373163953Srrs } 4374163953Srrs } 4375163953Srrs } else { 4376163953Srrs SCTP_STAT_INCR(sctps_pdrpfmbox); 4377163953Srrs } 4378163953Srrs 4379163953Srrs /* now middle boxes in sat networks get a cwnd bump */ 4380163953Srrs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) && 4381163953Srrs (stcb->asoc.sat_t3_loss_recovery == 0) && 4382163953Srrs (stcb->asoc.sat_network)) { 4383163953Srrs /* 4384163953Srrs * This is debateable but for sat networks it makes sense 4385163953Srrs * Note if a T3 timer has went off, we will prohibit any 4386163953Srrs * changes to cwnd until we exit the t3 loss recovery. 4387163953Srrs */ 4388171440Srrs stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped(stcb, 4389171440Srrs net, cp, &bottle_bw, &on_queue); 4390163953Srrs } 4391163953Srrs} 4392163953Srrs 4393163953Srrs/* 4394163953Srrs * handles all control chunks in a packet inputs: - m: mbuf chain, assumed to 4395163953Srrs * still contain IP/SCTP header - stcb: is the tcb found for this packet - 4396163953Srrs * offset: offset into the mbuf chain to first chunkhdr - length: is the 4397163953Srrs * length of the complete packet outputs: - length: modified to remaining 4398163953Srrs * length after control processing - netp: modified to new sctp_nets after 4399163953Srrs * cookie-echo processing - return NULL to discard the packet (ie. no asoc, 4400163953Srrs * bad packet,...) otherwise return the tcb for this packet 4401163953Srrs */ 4402170099Srrs#ifdef __GNUC__ 4403170099Srrs__attribute__((noinline)) 4404170099Srrs#endif 4405170099Srrs static struct sctp_tcb * 4406170099Srrs sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, 4407170099Srrs struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp, 4408170099Srrs struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen, 4409237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 4410179157Srrs uint32_t vrf_id, uint16_t port) 4411163953Srrs{ 4412163953Srrs struct sctp_association *asoc; 4413163953Srrs uint32_t vtag_in; 4414163953Srrs int num_chunks = 0; /* number of control chunks processed */ 4415170140Srrs uint32_t chk_length; 4416163953Srrs int ret; 4417168299Srrs int abort_no_unlock = 0; 4418218186Srrs int ecne_seen = 0; 4419163953Srrs 4420163953Srrs /* 4421163953Srrs * How big should this be, and should it be alloc'd? Lets try the 4422163953Srrs * d-mtu-ceiling for now (2k) and that should hopefully work ... 4423163953Srrs * until we get into jumbo grams and such.. 4424163953Srrs */ 4425166675Srrs uint8_t chunk_buf[SCTP_CHUNK_BUFFER_SIZE]; 4426163953Srrs struct sctp_tcb *locked_tcb = stcb; 4427163953Srrs int got_auth = 0; 4428163953Srrs uint32_t auth_offset = 0, auth_len = 0; 4429163953Srrs int auth_skipped = 0; 4430171990Srrs int asconf_cnt = 0; 4431163953Srrs 4432237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4433172090Srrs struct socket *so; 4434172090Srrs 4435172090Srrs#endif 4436172090Srrs 4437169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n", 4438169420Srrs iphlen, *offset, length, stcb); 4439163953Srrs 4440163953Srrs /* validate chunk header length... */ 4441163953Srrs if (ntohs(ch->chunk_length) < sizeof(*ch)) { 4442170056Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Invalid header length %d\n", 4443170056Srrs ntohs(ch->chunk_length)); 4444170091Srrs if (locked_tcb) { 4445170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4446170091Srrs } 4447163953Srrs return (NULL); 4448163953Srrs } 4449163953Srrs /* 4450163953Srrs * validate the verification tag 4451163953Srrs */ 4452163953Srrs vtag_in = ntohl(sh->v_tag); 4453163953Srrs 4454165220Srrs if (locked_tcb) { 4455165220Srrs SCTP_TCB_LOCK_ASSERT(locked_tcb); 4456165220Srrs } 4457163953Srrs if (ch->chunk_type == SCTP_INITIATION) { 4458170056Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Its an INIT of len:%d vtag:%x\n", 4459170056Srrs ntohs(ch->chunk_length), vtag_in); 4460163953Srrs if (vtag_in != 0) { 4461163953Srrs /* protocol error- silently discard... */ 4462163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4463169378Srrs if (locked_tcb) { 4464163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4465169378Srrs } 4466163953Srrs return (NULL); 4467163953Srrs } 4468163953Srrs } else if (ch->chunk_type != SCTP_COOKIE_ECHO) { 4469163953Srrs /* 4470163953Srrs * If there is no stcb, skip the AUTH chunk and process 4471163953Srrs * later after a stcb is found (to validate the lookup was 4472163953Srrs * valid. 4473163953Srrs */ 4474163953Srrs if ((ch->chunk_type == SCTP_AUTHENTICATION) && 4475179783Srrs (stcb == NULL) && 4476179783Srrs !SCTP_BASE_SYSCTL(sctp_auth_disable)) { 4477163953Srrs /* save this chunk for later processing */ 4478163953Srrs auth_skipped = 1; 4479163953Srrs auth_offset = *offset; 4480163953Srrs auth_len = ntohs(ch->chunk_length); 4481163953Srrs 4482163953Srrs /* (temporarily) move past this chunk */ 4483163953Srrs *offset += SCTP_SIZE32(auth_len); 4484163953Srrs if (*offset >= length) { 4485163953Srrs /* no more data left in the mbuf chain */ 4486163953Srrs *offset = length; 4487170091Srrs if (locked_tcb) { 4488170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4489170091Srrs } 4490163953Srrs return (NULL); 4491163953Srrs } 4492163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4493163953Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 4494163953Srrs } 4495169420Srrs if (ch == NULL) { 4496169420Srrs /* Help */ 4497169420Srrs *offset = length; 4498170091Srrs if (locked_tcb) { 4499170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4500170091Srrs } 4501169420Srrs return (NULL); 4502169420Srrs } 4503163953Srrs if (ch->chunk_type == SCTP_COOKIE_ECHO) { 4504163953Srrs goto process_control_chunks; 4505163953Srrs } 4506163953Srrs /* 4507163953Srrs * first check if it's an ASCONF with an unknown src addr we 4508163953Srrs * need to look inside to find the association 4509163953Srrs */ 4510163953Srrs if (ch->chunk_type == SCTP_ASCONF && stcb == NULL) { 4511171990Srrs struct sctp_chunkhdr *asconf_ch = ch; 4512171990Srrs uint32_t asconf_offset = 0, asconf_len = 0; 4513171990Srrs 4514163953Srrs /* inp's refcount may be reduced */ 4515163953Srrs SCTP_INP_INCR_REF(inp); 4516163953Srrs 4517171990Srrs asconf_offset = *offset; 4518171990Srrs do { 4519171990Srrs asconf_len = ntohs(asconf_ch->chunk_length); 4520171990Srrs if (asconf_len < sizeof(struct sctp_asconf_paramhdr)) 4521171990Srrs break; 4522228653Stuexen stcb = sctp_findassociation_ep_asconf(m, 4523185694Srrs *offset, sh, &inp, netp, vrf_id); 4524171990Srrs if (stcb != NULL) 4525171990Srrs break; 4526171990Srrs asconf_offset += SCTP_SIZE32(asconf_len); 4527171990Srrs asconf_ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, asconf_offset, 4528171990Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 4529171990Srrs } while (asconf_ch != NULL && asconf_ch->chunk_type == SCTP_ASCONF); 4530163953Srrs if (stcb == NULL) { 4531163953Srrs /* 4532163953Srrs * reduce inp's refcount if not reduced in 4533163953Srrs * sctp_findassociation_ep_asconf(). 4534163953Srrs */ 4535163953Srrs SCTP_INP_DECR_REF(inp); 4536171990Srrs } else { 4537171990Srrs locked_tcb = stcb; 4538163953Srrs } 4539171990Srrs 4540163953Srrs /* now go back and verify any auth chunk to be sure */ 4541163953Srrs if (auth_skipped && (stcb != NULL)) { 4542163953Srrs struct sctp_auth_chunk *auth; 4543163953Srrs 4544163953Srrs auth = (struct sctp_auth_chunk *) 4545163953Srrs sctp_m_getptr(m, auth_offset, 4546163953Srrs auth_len, chunk_buf); 4547163953Srrs got_auth = 1; 4548163953Srrs auth_skipped = 0; 4549169420Srrs if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, 4550163953Srrs auth_offset)) { 4551163953Srrs /* auth HMAC failed so dump it */ 4552163953Srrs *offset = length; 4553170091Srrs if (locked_tcb) { 4554170091Srrs SCTP_TCB_UNLOCK(locked_tcb); 4555170091Srrs } 4556163953Srrs return (NULL); 4557163953Srrs } else { 4558163953Srrs /* remaining chunks are HMAC checked */ 4559163953Srrs stcb->asoc.authenticated = 1; 4560163953Srrs } 4561163953Srrs } 4562163953Srrs } 4563163953Srrs if (stcb == NULL) { 4564163953Srrs /* no association, so it's out of the blue... */ 4565236450Stuexen sctp_handle_ootb(m, iphlen, *offset, sh, inp, 4566237049Stuexen use_mflowid, mflowid, 4567179157Srrs vrf_id, port); 4568163953Srrs *offset = length; 4569169378Srrs if (locked_tcb) { 4570163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4571169378Srrs } 4572163953Srrs return (NULL); 4573163953Srrs } 4574163953Srrs asoc = &stcb->asoc; 4575163953Srrs /* ABORT and SHUTDOWN can use either v_tag... */ 4576163953Srrs if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) || 4577163953Srrs (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) || 4578163953Srrs (ch->chunk_type == SCTP_PACKET_DROPPED)) { 4579163953Srrs if ((vtag_in == asoc->my_vtag) || 4580163953Srrs ((ch->chunk_flags & SCTP_HAD_NO_TCB) && 4581163953Srrs (vtag_in == asoc->peer_vtag))) { 4582163953Srrs /* this is valid */ 4583163953Srrs } else { 4584163953Srrs /* drop this packet... */ 4585163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4586169378Srrs if (locked_tcb) { 4587163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4588169378Srrs } 4589163953Srrs return (NULL); 4590163953Srrs } 4591163953Srrs } else if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 4592163953Srrs if (vtag_in != asoc->my_vtag) { 4593163953Srrs /* 4594163953Srrs * this could be a stale SHUTDOWN-ACK or the 4595163953Srrs * peer never got the SHUTDOWN-COMPLETE and 4596163953Srrs * is still hung; we have started a new asoc 4597163953Srrs * but it won't complete until the shutdown 4598163953Srrs * is completed 4599163953Srrs */ 4600169378Srrs if (locked_tcb) { 4601163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4602169378Srrs } 4603163953Srrs sctp_handle_ootb(m, iphlen, *offset, sh, inp, 4604237049Stuexen use_mflowid, mflowid, 4605236450Stuexen vrf_id, port); 4606163953Srrs return (NULL); 4607163953Srrs } 4608163953Srrs } else { 4609163953Srrs /* for all other chunks, vtag must match */ 4610163953Srrs if (vtag_in != asoc->my_vtag) { 4611163953Srrs /* invalid vtag... */ 4612169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 4613169420Srrs "invalid vtag: %xh, expect %xh\n", 4614169420Srrs vtag_in, asoc->my_vtag); 4615163953Srrs SCTP_STAT_INCR(sctps_badvtag); 4616169378Srrs if (locked_tcb) { 4617163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4618169378Srrs } 4619163953Srrs *offset = length; 4620163953Srrs return (NULL); 4621163953Srrs } 4622163953Srrs } 4623163953Srrs } /* end if !SCTP_COOKIE_ECHO */ 4624163953Srrs /* 4625163953Srrs * process all control chunks... 4626163953Srrs */ 4627163953Srrs if (((ch->chunk_type == SCTP_SELECTIVE_ACK) || 4628185694Srrs (ch->chunk_type == SCTP_NR_SELECTIVE_ACK) || 4629163953Srrs (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) && 4630163953Srrs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { 4631163953Srrs /* implied cookie-ack.. we must have lost the ack */ 4632179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 4633171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 4634171943Srrs stcb->asoc.overall_error_count, 4635171943Srrs 0, 4636171943Srrs SCTP_FROM_SCTP_INPUT, 4637171943Srrs __LINE__); 4638171943Srrs } 4639163953Srrs stcb->asoc.overall_error_count = 0; 4640163953Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, 4641163953Srrs *netp); 4642163953Srrs } 4643163953Srrsprocess_control_chunks: 4644163953Srrs while (IS_SCTP_CONTROL(ch)) { 4645163953Srrs /* validate chunk length */ 4646163953Srrs chk_length = ntohs(ch->chunk_length); 4647169420Srrs SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_process_control: processing a chunk type=%u, len=%u\n", 4648169420Srrs ch->chunk_type, chk_length); 4649170744Srrs SCTP_LTRACE_CHK(inp, stcb, ch->chunk_type, chk_length); 4650170140Srrs if (chk_length < sizeof(*ch) || 4651170140Srrs (*offset + (int)chk_length) > length) { 4652163953Srrs *offset = length; 4653169378Srrs if (locked_tcb) { 4654163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4655169378Srrs } 4656163953Srrs return (NULL); 4657163953Srrs } 4658163953Srrs SCTP_STAT_INCR_COUNTER64(sctps_incontrolchunks); 4659163953Srrs /* 4660163953Srrs * INIT-ACK only gets the init ack "header" portion only 4661163953Srrs * because we don't have to process the peer's COOKIE. All 4662163953Srrs * others get a complete chunk. 4663163953Srrs */ 4664169208Srrs if ((ch->chunk_type == SCTP_INITIATION_ACK) || 4665169208Srrs (ch->chunk_type == SCTP_INITIATION)) { 4666163953Srrs /* get an init-ack chunk */ 4667163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4668163953Srrs sizeof(struct sctp_init_ack_chunk), chunk_buf); 4669163953Srrs if (ch == NULL) { 4670163953Srrs *offset = length; 4671169378Srrs if (locked_tcb) { 4672163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4673169378Srrs } 4674163953Srrs return (NULL); 4675163953Srrs } 4676170642Srrs } else { 4677170786Srrs /* For cookies and all other chunks. */ 4678169208Srrs if (chk_length > sizeof(chunk_buf)) { 4679169208Srrs /* 4680169208Srrs * use just the size of the chunk buffer so 4681170642Srrs * the front part of our chunks fit in 4682170642Srrs * contiguous space up to the chunk buffer 4683170642Srrs * size (508 bytes). For chunks that need to 4684170786Srrs * get more than that they must use the 4685170642Srrs * sctp_m_getptr() function or other means 4686170786Srrs * (e.g. know how to parse mbuf chains). 4687170786Srrs * Cookies do this already. 4688169208Srrs */ 4689169208Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4690169208Srrs (sizeof(chunk_buf) - 4), 4691169208Srrs chunk_buf); 4692169208Srrs if (ch == NULL) { 4693169208Srrs *offset = length; 4694169378Srrs if (locked_tcb) { 4695169208Srrs SCTP_TCB_UNLOCK(locked_tcb); 4696169378Srrs } 4697169208Srrs return (NULL); 4698169208Srrs } 4699169208Srrs } else { 4700169208Srrs /* We can fit it all */ 4701170642Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 4702170642Srrs chk_length, chunk_buf); 4703170642Srrs if (ch == NULL) { 4704170642Srrs SCTP_PRINTF("sctp_process_control: Can't get the all data....\n"); 4705170642Srrs *offset = length; 4706170642Srrs if (locked_tcb) { 4707170642Srrs SCTP_TCB_UNLOCK(locked_tcb); 4708169208Srrs } 4709170642Srrs return (NULL); 4710163953Srrs } 4711163953Srrs } 4712163953Srrs } 4713163953Srrs num_chunks++; 4714163953Srrs /* Save off the last place we got a control from */ 4715163953Srrs if (stcb != NULL) { 4716169420Srrs if (((netp != NULL) && (*netp != NULL)) || (ch->chunk_type == SCTP_ASCONF)) { 4717163953Srrs /* 4718163953Srrs * allow last_control to be NULL if 4719163953Srrs * ASCONF... ASCONF processing will find the 4720163953Srrs * right net later 4721163953Srrs */ 4722169420Srrs if ((netp != NULL) && (*netp != NULL)) 4723169420Srrs stcb->asoc.last_control_chunk_from = *netp; 4724163953Srrs } 4725163953Srrs } 4726163953Srrs#ifdef SCTP_AUDITING_ENABLED 4727163953Srrs sctp_audit_log(0xB0, ch->chunk_type); 4728163953Srrs#endif 4729163953Srrs 4730163953Srrs /* check to see if this chunk required auth, but isn't */ 4731179783Srrs if ((stcb != NULL) && 4732179783Srrs !SCTP_BASE_SYSCTL(sctp_auth_disable) && 4733179783Srrs sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) && 4734163953Srrs !stcb->asoc.authenticated) { 4735163953Srrs /* "silently" ignore */ 4736163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 4737163953Srrs goto next_chunk; 4738163953Srrs } 4739163953Srrs switch (ch->chunk_type) { 4740163953Srrs case SCTP_INITIATION: 4741169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT\n"); 4742229774Stuexen /* The INIT chunk must be the only chunk. */ 4743229774Stuexen if ((num_chunks > 1) || 4744229775Stuexen (length - *offset > (int)SCTP_SIZE32(chk_length))) { 4745229774Stuexen sctp_abort_association(inp, stcb, m, 4746237049Stuexen iphlen, sh, NULL, 4747237049Stuexen use_mflowid, mflowid, 4748237049Stuexen vrf_id, port); 4749163953Srrs *offset = length; 4750163953Srrs return (NULL); 4751163953Srrs } 4752229774Stuexen /* Honor our resource limit. */ 4753229774Stuexen if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) { 4754229774Stuexen struct mbuf *op_err; 4755229774Stuexen 4756229774Stuexen op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); 4757229774Stuexen sctp_abort_association(inp, stcb, m, 4758237049Stuexen iphlen, sh, op_err, 4759237049Stuexen use_mflowid, mflowid, 4760237049Stuexen vrf_id, port); 4761163953Srrs *offset = length; 4762163953Srrs return (NULL); 4763163953Srrs } 4764229774Stuexen sctp_handle_init(m, iphlen, *offset, sh, 4765229774Stuexen (struct sctp_init_chunk *)ch, inp, 4766237049Stuexen stcb, &abort_no_unlock, 4767237049Stuexen use_mflowid, mflowid, 4768237049Stuexen vrf_id, port); 4769163953Srrs *offset = length; 4770229774Stuexen if ((!abort_no_unlock) && (locked_tcb)) { 4771163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4772169378Srrs } 4773163953Srrs return (NULL); 4774163953Srrs break; 4775170642Srrs case SCTP_PAD_CHUNK: 4776170642Srrs break; 4777163953Srrs case SCTP_INITIATION_ACK: 4778169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n"); 4779163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 4780163953Srrs /* We are not interested anymore */ 4781163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 4782163953Srrs ; 4783163953Srrs } else { 4784208876Srrs if (locked_tcb != stcb) { 4785208876Srrs /* Very unlikely */ 4786163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4787169378Srrs } 4788163953Srrs *offset = length; 4789163953Srrs if (stcb) { 4790237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4791172090Srrs so = SCTP_INP_SO(inp); 4792172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 4793172090Srrs SCTP_TCB_UNLOCK(stcb); 4794172090Srrs SCTP_SOCKET_LOCK(so, 1); 4795172090Srrs SCTP_TCB_LOCK(stcb); 4796172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 4797172090Srrs#endif 4798171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27); 4799237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 4800172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 4801172090Srrs#endif 4802163953Srrs } 4803163953Srrs return (NULL); 4804163953Srrs } 4805163953Srrs } 4806229775Stuexen /* The INIT-ACK chunk must be the only chunk. */ 4807163953Srrs if ((num_chunks > 1) || 4808229775Stuexen (length - *offset > (int)SCTP_SIZE32(chk_length))) { 4809163953Srrs *offset = length; 4810169378Srrs if (locked_tcb) { 4811163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4812169378Srrs } 4813163953Srrs return (NULL); 4814163953Srrs } 4815169420Srrs if ((netp) && (*netp)) { 4816169420Srrs ret = sctp_handle_init_ack(m, iphlen, *offset, sh, 4817237049Stuexen (struct sctp_init_ack_chunk *)ch, 4818237049Stuexen stcb, *netp, 4819237049Stuexen &abort_no_unlock, 4820237049Stuexen use_mflowid, mflowid, 4821237049Stuexen vrf_id); 4822169420Srrs } else { 4823169420Srrs ret = -1; 4824169420Srrs } 4825229774Stuexen *offset = length; 4826229774Stuexen if (abort_no_unlock) { 4827229774Stuexen return (NULL); 4828229774Stuexen } 4829163953Srrs /* 4830163953Srrs * Special case, I must call the output routine to 4831163953Srrs * get the cookie echoed 4832163953Srrs */ 4833229774Stuexen if ((stcb != NULL) && (ret == 0)) { 4834172090Srrs sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 4835229774Stuexen } 4836169378Srrs if (locked_tcb) { 4837163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 4838169378Srrs } 4839163953Srrs return (NULL); 4840163953Srrs break; 4841163953Srrs case SCTP_SELECTIVE_ACK: 4842163953Srrs { 4843163953Srrs struct sctp_sack_chunk *sack; 4844163953Srrs int abort_now = 0; 4845163953Srrs uint32_t a_rwnd, cum_ack; 4846202526Stuexen uint16_t num_seg, num_dup; 4847202526Stuexen uint8_t flags; 4848202526Stuexen int offset_seg, offset_dup; 4849163953Srrs 4850211944Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n"); 4851211944Stuexen SCTP_STAT_INCR(sctps_recvsacks); 4852202526Stuexen if (stcb == NULL) { 4853202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing SACK chunk\n"); 4854202526Stuexen break; 4855169208Srrs } 4856202526Stuexen if (chk_length < sizeof(struct sctp_sack_chunk)) { 4857202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on SACK chunk, too small\n"); 4858202526Stuexen break; 4859202526Stuexen } 4860171990Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 4861171990Srrs /*- 4862171990Srrs * If we have sent a shutdown-ack, we will pay no 4863171990Srrs * attention to a sack sent in to us since 4864171990Srrs * we don't care anymore. 4865171990Srrs */ 4866184883Srrs break; 4867171990Srrs } 4868163953Srrs sack = (struct sctp_sack_chunk *)ch; 4869202526Stuexen flags = ch->chunk_flags; 4870163953Srrs cum_ack = ntohl(sack->sack.cum_tsn_ack); 4871163953Srrs num_seg = ntohs(sack->sack.num_gap_ack_blks); 4872202526Stuexen num_dup = ntohs(sack->sack.num_dup_tsns); 4873163953Srrs a_rwnd = (uint32_t) ntohl(sack->sack.a_rwnd); 4874202526Stuexen if (sizeof(struct sctp_sack_chunk) + 4875202526Stuexen num_seg * sizeof(struct sctp_gap_ack_block) + 4876202526Stuexen num_dup * sizeof(uint32_t) != chk_length) { 4877202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of SACK chunk\n"); 4878202526Stuexen break; 4879202526Stuexen } 4880202526Stuexen offset_seg = *offset + sizeof(struct sctp_sack_chunk); 4881202526Stuexen offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 4882170606Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 4883202526Stuexen cum_ack, num_seg, a_rwnd); 4884163953Srrs stcb->asoc.seen_a_sack_this_pkt = 1; 4885163953Srrs if ((stcb->asoc.pr_sctp_cnt == 0) && 4886163953Srrs (num_seg == 0) && 4887216825Stuexen SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 4888163953Srrs (stcb->asoc.saw_sack_with_frags == 0) && 4889216188Stuexen (stcb->asoc.saw_sack_with_nr_frags == 0) && 4890163953Srrs (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) 4891163953Srrs ) { 4892163953Srrs /* 4893163953Srrs * We have a SIMPLE sack having no 4894163953Srrs * prior segments and data on sent 4895163953Srrs * queue to be acked.. Use the 4896163953Srrs * faster path sack processing. We 4897163953Srrs * also allow window update sacks 4898163953Srrs * with no missing segments to go 4899163953Srrs * this way too. 4900163953Srrs */ 4901218186Srrs sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now, ecne_seen); 4902163953Srrs } else { 4903169420Srrs if (netp && *netp) 4904228653Stuexen sctp_handle_sack(m, offset_seg, offset_dup, stcb, 4905202526Stuexen num_seg, 0, num_dup, &abort_now, flags, 4906218186Srrs cum_ack, a_rwnd, ecne_seen); 4907163953Srrs } 4908202526Stuexen if (abort_now) { 4909202526Stuexen /* ABORT signal from sack processing */ 4910202526Stuexen *offset = length; 4911202526Stuexen return (NULL); 4912202526Stuexen } 4913185694Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 4914185694Srrs TAILQ_EMPTY(&stcb->asoc.sent_queue) && 4915185694Srrs (stcb->asoc.stream_queue_cnt == 0)) { 4916185694Srrs sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 4917185694Srrs } 4918163953Srrs } 4919163953Srrs break; 4920185694Srrs /* 4921185694Srrs * EY - nr_sack: If the received chunk is an 4922185694Srrs * nr_sack chunk 4923185694Srrs */ 4924185694Srrs case SCTP_NR_SELECTIVE_ACK: 4925185694Srrs { 4926185694Srrs struct sctp_nr_sack_chunk *nr_sack; 4927185694Srrs int abort_now = 0; 4928185694Srrs uint32_t a_rwnd, cum_ack; 4929202526Stuexen uint16_t num_seg, num_nr_seg, num_dup; 4930202526Stuexen uint8_t flags; 4931202526Stuexen int offset_seg, offset_dup; 4932185694Srrs 4933211944Stuexen SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n"); 4934211944Stuexen SCTP_STAT_INCR(sctps_recvsacks); 4935212225Srrs if (stcb == NULL) { 4936212225Srrs SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing NR-SACK chunk\n"); 4937212225Srrs break; 4938212225Srrs } 4939211944Stuexen if ((stcb->asoc.sctp_nr_sack_on_off == 0) || 4940211944Stuexen (stcb->asoc.peer_supports_nr_sack == 0)) { 4941185694Srrs goto unknown_chunk; 4942185694Srrs } 4943202526Stuexen if (chk_length < sizeof(struct sctp_nr_sack_chunk)) { 4944202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on NR-SACK chunk, too small\n"); 4945202526Stuexen break; 4946202526Stuexen } 4947185694Srrs if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 4948185694Srrs /*- 4949185694Srrs * If we have sent a shutdown-ack, we will pay no 4950185694Srrs * attention to a sack sent in to us since 4951185694Srrs * we don't care anymore. 4952185694Srrs */ 4953202526Stuexen break; 4954185694Srrs } 4955185694Srrs nr_sack = (struct sctp_nr_sack_chunk *)ch; 4956202526Stuexen flags = ch->chunk_flags; 4957185694Srrs cum_ack = ntohl(nr_sack->nr_sack.cum_tsn_ack); 4958185694Srrs num_seg = ntohs(nr_sack->nr_sack.num_gap_ack_blks); 4959185694Srrs num_nr_seg = ntohs(nr_sack->nr_sack.num_nr_gap_ack_blks); 4960202526Stuexen num_dup = ntohs(nr_sack->nr_sack.num_dup_tsns); 4961185694Srrs a_rwnd = (uint32_t) ntohl(nr_sack->nr_sack.a_rwnd); 4962202526Stuexen if (sizeof(struct sctp_nr_sack_chunk) + 4963202526Stuexen (num_seg + num_nr_seg) * sizeof(struct sctp_gap_ack_block) + 4964202526Stuexen num_dup * sizeof(uint32_t) != chk_length) { 4965202526Stuexen SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of NR_SACK chunk\n"); 4966202526Stuexen break; 4967202526Stuexen } 4968202526Stuexen offset_seg = *offset + sizeof(struct sctp_nr_sack_chunk); 4969202526Stuexen offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 4970185694Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 4971202526Stuexen cum_ack, num_seg, a_rwnd); 4972185694Srrs stcb->asoc.seen_a_sack_this_pkt = 1; 4973185694Srrs if ((stcb->asoc.pr_sctp_cnt == 0) && 4974202526Stuexen (num_seg == 0) && (num_nr_seg == 0) && 4975216825Stuexen SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 4976185694Srrs (stcb->asoc.saw_sack_with_frags == 0) && 4977216188Stuexen (stcb->asoc.saw_sack_with_nr_frags == 0) && 4978202526Stuexen (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 4979185694Srrs /* 4980185694Srrs * We have a SIMPLE sack having no 4981185694Srrs * prior segments and data on sent 4982202526Stuexen * queue to be acked. Use the faster 4983202526Stuexen * path sack processing. We also 4984202526Stuexen * allow window update sacks with no 4985202526Stuexen * missing segments to go this way 4986202526Stuexen * too. 4987185694Srrs */ 4988218129Srrs sctp_express_handle_sack(stcb, cum_ack, a_rwnd, 4989218186Srrs &abort_now, ecne_seen); 4990185694Srrs } else { 4991185694Srrs if (netp && *netp) 4992228653Stuexen sctp_handle_sack(m, offset_seg, offset_dup, stcb, 4993202526Stuexen num_seg, num_nr_seg, num_dup, &abort_now, flags, 4994218186Srrs cum_ack, a_rwnd, ecne_seen); 4995185694Srrs } 4996202526Stuexen if (abort_now) { 4997202526Stuexen /* ABORT signal from sack processing */ 4998202526Stuexen *offset = length; 4999202526Stuexen return (NULL); 5000202526Stuexen } 5001185694Srrs if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 5002185694Srrs TAILQ_EMPTY(&stcb->asoc.sent_queue) && 5003185694Srrs (stcb->asoc.stream_queue_cnt == 0)) { 5004185694Srrs sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 5005185694Srrs } 5006185694Srrs } 5007185694Srrs break; 5008185694Srrs 5009163953Srrs case SCTP_HEARTBEAT_REQUEST: 5010169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT\n"); 5011169420Srrs if ((stcb) && netp && *netp) { 5012169420Srrs SCTP_STAT_INCR(sctps_recvheartbeat); 5013169420Srrs sctp_send_heartbeat_ack(stcb, m, *offset, 5014169420Srrs chk_length, *netp); 5015169420Srrs 5016169420Srrs /* He's alive so give him credit */ 5017179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5018171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5019171943Srrs stcb->asoc.overall_error_count, 5020171943Srrs 0, 5021171943Srrs SCTP_FROM_SCTP_INPUT, 5022171943Srrs __LINE__); 5023171943Srrs } 5024169420Srrs stcb->asoc.overall_error_count = 0; 5025163953Srrs } 5026163953Srrs break; 5027163953Srrs case SCTP_HEARTBEAT_ACK: 5028169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT-ACK\n"); 5029169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_heartbeat_chunk))) { 5030169208Srrs /* Its not ours */ 5031169352Srrs *offset = length; 5032169378Srrs if (locked_tcb) { 5033169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5034169378Srrs } 5035169208Srrs return (NULL); 5036169208Srrs } 5037163953Srrs /* He's alive so give him credit */ 5038179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5039171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5040171943Srrs stcb->asoc.overall_error_count, 5041171943Srrs 0, 5042171943Srrs SCTP_FROM_SCTP_INPUT, 5043171943Srrs __LINE__); 5044171943Srrs } 5045163953Srrs stcb->asoc.overall_error_count = 0; 5046163953Srrs SCTP_STAT_INCR(sctps_recvheartbeatack); 5047169420Srrs if (netp && *netp) 5048169420Srrs sctp_handle_heartbeat_ack((struct sctp_heartbeat_chunk *)ch, 5049169420Srrs stcb, *netp); 5050163953Srrs break; 5051163953Srrs case SCTP_ABORT_ASSOCIATION: 5052170091Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT, stcb %p\n", 5053170091Srrs stcb); 5054169420Srrs if ((stcb) && netp && *netp) 5055169420Srrs sctp_handle_abort((struct sctp_abort_chunk *)ch, 5056169420Srrs stcb, *netp); 5057163953Srrs *offset = length; 5058163953Srrs return (NULL); 5059163953Srrs break; 5060163953Srrs case SCTP_SHUTDOWN: 5061170091Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN, stcb %p\n", 5062170091Srrs stcb); 5063169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_shutdown_chunk))) { 5064169208Srrs *offset = length; 5065169378Srrs if (locked_tcb) { 5066169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5067169378Srrs } 5068169208Srrs return (NULL); 5069169420Srrs } 5070169420Srrs if (netp && *netp) { 5071163953Srrs int abort_flag = 0; 5072163953Srrs 5073163953Srrs sctp_handle_shutdown((struct sctp_shutdown_chunk *)ch, 5074163953Srrs stcb, *netp, &abort_flag); 5075163953Srrs if (abort_flag) { 5076163953Srrs *offset = length; 5077163953Srrs return (NULL); 5078163953Srrs } 5079163953Srrs } 5080163953Srrs break; 5081163953Srrs case SCTP_SHUTDOWN_ACK: 5082170091Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", stcb); 5083169420Srrs if ((stcb) && (netp) && (*netp)) 5084169420Srrs sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp); 5085163953Srrs *offset = length; 5086163953Srrs return (NULL); 5087163953Srrs break; 5088169420Srrs 5089163953Srrs case SCTP_OPERATION_ERROR: 5090169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_OP-ERR\n"); 5091169420Srrs if ((stcb) && netp && *netp && sctp_handle_error(ch, stcb, *netp) < 0) { 5092163953Srrs *offset = length; 5093163953Srrs return (NULL); 5094163953Srrs } 5095163953Srrs break; 5096163953Srrs case SCTP_COOKIE_ECHO: 5097169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 5098170091Srrs "SCTP_COOKIE-ECHO, stcb %p\n", stcb); 5099163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 5100163953Srrs ; 5101163953Srrs } else { 5102169420Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5103163953Srrs /* We are not interested anymore */ 5104208878Srrs abend: 5105208853Srrs if (stcb) { 5106208853Srrs SCTP_TCB_UNLOCK(stcb); 5107208853Srrs } 5108163953Srrs *offset = length; 5109163953Srrs return (NULL); 5110163953Srrs } 5111163953Srrs } 5112163953Srrs /* 5113163953Srrs * First are we accepting? We do this again here 5114207924Srrs * since it is possible that a previous endpoint WAS 5115207924Srrs * listening responded to a INIT-ACK and then 5116163953Srrs * closed. We opened and bound.. and are now no 5117163953Srrs * longer listening. 5118163953Srrs */ 5119172703Srrs 5120172703Srrs if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) { 5121172703Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 5122179783Srrs (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) { 5123229774Stuexen struct mbuf *op_err; 5124163953Srrs 5125229774Stuexen op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); 5126172703Srrs sctp_abort_association(inp, stcb, m, 5127237049Stuexen iphlen, sh, op_err, 5128237049Stuexen use_mflowid, mflowid, 5129237049Stuexen vrf_id, port); 5130163953Srrs } 5131172703Srrs *offset = length; 5132172703Srrs return (NULL); 5133172703Srrs } else { 5134163953Srrs struct mbuf *ret_buf; 5135165220Srrs struct sctp_inpcb *linp; 5136163953Srrs 5137169420Srrs if (stcb) { 5138165220Srrs linp = NULL; 5139169420Srrs } else { 5140165220Srrs linp = inp; 5141169420Srrs } 5142165220Srrs 5143169420Srrs if (linp) { 5144165220Srrs SCTP_ASOC_CREATE_LOCK(linp); 5145208878Srrs if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 5146208878Srrs (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 5147208878Srrs SCTP_ASOC_CREATE_UNLOCK(linp); 5148208878Srrs goto abend; 5149208878Srrs } 5150169420Srrs } 5151169420Srrs if (netp) { 5152169420Srrs ret_buf = 5153169420Srrs sctp_handle_cookie_echo(m, iphlen, 5154169420Srrs *offset, sh, 5155169420Srrs (struct sctp_cookie_echo_chunk *)ch, 5156169420Srrs &inp, &stcb, netp, 5157169420Srrs auth_skipped, 5158169420Srrs auth_offset, 5159169420Srrs auth_len, 5160169420Srrs &locked_tcb, 5161237049Stuexen use_mflowid, 5162237049Stuexen mflowid, 5163179157Srrs vrf_id, 5164179157Srrs port); 5165169420Srrs } else { 5166169420Srrs ret_buf = NULL; 5167169420Srrs } 5168169420Srrs if (linp) { 5169165220Srrs SCTP_ASOC_CREATE_UNLOCK(linp); 5170169420Srrs } 5171163953Srrs if (ret_buf == NULL) { 5172163953Srrs if (locked_tcb) { 5173163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5174163953Srrs } 5175169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, 5176169420Srrs "GAK, null buffer\n"); 5177163953Srrs *offset = length; 5178163953Srrs return (NULL); 5179163953Srrs } 5180163953Srrs /* if AUTH skipped, see if it verified... */ 5181163953Srrs if (auth_skipped) { 5182163953Srrs got_auth = 1; 5183163953Srrs auth_skipped = 0; 5184163953Srrs } 5185163953Srrs if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) { 5186163953Srrs /* 5187163953Srrs * Restart the timer if we have 5188163953Srrs * pending data 5189163953Srrs */ 5190163953Srrs struct sctp_tmit_chunk *chk; 5191163953Srrs 5192163953Srrs chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 5193216822Stuexen sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 5194163953Srrs } 5195163953Srrs } 5196163953Srrs break; 5197163953Srrs case SCTP_COOKIE_ACK: 5198170091Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", stcb); 5199169420Srrs if ((stcb == NULL) || chk_length != sizeof(struct sctp_cookie_ack_chunk)) { 5200169378Srrs if (locked_tcb) { 5201169352Srrs SCTP_TCB_UNLOCK(locked_tcb); 5202169378Srrs } 5203169352Srrs return (NULL); 5204169352Srrs } 5205163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5206163953Srrs /* We are not interested anymore */ 5207163953Srrs if ((stcb) && (stcb->asoc.total_output_queue_size)) { 5208163953Srrs ; 5209169420Srrs } else if (stcb) { 5210237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5211172090Srrs so = SCTP_INP_SO(inp); 5212172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5213172090Srrs SCTP_TCB_UNLOCK(stcb); 5214172090Srrs SCTP_SOCKET_LOCK(so, 1); 5215172090Srrs SCTP_TCB_LOCK(stcb); 5216172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 5217172090Srrs#endif 5218171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27); 5219237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5220172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 5221172090Srrs#endif 5222163953Srrs *offset = length; 5223163953Srrs return (NULL); 5224163953Srrs } 5225163953Srrs } 5226163953Srrs /* He's alive so give him credit */ 5227169420Srrs if ((stcb) && netp && *netp) { 5228179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5229171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5230171943Srrs stcb->asoc.overall_error_count, 5231171943Srrs 0, 5232171943Srrs SCTP_FROM_SCTP_INPUT, 5233171943Srrs __LINE__); 5234171943Srrs } 5235169378Srrs stcb->asoc.overall_error_count = 0; 5236169378Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, *netp); 5237169378Srrs } 5238163953Srrs break; 5239163953Srrs case SCTP_ECN_ECHO: 5240169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-ECHO\n"); 5241163953Srrs /* He's alive so give him credit */ 5242169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_ecne_chunk))) { 5243169208Srrs /* Its not ours */ 5244169378Srrs if (locked_tcb) { 5245169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5246169378Srrs } 5247169208Srrs *offset = length; 5248169208Srrs return (NULL); 5249169208Srrs } 5250169378Srrs if (stcb) { 5251179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5252171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5253171943Srrs stcb->asoc.overall_error_count, 5254171943Srrs 0, 5255171943Srrs SCTP_FROM_SCTP_INPUT, 5256171943Srrs __LINE__); 5257171943Srrs } 5258169378Srrs stcb->asoc.overall_error_count = 0; 5259169378Srrs sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch, 5260169378Srrs stcb); 5261218186Srrs ecne_seen = 1; 5262169378Srrs } 5263163953Srrs break; 5264163953Srrs case SCTP_ECN_CWR: 5265169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-CWR\n"); 5266163953Srrs /* He's alive so give him credit */ 5267169420Srrs if ((stcb == NULL) || (chk_length != sizeof(struct sctp_cwr_chunk))) { 5268169208Srrs /* Its not ours */ 5269169378Srrs if (locked_tcb) { 5270169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5271169378Srrs } 5272169208Srrs *offset = length; 5273169208Srrs return (NULL); 5274169208Srrs } 5275169378Srrs if (stcb) { 5276179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5277171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5278171943Srrs stcb->asoc.overall_error_count, 5279171943Srrs 0, 5280171943Srrs SCTP_FROM_SCTP_INPUT, 5281171943Srrs __LINE__); 5282171943Srrs } 5283169378Srrs stcb->asoc.overall_error_count = 0; 5284218072Srrs sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb, *netp); 5285169378Srrs } 5286163953Srrs break; 5287163953Srrs case SCTP_SHUTDOWN_COMPLETE: 5288170091Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", stcb); 5289163953Srrs /* must be first and only chunk */ 5290163953Srrs if ((num_chunks > 1) || 5291170140Srrs (length - *offset > (int)SCTP_SIZE32(chk_length))) { 5292163953Srrs *offset = length; 5293169378Srrs if (locked_tcb) { 5294163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5295169378Srrs } 5296163953Srrs return (NULL); 5297163953Srrs } 5298169420Srrs if ((stcb) && netp && *netp) { 5299169378Srrs sctp_handle_shutdown_complete((struct sctp_shutdown_complete_chunk *)ch, 5300169378Srrs stcb, *netp); 5301169378Srrs } 5302163953Srrs *offset = length; 5303163953Srrs return (NULL); 5304163953Srrs break; 5305163953Srrs case SCTP_ASCONF: 5306169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n"); 5307163953Srrs /* He's alive so give him credit */ 5308169378Srrs if (stcb) { 5309179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5310171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5311171943Srrs stcb->asoc.overall_error_count, 5312171943Srrs 0, 5313171943Srrs SCTP_FROM_SCTP_INPUT, 5314171943Srrs __LINE__); 5315171943Srrs } 5316169378Srrs stcb->asoc.overall_error_count = 0; 5317169378Srrs sctp_handle_asconf(m, *offset, 5318171990Srrs (struct sctp_asconf_chunk *)ch, stcb, asconf_cnt == 0); 5319171990Srrs asconf_cnt++; 5320169378Srrs } 5321163953Srrs break; 5322163953Srrs case SCTP_ASCONF_ACK: 5323169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF-ACK\n"); 5324169208Srrs if (chk_length < sizeof(struct sctp_asconf_ack_chunk)) { 5325169208Srrs /* Its not ours */ 5326169378Srrs if (locked_tcb) { 5327169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5328169378Srrs } 5329169208Srrs *offset = length; 5330169208Srrs return (NULL); 5331169208Srrs } 5332169420Srrs if ((stcb) && netp && *netp) { 5333169378Srrs /* He's alive so give him credit */ 5334179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5335171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5336171943Srrs stcb->asoc.overall_error_count, 5337171943Srrs 0, 5338171943Srrs SCTP_FROM_SCTP_INPUT, 5339171943Srrs __LINE__); 5340171943Srrs } 5341169378Srrs stcb->asoc.overall_error_count = 0; 5342169378Srrs sctp_handle_asconf_ack(m, *offset, 5343172190Srrs (struct sctp_asconf_ack_chunk *)ch, stcb, *netp, &abort_no_unlock); 5344172190Srrs if (abort_no_unlock) 5345172190Srrs return (NULL); 5346169378Srrs } 5347163953Srrs break; 5348163953Srrs case SCTP_FORWARD_CUM_TSN: 5349169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_FWD-TSN\n"); 5350169208Srrs if (chk_length < sizeof(struct sctp_forward_tsn_chunk)) { 5351169208Srrs /* Its not ours */ 5352169378Srrs if (locked_tcb) { 5353169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5354169378Srrs } 5355169208Srrs *offset = length; 5356169208Srrs return (NULL); 5357169208Srrs } 5358163953Srrs /* He's alive so give him credit */ 5359169378Srrs if (stcb) { 5360163953Srrs int abort_flag = 0; 5361163953Srrs 5362163953Srrs stcb->asoc.overall_error_count = 0; 5363179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5364171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5365171943Srrs stcb->asoc.overall_error_count, 5366171943Srrs 0, 5367171943Srrs SCTP_FROM_SCTP_INPUT, 5368171943Srrs __LINE__); 5369171943Srrs } 5370163953Srrs *fwd_tsn_seen = 1; 5371163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5372163953Srrs /* We are not interested anymore */ 5373237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5374172090Srrs so = SCTP_INP_SO(inp); 5375172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5376172090Srrs SCTP_TCB_UNLOCK(stcb); 5377172090Srrs SCTP_SOCKET_LOCK(so, 1); 5378172090Srrs SCTP_TCB_LOCK(stcb); 5379172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 5380172090Srrs#endif 5381171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_29); 5382237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5383172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 5384172090Srrs#endif 5385163953Srrs *offset = length; 5386163953Srrs return (NULL); 5387163953Srrs } 5388163953Srrs sctp_handle_forward_tsn(stcb, 5389170992Srrs (struct sctp_forward_tsn_chunk *)ch, &abort_flag, m, *offset); 5390163953Srrs if (abort_flag) { 5391163953Srrs *offset = length; 5392163953Srrs return (NULL); 5393163953Srrs } else { 5394179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5395171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5396171943Srrs stcb->asoc.overall_error_count, 5397171943Srrs 0, 5398171943Srrs SCTP_FROM_SCTP_INPUT, 5399171943Srrs __LINE__); 5400171943Srrs } 5401163953Srrs stcb->asoc.overall_error_count = 0; 5402163953Srrs } 5403163953Srrs 5404163953Srrs } 5405163953Srrs break; 5406163953Srrs case SCTP_STREAM_RESET: 5407169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_STREAM_RESET\n"); 5408169420Srrs if (((stcb == NULL) || (ch == NULL) || (chk_length < sizeof(struct sctp_stream_reset_tsn_req)))) { 5409169208Srrs /* Its not ours */ 5410169378Srrs if (locked_tcb) { 5411169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5412169378Srrs } 5413169208Srrs *offset = length; 5414169208Srrs return (NULL); 5415169208Srrs } 5416163953Srrs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 5417163953Srrs /* We are not interested anymore */ 5418237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5419172090Srrs so = SCTP_INP_SO(inp); 5420172090Srrs atomic_add_int(&stcb->asoc.refcnt, 1); 5421172090Srrs SCTP_TCB_UNLOCK(stcb); 5422172090Srrs SCTP_SOCKET_LOCK(so, 1); 5423172090Srrs SCTP_TCB_LOCK(stcb); 5424172090Srrs atomic_subtract_int(&stcb->asoc.refcnt, 1); 5425172090Srrs#endif 5426171943Srrs (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_30); 5427237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 5428172090Srrs SCTP_SOCKET_UNLOCK(so, 1); 5429172090Srrs#endif 5430163953Srrs *offset = length; 5431163953Srrs return (NULL); 5432163953Srrs } 5433169420Srrs if (stcb->asoc.peer_supports_strreset == 0) { 5434169420Srrs /* 5435169420Srrs * hmm, peer should have announced this, but 5436169420Srrs * we will turn it on since he is sending us 5437169420Srrs * a stream reset. 5438169420Srrs */ 5439169420Srrs stcb->asoc.peer_supports_strreset = 1; 5440163953Srrs } 5441170992Srrs if (sctp_handle_stream_reset(stcb, m, *offset, (struct sctp_stream_reset_out_req *)ch)) { 5442169420Srrs /* stop processing */ 5443169420Srrs *offset = length; 5444169420Srrs return (NULL); 5445169420Srrs } 5446163953Srrs break; 5447163953Srrs case SCTP_PACKET_DROPPED: 5448169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_PACKET_DROPPED\n"); 5449163953Srrs /* re-get it all please */ 5450169208Srrs if (chk_length < sizeof(struct sctp_pktdrop_chunk)) { 5451169208Srrs /* Its not ours */ 5452169378Srrs if (locked_tcb) { 5453169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5454169378Srrs } 5455169208Srrs *offset = length; 5456169208Srrs return (NULL); 5457169208Srrs } 5458169420Srrs if (ch && (stcb) && netp && (*netp)) { 5459169378Srrs sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch, 5460170781Srrs stcb, *netp, 5461170781Srrs min(chk_length, (sizeof(chunk_buf) - 4))); 5462170781Srrs 5463169378Srrs } 5464163953Srrs break; 5465163953Srrs 5466163953Srrs case SCTP_AUTHENTICATION: 5467169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n"); 5468179783Srrs if (SCTP_BASE_SYSCTL(sctp_auth_disable)) 5469163953Srrs goto unknown_chunk; 5470163953Srrs 5471163953Srrs if (stcb == NULL) { 5472163953Srrs /* save the first AUTH for later processing */ 5473163953Srrs if (auth_skipped == 0) { 5474163953Srrs auth_offset = *offset; 5475163953Srrs auth_len = chk_length; 5476163953Srrs auth_skipped = 1; 5477163953Srrs } 5478163953Srrs /* skip this chunk (temporarily) */ 5479163953Srrs goto next_chunk; 5480163953Srrs } 5481169208Srrs if ((chk_length < (sizeof(struct sctp_auth_chunk))) || 5482169420Srrs (chk_length > (sizeof(struct sctp_auth_chunk) + 5483169420Srrs SCTP_AUTH_DIGEST_LEN_MAX))) { 5484169208Srrs /* Its not ours */ 5485169378Srrs if (locked_tcb) { 5486169295Srrs SCTP_TCB_UNLOCK(locked_tcb); 5487169378Srrs } 5488169208Srrs *offset = length; 5489169208Srrs return (NULL); 5490169208Srrs } 5491163953Srrs if (got_auth == 1) { 5492163953Srrs /* skip this chunk... it's already auth'd */ 5493163953Srrs goto next_chunk; 5494163953Srrs } 5495163953Srrs got_auth = 1; 5496169420Srrs if ((ch == NULL) || sctp_handle_auth(stcb, (struct sctp_auth_chunk *)ch, 5497163953Srrs m, *offset)) { 5498163953Srrs /* auth HMAC failed so dump the packet */ 5499163953Srrs *offset = length; 5500163953Srrs return (stcb); 5501163953Srrs } else { 5502163953Srrs /* remaining chunks are HMAC checked */ 5503163953Srrs stcb->asoc.authenticated = 1; 5504163953Srrs } 5505163953Srrs break; 5506163953Srrs 5507163953Srrs default: 5508163953Srrs unknown_chunk: 5509163953Srrs /* it's an unknown chunk! */ 5510163953Srrs if ((ch->chunk_type & 0x40) && (stcb != NULL)) { 5511163953Srrs struct mbuf *mm; 5512163953Srrs struct sctp_paramhdr *phd; 5513163953Srrs 5514163953Srrs mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 5515165647Srrs 0, M_DONTWAIT, 1, MT_DATA); 5516163953Srrs if (mm) { 5517163953Srrs phd = mtod(mm, struct sctp_paramhdr *); 5518163953Srrs /* 5519163953Srrs * We cheat and use param type since 5520163953Srrs * we did not bother to define a 5521163953Srrs * error cause struct. They are the 5522163953Srrs * same basic format with different 5523163953Srrs * names. 5524163953Srrs */ 5525163953Srrs phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK); 5526163953Srrs phd->param_length = htons(chk_length + sizeof(*phd)); 5527165647Srrs SCTP_BUF_LEN(mm) = sizeof(*phd); 5528234459Stuexen SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, M_DONTWAIT); 5529165647Srrs if (SCTP_BUF_NEXT(mm)) { 5530234459Stuexen if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL)) { 5531234459Stuexen sctp_m_freem(mm); 5532234459Stuexen } else { 5533178202Srrs#ifdef SCTP_MBUF_LOGGING 5534234459Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 5535234459Stuexen struct mbuf *mat; 5536178202Srrs 5537234461Stuexen for (mat = SCTP_BUF_NEXT(mm); mat; mat = SCTP_BUF_NEXT(mat)) { 5538234459Stuexen if (SCTP_BUF_IS_EXTENDED(mat)) { 5539234459Stuexen sctp_log_mb(mat, SCTP_MBUF_ICOPY); 5540234459Stuexen } 5541178202Srrs } 5542178202Srrs } 5543234459Stuexen#endif 5544234459Stuexen sctp_queue_op_err(stcb, mm); 5545178202Srrs } 5546163953Srrs } else { 5547163953Srrs sctp_m_freem(mm); 5548163953Srrs } 5549163953Srrs } 5550163953Srrs } 5551163953Srrs if ((ch->chunk_type & 0x80) == 0) { 5552163953Srrs /* discard this packet */ 5553163953Srrs *offset = length; 5554163953Srrs return (stcb); 5555163953Srrs } /* else skip this bad chunk and continue... */ 5556163953Srrs break; 5557163953Srrs } /* switch (ch->chunk_type) */ 5558163953Srrs 5559163953Srrs 5560163953Srrsnext_chunk: 5561163953Srrs /* get the next chunk */ 5562163953Srrs *offset += SCTP_SIZE32(chk_length); 5563163953Srrs if (*offset >= length) { 5564163953Srrs /* no more data left in the mbuf chain */ 5565163953Srrs break; 5566163953Srrs } 5567163953Srrs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 5568163953Srrs sizeof(struct sctp_chunkhdr), chunk_buf); 5569163953Srrs if (ch == NULL) { 5570169378Srrs if (locked_tcb) { 5571163953Srrs SCTP_TCB_UNLOCK(locked_tcb); 5572169378Srrs } 5573163953Srrs *offset = length; 5574163953Srrs return (NULL); 5575163953Srrs } 5576163953Srrs } /* while */ 5577171990Srrs 5578171990Srrs if (asconf_cnt > 0 && stcb != NULL) { 5579171990Srrs sctp_send_asconf_ack(stcb); 5580171990Srrs } 5581163953Srrs return (stcb); 5582163953Srrs} 5583163953Srrs 5584163953Srrs 5585171440Srrs#ifdef INVARIANTS 5586208853Srrs#ifdef __GNUC__ 5587208853Srrs__attribute__((noinline)) 5588208853Srrs#endif 5589208853Srrs void 5590208853Srrs sctp_validate_no_locks(struct sctp_inpcb *inp) 5591171440Srrs{ 5592208853Srrs struct sctp_tcb *lstcb; 5593171440Srrs 5594208853Srrs LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) { 5595208853Srrs if (mtx_owned(&lstcb->tcb_mtx)) { 5596171440Srrs panic("Own lock on stcb at return from input"); 5597171440Srrs } 5598171440Srrs } 5599208876Srrs if (mtx_owned(&inp->inp_create_mtx)) { 5600208876Srrs panic("Own create lock on inp"); 5601208876Srrs } 5602208876Srrs if (mtx_owned(&inp->inp_mtx)) { 5603208876Srrs panic("Own inp lock on inp"); 5604208876Srrs } 5605171440Srrs} 5606171440Srrs 5607171440Srrs#endif 5608171440Srrs 5609163953Srrs/* 5610163953Srrs * common input chunk processing (v4 and v6) 5611163953Srrs */ 5612169378Srrsvoid 5613163953Srrssctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, 5614163953Srrs int length, struct sctphdr *sh, struct sctp_chunkhdr *ch, 5615237049Stuexen struct sctp_inpcb *inp, struct sctp_tcb *stcb, 5616237049Stuexen struct sctp_nets *net, uint8_t ecn_bits, 5617237049Stuexen uint8_t use_mflowid, uint32_t mflowid, 5618237049Stuexen uint32_t vrf_id, uint16_t port) 5619163953Srrs{ 5620163953Srrs /* 5621163953Srrs * Control chunk processing 5622163953Srrs */ 5623163953Srrs uint32_t high_tsn; 5624163953Srrs int fwd_tsn_seen = 0, data_processed = 0; 5625163953Srrs struct mbuf *m = *mm; 5626163953Srrs int un_sent; 5627218129Srrs int cnt_ctrl_ready = 0; 5628163953Srrs 5629163953Srrs SCTP_STAT_INCR(sctps_recvdatagrams); 5630163953Srrs#ifdef SCTP_AUDITING_ENABLED 5631163953Srrs sctp_audit_log(0xE0, 1); 5632163953Srrs sctp_auditing(0, inp, stcb, net); 5633163953Srrs#endif 5634163953Srrs 5635179783Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n", 5636179783Srrs m, iphlen, offset, length, stcb); 5637163953Srrs if (stcb) { 5638163953Srrs /* always clear this before beginning a packet */ 5639163953Srrs stcb->asoc.authenticated = 0; 5640163953Srrs stcb->asoc.seen_a_sack_this_pkt = 0; 5641171990Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "stcb:%p state:%x\n", 5642171990Srrs stcb, stcb->asoc.state); 5643171990Srrs 5644171943Srrs if ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) || 5645171943Srrs (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) { 5646171745Srrs /*- 5647171745Srrs * If we hit here, we had a ref count 5648171745Srrs * up when the assoc was aborted and the 5649171745Srrs * timer is clearing out the assoc, we should 5650171745Srrs * NOT respond to any packet.. its OOTB. 5651171745Srrs */ 5652171745Srrs SCTP_TCB_UNLOCK(stcb); 5653236450Stuexen sctp_handle_ootb(m, iphlen, offset, sh, inp, 5654237049Stuexen use_mflowid, mflowid, 5655179157Srrs vrf_id, port); 5656171745Srrs goto out_now; 5657171745Srrs } 5658163953Srrs } 5659163953Srrs if (IS_SCTP_CONTROL(ch)) { 5660163953Srrs /* process the control portion of the SCTP packet */ 5661169655Srrs /* sa_ignore NO_NULL_CHK */ 5662163953Srrs stcb = sctp_process_control(m, iphlen, &offset, length, sh, ch, 5663237049Stuexen inp, stcb, &net, &fwd_tsn_seen, 5664237049Stuexen use_mflowid, mflowid, 5665237049Stuexen vrf_id, port); 5666163953Srrs if (stcb) { 5667163953Srrs /* 5668163953Srrs * This covers us if the cookie-echo was there and 5669163953Srrs * it changes our INP. 5670163953Srrs */ 5671163953Srrs inp = stcb->sctp_ep; 5672179783Srrs if ((net) && (port)) { 5673179783Srrs if (net->port == 0) { 5674228653Stuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 5675179783Srrs } 5676179783Srrs net->port = port; 5677179783Srrs } 5678163953Srrs } 5679163953Srrs } else { 5680163953Srrs /* 5681163953Srrs * no control chunks, so pre-process DATA chunks (these 5682163953Srrs * checks are taken care of by control processing) 5683163953Srrs */ 5684163953Srrs 5685163953Srrs /* 5686163953Srrs * if DATA only packet, and auth is required, then punt... 5687163953Srrs * can't have authenticated without any AUTH (control) 5688163953Srrs * chunks 5689163953Srrs */ 5690179783Srrs if ((stcb != NULL) && 5691179783Srrs !SCTP_BASE_SYSCTL(sctp_auth_disable) && 5692179783Srrs sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) { 5693163953Srrs /* "silently" ignore */ 5694163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 5695163953Srrs SCTP_TCB_UNLOCK(stcb); 5696171440Srrs goto out_now; 5697163953Srrs } 5698163953Srrs if (stcb == NULL) { 5699163953Srrs /* out of the blue DATA chunk */ 5700236450Stuexen sctp_handle_ootb(m, iphlen, offset, sh, inp, 5701237049Stuexen use_mflowid, mflowid, 5702179157Srrs vrf_id, port); 5703171440Srrs goto out_now; 5704163953Srrs } 5705163953Srrs if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) { 5706163953Srrs /* v_tag mismatch! */ 5707163953Srrs SCTP_STAT_INCR(sctps_badvtag); 5708163953Srrs SCTP_TCB_UNLOCK(stcb); 5709171440Srrs goto out_now; 5710163953Srrs } 5711163953Srrs } 5712163953Srrs 5713163953Srrs if (stcb == NULL) { 5714163953Srrs /* 5715163953Srrs * no valid TCB for this packet, or we found it's a bad 5716163953Srrs * packet while processing control, or we're done with this 5717163953Srrs * packet (done or skip rest of data), so we drop it... 5718163953Srrs */ 5719171440Srrs goto out_now; 5720163953Srrs } 5721163953Srrs /* 5722163953Srrs * DATA chunk processing 5723163953Srrs */ 5724163953Srrs /* plow through the data chunks while length > offset */ 5725163953Srrs 5726163953Srrs /* 5727163953Srrs * Rest should be DATA only. Check authentication state if AUTH for 5728163953Srrs * DATA is required. 5729163953Srrs */ 5730179783Srrs if ((length > offset) && 5731179783Srrs (stcb != NULL) && 5732179783Srrs !SCTP_BASE_SYSCTL(sctp_auth_disable) && 5733179783Srrs sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) && 5734163953Srrs !stcb->asoc.authenticated) { 5735163953Srrs /* "silently" ignore */ 5736163953Srrs SCTP_STAT_INCR(sctps_recvauthmissing); 5737169420Srrs SCTPDBG(SCTP_DEBUG_AUTH1, 5738169420Srrs "Data chunk requires AUTH, skipped\n"); 5739165220Srrs goto trigger_send; 5740163953Srrs } 5741163953Srrs if (length > offset) { 5742163953Srrs int retval; 5743163953Srrs 5744163953Srrs /* 5745163953Srrs * First check to make sure our state is correct. We would 5746163953Srrs * not get here unless we really did have a tag, so we don't 5747163953Srrs * abort if this happens, just dump the chunk silently. 5748163953Srrs */ 5749163953Srrs switch (SCTP_GET_STATE(&stcb->asoc)) { 5750163953Srrs case SCTP_STATE_COOKIE_ECHOED: 5751163953Srrs /* 5752163953Srrs * we consider data with valid tags in this state 5753163953Srrs * shows us the cookie-ack was lost. Imply it was 5754163953Srrs * there. 5755163953Srrs */ 5756179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 5757171943Srrs sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 5758171943Srrs stcb->asoc.overall_error_count, 5759171943Srrs 0, 5760171943Srrs SCTP_FROM_SCTP_INPUT, 5761171943Srrs __LINE__); 5762171943Srrs } 5763163953Srrs stcb->asoc.overall_error_count = 0; 5764163953Srrs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, net); 5765163953Srrs break; 5766163953Srrs case SCTP_STATE_COOKIE_WAIT: 5767163953Srrs /* 5768163953Srrs * We consider OOTB any data sent during asoc setup. 5769163953Srrs */ 5770236450Stuexen sctp_handle_ootb(m, iphlen, offset, sh, inp, 5771237049Stuexen use_mflowid, mflowid, 5772179157Srrs vrf_id, port); 5773163953Srrs SCTP_TCB_UNLOCK(stcb); 5774171440Srrs goto out_now; 5775171531Srrs /* sa_ignore NOTREACHED */ 5776163953Srrs break; 5777163953Srrs case SCTP_STATE_EMPTY: /* should not happen */ 5778163953Srrs case SCTP_STATE_INUSE: /* should not happen */ 5779163953Srrs case SCTP_STATE_SHUTDOWN_RECEIVED: /* This is a peer error */ 5780163953Srrs case SCTP_STATE_SHUTDOWN_ACK_SENT: 5781163953Srrs default: 5782163953Srrs SCTP_TCB_UNLOCK(stcb); 5783171440Srrs goto out_now; 5784171531Srrs /* sa_ignore NOTREACHED */ 5785163953Srrs break; 5786163953Srrs case SCTP_STATE_OPEN: 5787163953Srrs case SCTP_STATE_SHUTDOWN_SENT: 5788163953Srrs break; 5789163953Srrs } 5790163953Srrs /* plow through the data chunks while length > offset */ 5791163953Srrs retval = sctp_process_data(mm, iphlen, &offset, length, sh, 5792237049Stuexen inp, stcb, net, &high_tsn, 5793237049Stuexen use_mflowid, mflowid, 5794237049Stuexen vrf_id, port); 5795163953Srrs if (retval == 2) { 5796163953Srrs /* 5797163953Srrs * The association aborted, NO UNLOCK needed since 5798163953Srrs * the association is destroyed. 5799163953Srrs */ 5800171440Srrs goto out_now; 5801163953Srrs } 5802163953Srrs data_processed = 1; 5803163953Srrs /* 5804163953Srrs * Anything important needs to have been m_copy'ed in 5805163953Srrs * process_data 5806163953Srrs */ 5807163953Srrs } 5808218129Srrs /* take care of ecn */ 5809228907Stuexen if ((data_processed == 1) && 5810228907Stuexen (stcb->asoc.ecn_allowed == 1) && 5811218235Stuexen ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) { 5812218129Srrs /* Yep, we need to add a ECNE */ 5813218129Srrs sctp_send_ecn_echo(stcb, net, high_tsn); 5814218129Srrs } 5815163953Srrs if ((data_processed == 0) && (fwd_tsn_seen)) { 5816216495Stuexen int was_a_gap; 5817216495Stuexen uint32_t highest_tsn; 5818163953Srrs 5819216825Stuexen if (SCTP_TSN_GT(stcb->asoc.highest_tsn_inside_nr_map, stcb->asoc.highest_tsn_inside_map)) { 5820216495Stuexen highest_tsn = stcb->asoc.highest_tsn_inside_nr_map; 5821216495Stuexen } else { 5822216495Stuexen highest_tsn = stcb->asoc.highest_tsn_inside_map; 5823163953Srrs } 5824216825Stuexen was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn); 5825190689Srrs stcb->asoc.send_sack = 1; 5826228653Stuexen sctp_sack_check(stcb, was_a_gap); 5827190689Srrs } else if (fwd_tsn_seen) { 5828190689Srrs stcb->asoc.send_sack = 1; 5829163953Srrs } 5830163953Srrs /* trigger send of any chunks in queue... */ 5831165220Srrstrigger_send: 5832163953Srrs#ifdef SCTP_AUDITING_ENABLED 5833163953Srrs sctp_audit_log(0xE0, 2); 5834163953Srrs sctp_auditing(1, inp, stcb, net); 5835163953Srrs#endif 5836169420Srrs SCTPDBG(SCTP_DEBUG_INPUT1, 5837169420Srrs "Check for chunk output prw:%d tqe:%d tf=%d\n", 5838169420Srrs stcb->asoc.peers_rwnd, 5839169420Srrs TAILQ_EMPTY(&stcb->asoc.control_send_queue), 5840169420Srrs stcb->asoc.total_flight); 5841163953Srrs un_sent = (stcb->asoc.total_output_queue_size - stcb->asoc.total_flight); 5842218129Srrs if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 5843218129Srrs cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq; 5844218129Srrs } 5845218129Srrs if (cnt_ctrl_ready || 5846163953Srrs ((un_sent) && 5847163953Srrs (stcb->asoc.peers_rwnd > 0 || 5848163953Srrs (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) { 5849169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "Calling chunk OUTPUT\n"); 5850172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 5851169420Srrs SCTPDBG(SCTP_DEBUG_INPUT3, "chunk OUTPUT returns\n"); 5852163953Srrs } 5853163953Srrs#ifdef SCTP_AUDITING_ENABLED 5854163953Srrs sctp_audit_log(0xE0, 3); 5855163953Srrs sctp_auditing(2, inp, stcb, net); 5856163953Srrs#endif 5857163953Srrs SCTP_TCB_UNLOCK(stcb); 5858171440Srrsout_now: 5859171440Srrs#ifdef INVARIANTS 5860171440Srrs sctp_validate_no_locks(inp); 5861171440Srrs#endif 5862169378Srrs return; 5863163953Srrs} 5864163953Srrs 5865185694Srrs#if 0 5866185694Srrsstatic void 5867185694Srrssctp_print_mbuf_chain(struct mbuf *m) 5868185694Srrs{ 5869185694Srrs for (; m; m = SCTP_BUF_NEXT(m)) { 5870234995Stuexen SCTP_PRINTF("%p: m_len = %ld\n", m, SCTP_BUF_LEN(m)); 5871185694Srrs if (SCTP_BUF_IS_EXTENDED(m)) 5872234995Stuexen SCTP_PRINTF("%p: extend_size = %d\n", m, SCTP_BUF_EXTEND_SIZE(m)); 5873185694Srrs } 5874185694Srrs} 5875163953Srrs 5876185694Srrs#endif 5877185694Srrs 5878221249Stuexen#ifdef INET 5879163953Srrsvoid 5880189004Srdivackysctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) 5881163953Srrs{ 5882165647Srrs struct mbuf *m; 5883163953Srrs int iphlen; 5884170181Srrs uint32_t vrf_id = 0; 5885163953Srrs uint8_t ecn_bits; 5886163953Srrs struct ip *ip; 5887163953Srrs struct sctphdr *sh; 5888237569Stuexen struct sctp_chunkhdr *ch; 5889163953Srrs struct sctp_inpcb *inp = NULL; 5890163953Srrs struct sctp_tcb *stcb = NULL; 5891237569Stuexen struct sctp_nets *net = NULL; 5892163953Srrs int refcount_up = 0; 5893237569Stuexen int length, offset; 5894237049Stuexen uint32_t mflowid; 5895237049Stuexen uint8_t use_mflowid; 5896163953Srrs 5897211969Stuexen#if !defined(SCTP_WITH_NO_CSUM) 5898211969Stuexen uint32_t check, calc_check; 5899211969Stuexen 5900211969Stuexen#endif 5901211969Stuexen 5902237569Stuexen iphlen = off; 5903169352Srrs if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) { 5904169352Srrs SCTP_RELEASE_PKT(i_pak); 5905169352Srrs return; 5906169352Srrs } 5907165647Srrs m = SCTP_HEADER_TO_CHAIN(i_pak); 5908163953Srrs#ifdef SCTP_MBUF_LOGGING 5909163953Srrs /* Log in any input mbufs */ 5910179783Srrs if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 5911234461Stuexen struct mbuf *mat; 5912234461Stuexen 5913228907Stuexen for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) { 5914170744Srrs if (SCTP_BUF_IS_EXTENDED(mat)) { 5915170744Srrs sctp_log_mb(mat, SCTP_MBUF_INPUT); 5916170744Srrs } 5917163953Srrs } 5918163953Srrs } 5919163953Srrs#endif 5920237540Stuexen#ifdef SCTP_PACKET_LOGGING 5921237569Stuexen if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { 5922237540Stuexen sctp_packet_log(m); 5923237569Stuexen } 5924170091Srrs#endif 5925237049Stuexen if (m->m_flags & M_FLOWID) { 5926237049Stuexen mflowid = m->m_pkthdr.flowid; 5927237049Stuexen use_mflowid = 1; 5928237049Stuexen } else { 5929237049Stuexen mflowid = 0; 5930237049Stuexen use_mflowid = 0; 5931237049Stuexen } 5932237569Stuexen SCTP_STAT_INCR(sctps_recvpackets); 5933237569Stuexen SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 5934237569Stuexen /* Get IP, SCTP, and first chunk header together in the first mbuf. */ 5935163953Srrs ip = mtod(m, struct ip *); 5936237569Stuexen offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); 5937165647Srrs if (SCTP_BUF_LEN(m) < offset) { 5938163953Srrs if ((m = m_pullup(m, offset)) == 0) { 5939163953Srrs SCTP_STAT_INCR(sctps_hdrops); 5940163953Srrs return; 5941163953Srrs } 5942163953Srrs ip = mtod(m, struct ip *); 5943163953Srrs } 5944237569Stuexen sh = (struct sctphdr *)((caddr_t)ip + iphlen); 5945237569Stuexen ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 5946237569Stuexen offset -= sizeof(struct sctp_chunkhdr); 5947237569Stuexen length = ip->ip_len + iphlen; 5948237569Stuexen /* Validate mbuf chain length with IP payload length. */ 5949237569Stuexen if (SCTP_HEADER_LEN(i_pak) != length) { 5950237569Stuexen SCTPDBG(SCTP_DEBUG_INPUT1, 5951237569Stuexen "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(i_pak)); 5952188067Srrs SCTP_STAT_INCR(sctps_hdrops); 5953188067Srrs goto bad; 5954188067Srrs } 5955163953Srrs /* SCTP does not allow broadcasts or multicasts */ 5956163953Srrs if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { 5957163953Srrs goto bad; 5958163953Srrs } 5959168124Srrs if (SCTP_IS_IT_BROADCAST(ip->ip_dst, m)) { 5960163953Srrs goto bad; 5961163953Srrs } 5962237569Stuexen SCTPDBG(SCTP_DEBUG_INPUT1, 5963237569Stuexen "sctp_input() length:%d iphlen:%d\n", length, iphlen); 5964188067Srrs SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 5965188067Srrs "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", 5966188067Srrs m->m_pkthdr.len, 5967188067Srrs if_name(m->m_pkthdr.rcvif), 5968188067Srrs m->m_pkthdr.csum_flags); 5969211969Stuexen#if defined(SCTP_WITH_NO_CSUM) 5970211969Stuexen SCTP_STAT_INCR(sctps_recvnocrc); 5971211969Stuexen#else 5972188067Srrs if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { 5973188067Srrs SCTP_STAT_INCR(sctps_recvhwcrc); 5974237569Stuexen goto sctp_skip_csum; 5975188067Srrs } 5976237569Stuexen check = sh->checksum; 5977237569Stuexen sh->checksum = 0; 5978188067Srrs calc_check = sctp_calculate_cksum(m, iphlen); 5979203503Stuexen sh->checksum = check; 5980188067Srrs SCTP_STAT_INCR(sctps_recvswcrc); 5981171990Srrs if (calc_check != check) { 5982171990Srrs SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n", 5983237569Stuexen calc_check, check, m, length, iphlen); 5984237569Stuexen stcb = sctp_findassociation_addr(m, offset, 5985237569Stuexen sh, ch, &inp, &net, vrf_id); 5986179157Srrs if ((net) && (port)) { 5987179157Srrs if (net->port == 0) { 5988228653Stuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 5989179157Srrs } 5990179157Srrs net->port = port; 5991179157Srrs } 5992237049Stuexen if ((net != NULL) && (use_mflowid != 0)) { 5993237049Stuexen net->flowid = mflowid; 5994218400Stuexen#ifdef INVARIANTS 5995218400Stuexen net->flowidset = 1; 5996218400Stuexen#endif 5997218400Stuexen } 5998171990Srrs if ((inp) && (stcb)) { 5999237569Stuexen sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1); 6000172090Srrs sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED); 6001171990Srrs } else if ((inp != NULL) && (stcb == NULL)) { 6002171990Srrs refcount_up = 1; 6003163953Srrs } 6004171990Srrs SCTP_STAT_INCR(sctps_badsum); 6005171990Srrs SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors); 6006171990Srrs goto bad; 6007168299Srrs } 6008237569Stuexensctp_skip_csum: 6009211969Stuexen#endif 6010168124Srrs /* destination port of 0 is illegal, based on RFC2960. */ 6011168124Srrs if (sh->dest_port == 0) { 6012168124Srrs SCTP_STAT_INCR(sctps_hdrops); 6013168124Srrs goto bad; 6014168124Srrs } 6015237569Stuexen stcb = sctp_findassociation_addr(m, offset, 6016168299Srrs sh, ch, &inp, &net, vrf_id); 6017179157Srrs if ((net) && (port)) { 6018179157Srrs if (net->port == 0) { 6019228653Stuexen sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 6020179157Srrs } 6021179157Srrs net->port = port; 6022179157Srrs } 6023237049Stuexen if ((net != NULL) && (use_mflowid != 0)) { 6024237049Stuexen net->flowid = mflowid; 6025218400Stuexen#ifdef INVARIANTS 6026218392Srrs net->flowidset = 1; 6027218400Stuexen#endif 6028218335Stuexen } 6029163953Srrs if (inp == NULL) { 6030163953Srrs SCTP_STAT_INCR(sctps_noport); 6031237230Stuexen if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) 6032163953Srrs goto bad; 6033165220Srrs if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 6034237049Stuexen sctp_send_shutdown_complete2(m, sh, 6035237049Stuexen use_mflowid, mflowid, 6036237049Stuexen vrf_id, port); 6037165220Srrs goto bad; 6038165220Srrs } 6039165220Srrs if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) { 6040165220Srrs goto bad; 6041165220Srrs } 6042229805Stuexen if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) { 6043229805Stuexen if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || 6044229805Stuexen ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && 6045229805Stuexen (ch->chunk_type != SCTP_INIT))) { 6046237049Stuexen sctp_send_abort(m, iphlen, sh, 0, NULL, 6047237049Stuexen use_mflowid, mflowid, 6048237049Stuexen vrf_id, port); 6049229805Stuexen } 6050229805Stuexen } 6051163953Srrs goto bad; 6052163953Srrs } else if (stcb == NULL) { 6053163953Srrs refcount_up = 1; 6054163953Srrs } 6055171167Sgnn#ifdef IPSEC 6056237569Stuexen /*- 6057163953Srrs * I very much doubt any of the IPSEC stuff will work but I have no 6058163953Srrs * idea, so I will leave it in place. 6059163953Srrs */ 6060163996Srrs if (inp && ipsec4_in_reject(m, &inp->ip_inp.inp)) { 6061197288Srrs MODULE_GLOBAL(ipsec4stat).in_polvio++; 6062163953Srrs SCTP_STAT_INCR(sctps_hdrops); 6063163953Srrs goto bad; 6064163953Srrs } 6065237569Stuexen#endif 6066163953Srrs 6067163953Srrs ecn_bits = ip->ip_tos; 6068169655Srrs /* sa_ignore NO_NULL_CHK */ 6069163953Srrs sctp_common_input_processing(&m, iphlen, offset, length, sh, ch, 6070237049Stuexen inp, stcb, net, ecn_bits, 6071237049Stuexen use_mflowid, mflowid, 6072237049Stuexen vrf_id, port); 6073163953Srrs if (m) { 6074163953Srrs sctp_m_freem(m); 6075163953Srrs } 6076163953Srrs if ((inp) && (refcount_up)) { 6077163953Srrs /* reduce ref-count */ 6078237569Stuexen SCTP_INP_WLOCK(inp); 6079163953Srrs SCTP_INP_DECR_REF(inp); 6080237569Stuexen SCTP_INP_WUNLOCK(inp); 6081163953Srrs } 6082163953Srrs return; 6083163953Srrsbad: 6084169420Srrs if (stcb) { 6085163953Srrs SCTP_TCB_UNLOCK(stcb); 6086169420Srrs } 6087163953Srrs if ((inp) && (refcount_up)) { 6088163953Srrs /* reduce ref-count */ 6089237569Stuexen SCTP_INP_WLOCK(inp); 6090163953Srrs SCTP_INP_DECR_REF(inp); 6091237569Stuexen SCTP_INP_WUNLOCK(inp); 6092163953Srrs } 6093163953Srrs if (m) { 6094163953Srrs sctp_m_freem(m); 6095163953Srrs } 6096163953Srrs return; 6097163953Srrs} 6098218211Srrs 6099218269Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 6100218269Srrsextern int *sctp_cpuarry; 6101218211Srrs 6102218269Srrs#endif 6103218269Srrs 6104179157Srrsvoid 6105218211Srrssctp_input(struct mbuf *m, int off) 6106179157Srrs{ 6107218211Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 6108218211Srrs struct ip *ip; 6109218211Srrs struct sctphdr *sh; 6110218211Srrs int offset; 6111218211Srrs int cpu_to_use; 6112218371Srrs uint32_t flowid, tag; 6113218211Srrs 6114218269Srrs if (mp_ncpus > 1) { 6115218371Srrs if (m->m_flags & M_FLOWID) { 6116218371Srrs flowid = m->m_pkthdr.flowid; 6117218269Srrs } else { 6118218269Srrs /* 6119218371Srrs * No flow id built by lower layers fix it so we 6120218371Srrs * create one. 6121218269Srrs */ 6122218371Srrs ip = mtod(m, struct ip *); 6123218371Srrs offset = off + sizeof(*sh); 6124218371Srrs if (SCTP_BUF_LEN(m) < offset) { 6125218371Srrs if ((m = m_pullup(m, offset)) == 0) { 6126218371Srrs SCTP_STAT_INCR(sctps_hdrops); 6127218371Srrs return; 6128218371Srrs } 6129218371Srrs ip = mtod(m, struct ip *); 6130218371Srrs } 6131218371Srrs sh = (struct sctphdr *)((caddr_t)ip + off); 6132218371Srrs tag = htonl(sh->v_tag); 6133218371Srrs flowid = tag ^ ntohs(sh->dest_port) ^ ntohs(sh->src_port); 6134218371Srrs m->m_pkthdr.flowid = flowid; 6135218371Srrs m->m_flags |= M_FLOWID; 6136218269Srrs } 6137218371Srrs cpu_to_use = sctp_cpuarry[flowid % mp_ncpus]; 6138218211Srrs sctp_queue_to_mcore(m, off, cpu_to_use); 6139218211Srrs return; 6140218211Srrs } 6141218211Srrs#endif 6142218211Srrs sctp_input_with_port(m, off, 0); 6143179157Srrs} 6144221249Stuexen 6145221249Stuexen#endif 6146