1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/sctp/src/netinet/sctp_input.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,6423 @@ 1.4 +/*- 1.5 + * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved. 1.6 + * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. 1.7 + * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved. 1.8 + * 1.9 + * Redistribution and use in source and binary forms, with or without 1.10 + * modification, are permitted provided that the following conditions are met: 1.11 + * 1.12 + * a) Redistributions of source code must retain the above copyright notice, 1.13 + * this list of conditions and the following disclaimer. 1.14 + * 1.15 + * b) Redistributions in binary form must reproduce the above copyright 1.16 + * notice, this list of conditions and the following disclaimer in 1.17 + * the documentation and/or other materials provided with the distribution. 1.18 + * 1.19 + * c) Neither the name of Cisco Systems, Inc. nor the names of its 1.20 + * contributors may be used to endorse or promote products derived 1.21 + * from this software without specific prior written permission. 1.22 + * 1.23 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.24 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 1.25 + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1.26 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 1.27 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1.28 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1.29 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 1.30 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 1.31 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 1.32 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 1.33 + * THE POSSIBILITY OF SUCH DAMAGE. 1.34 + */ 1.35 + 1.36 +#ifdef __FreeBSD__ 1.37 +#include <sys/cdefs.h> 1.38 +__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 262252 2014-02-20 20:14:43Z tuexen $"); 1.39 +#endif 1.40 + 1.41 +#include <netinet/sctp_os.h> 1.42 +#include <netinet/sctp_var.h> 1.43 +#include <netinet/sctp_sysctl.h> 1.44 +#include <netinet/sctp_pcb.h> 1.45 +#include <netinet/sctp_header.h> 1.46 +#include <netinet/sctputil.h> 1.47 +#include <netinet/sctp_output.h> 1.48 +#include <netinet/sctp_input.h> 1.49 +#include <netinet/sctp_auth.h> 1.50 +#include <netinet/sctp_indata.h> 1.51 +#include <netinet/sctp_asconf.h> 1.52 +#include <netinet/sctp_bsd_addr.h> 1.53 +#include <netinet/sctp_timer.h> 1.54 +#include <netinet/sctp_crc32.h> 1.55 +#if !defined(__Userspace_os_Windows) 1.56 +#include <netinet/udp.h> 1.57 +#endif 1.58 +#if defined(__FreeBSD__) 1.59 +#include <sys/smp.h> 1.60 +#endif 1.61 + 1.62 +#if defined(__APPLE__) 1.63 +#define APPLE_FILE_NO 2 1.64 +#endif 1.65 + 1.66 + 1.67 +static void 1.68 +sctp_stop_all_cookie_timers(struct sctp_tcb *stcb) 1.69 +{ 1.70 + struct sctp_nets *net; 1.71 + 1.72 + /* This now not only stops all cookie timers 1.73 + * it also stops any INIT timers as well. This 1.74 + * will make sure that the timers are stopped in 1.75 + * all collision cases. 1.76 + */ 1.77 + SCTP_TCB_LOCK_ASSERT(stcb); 1.78 + TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1.79 + if (net->rxt_timer.type == SCTP_TIMER_TYPE_COOKIE) { 1.80 + sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, 1.81 + stcb->sctp_ep, 1.82 + stcb, 1.83 + net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_1); 1.84 + } else if (net->rxt_timer.type == SCTP_TIMER_TYPE_INIT) { 1.85 + sctp_timer_stop(SCTP_TIMER_TYPE_INIT, 1.86 + stcb->sctp_ep, 1.87 + stcb, 1.88 + net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_2); 1.89 + } 1.90 + } 1.91 +} 1.92 + 1.93 +/* INIT handler */ 1.94 +static void 1.95 +sctp_handle_init(struct mbuf *m, int iphlen, int offset, 1.96 + struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 1.97 + struct sctp_init_chunk *cp, struct sctp_inpcb *inp, 1.98 + struct sctp_tcb *stcb, int *abort_no_unlock, 1.99 +#if defined(__FreeBSD__) 1.100 + uint8_t use_mflowid, uint32_t mflowid, 1.101 +#endif 1.102 + uint32_t vrf_id, uint16_t port) 1.103 +{ 1.104 + struct sctp_init *init; 1.105 + struct mbuf *op_err; 1.106 + 1.107 + SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_init: handling INIT tcb:%p\n", 1.108 + (void *)stcb); 1.109 + if (stcb == NULL) { 1.110 + SCTP_INP_RLOCK(inp); 1.111 + } 1.112 + /* validate length */ 1.113 + if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) { 1.114 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1.115 + sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 1.116 +#if defined(__FreeBSD__) 1.117 + use_mflowid, mflowid, 1.118 +#endif 1.119 + vrf_id, port); 1.120 + if (stcb) 1.121 + *abort_no_unlock = 1; 1.122 + goto outnow; 1.123 + } 1.124 + /* validate parameters */ 1.125 + init = &cp->init; 1.126 + if (init->initiate_tag == 0) { 1.127 + /* protocol error... send abort */ 1.128 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1.129 + sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 1.130 +#if defined(__FreeBSD__) 1.131 + use_mflowid, mflowid, 1.132 +#endif 1.133 + vrf_id, port); 1.134 + if (stcb) 1.135 + *abort_no_unlock = 1; 1.136 + goto outnow; 1.137 + } 1.138 + if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) { 1.139 + /* invalid parameter... send abort */ 1.140 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1.141 + sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 1.142 +#if defined(__FreeBSD__) 1.143 + use_mflowid, mflowid, 1.144 +#endif 1.145 + vrf_id, port); 1.146 + if (stcb) 1.147 + *abort_no_unlock = 1; 1.148 + goto outnow; 1.149 + } 1.150 + if (init->num_inbound_streams == 0) { 1.151 + /* protocol error... send abort */ 1.152 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1.153 + sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 1.154 +#if defined(__FreeBSD__) 1.155 + use_mflowid, mflowid, 1.156 +#endif 1.157 + vrf_id, port); 1.158 + if (stcb) 1.159 + *abort_no_unlock = 1; 1.160 + goto outnow; 1.161 + } 1.162 + if (init->num_outbound_streams == 0) { 1.163 + /* protocol error... send abort */ 1.164 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1.165 + sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, 1.166 +#if defined(__FreeBSD__) 1.167 + use_mflowid, mflowid, 1.168 +#endif 1.169 + vrf_id, port); 1.170 + if (stcb) 1.171 + *abort_no_unlock = 1; 1.172 + goto outnow; 1.173 + } 1.174 + if (sctp_validate_init_auth_params(m, offset + sizeof(*cp), 1.175 + offset + ntohs(cp->ch.chunk_length))) { 1.176 + /* auth parameter(s) error... send abort */ 1.177 + sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, NULL, 1.178 +#if defined(__FreeBSD__) 1.179 + use_mflowid, mflowid, 1.180 +#endif 1.181 + vrf_id, port); 1.182 + if (stcb) 1.183 + *abort_no_unlock = 1; 1.184 + goto outnow; 1.185 + } 1.186 + /* We are only accepting if we have a socket with positive so_qlimit.*/ 1.187 + if ((stcb == NULL) && 1.188 + ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 1.189 + (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 1.190 + (inp->sctp_socket == NULL) || 1.191 + (inp->sctp_socket->so_qlimit == 0))) { 1.192 + /* 1.193 + * FIX ME ?? What about TCP model and we have a 1.194 + * match/restart case? Actually no fix is needed. 1.195 + * the lookup will always find the existing assoc so stcb 1.196 + * would not be NULL. It may be questionable to do this 1.197 + * since we COULD just send back the INIT-ACK and hope that 1.198 + * the app did accept()'s by the time the COOKIE was sent. But 1.199 + * there is a price to pay for COOKIE generation and I don't 1.200 + * want to pay it on the chance that the app will actually do 1.201 + * some accepts(). The App just looses and should NOT be in 1.202 + * this state :-) 1.203 + */ 1.204 + if (SCTP_BASE_SYSCTL(sctp_blackhole) == 0) { 1.205 + sctp_send_abort(m, iphlen, src, dst, sh, 0, NULL, 1.206 +#if defined(__FreeBSD__) 1.207 + use_mflowid, mflowid, 1.208 +#endif 1.209 + vrf_id, port); 1.210 + } 1.211 + goto outnow; 1.212 + } 1.213 + if ((stcb != NULL) && 1.214 + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT)) { 1.215 + SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending SHUTDOWN-ACK\n"); 1.216 + sctp_send_shutdown_ack(stcb, NULL); 1.217 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 1.218 + } else { 1.219 + SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n"); 1.220 + sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, src, dst, 1.221 + sh, cp, 1.222 +#if defined(__FreeBSD__) 1.223 + use_mflowid, mflowid, 1.224 +#endif 1.225 + vrf_id, port, 1.226 + ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED)); 1.227 + } 1.228 + outnow: 1.229 + if (stcb == NULL) { 1.230 + SCTP_INP_RUNLOCK(inp); 1.231 + } 1.232 +} 1.233 + 1.234 +/* 1.235 + * process peer "INIT/INIT-ACK" chunk returns value < 0 on error 1.236 + */ 1.237 + 1.238 +int 1.239 +sctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked 1.240 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.241 + SCTP_UNUSED 1.242 +#endif 1.243 +) 1.244 +{ 1.245 + int unsent_data = 0; 1.246 + unsigned int i; 1.247 + struct sctp_stream_queue_pending *sp; 1.248 + struct sctp_association *asoc; 1.249 + 1.250 + /* This function returns the number of streams that have 1.251 + * true unsent data on them. Note that as it looks through 1.252 + * it will clean up any places that have old data that 1.253 + * has been sent but left at top of stream queue. 1.254 + */ 1.255 + asoc = &stcb->asoc; 1.256 + SCTP_TCB_SEND_LOCK(stcb); 1.257 + if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 1.258 + /* Check to see if some data queued */ 1.259 + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 1.260 + /*sa_ignore FREED_MEMORY*/ 1.261 + sp = TAILQ_FIRST(&stcb->asoc.strmout[i].outqueue); 1.262 + if (sp == NULL) { 1.263 + continue; 1.264 + } 1.265 + if ((sp->msg_is_complete) && 1.266 + (sp->length == 0) && 1.267 + (sp->sender_all_done)) { 1.268 + /* We are doing differed cleanup. Last 1.269 + * time through when we took all the data 1.270 + * the sender_all_done was not set. 1.271 + */ 1.272 + if (sp->put_last_out == 0) { 1.273 + SCTP_PRINTF("Gak, put out entire msg with NO end!-1\n"); 1.274 + SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d\n", 1.275 + sp->sender_all_done, 1.276 + sp->length, 1.277 + sp->msg_is_complete, 1.278 + sp->put_last_out); 1.279 + } 1.280 + atomic_subtract_int(&stcb->asoc.stream_queue_cnt, 1); 1.281 + TAILQ_REMOVE(&stcb->asoc.strmout[i].outqueue, sp, next); 1.282 + if (sp->net) { 1.283 + sctp_free_remote_addr(sp->net); 1.284 + sp->net = NULL; 1.285 + } 1.286 + if (sp->data) { 1.287 + sctp_m_freem(sp->data); 1.288 + sp->data = NULL; 1.289 + } 1.290 + sctp_free_a_strmoq(stcb, sp, so_locked); 1.291 + } else { 1.292 + unsent_data++; 1.293 + break; 1.294 + } 1.295 + } 1.296 + } 1.297 + SCTP_TCB_SEND_UNLOCK(stcb); 1.298 + return (unsent_data); 1.299 +} 1.300 + 1.301 +static int 1.302 +sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb) 1.303 +{ 1.304 + struct sctp_init *init; 1.305 + struct sctp_association *asoc; 1.306 + struct sctp_nets *lnet; 1.307 + unsigned int i; 1.308 + 1.309 + init = &cp->init; 1.310 + asoc = &stcb->asoc; 1.311 + /* save off parameters */ 1.312 + asoc->peer_vtag = ntohl(init->initiate_tag); 1.313 + asoc->peers_rwnd = ntohl(init->a_rwnd); 1.314 + /* init tsn's */ 1.315 + asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1; 1.316 + 1.317 + if (!TAILQ_EMPTY(&asoc->nets)) { 1.318 + /* update any ssthresh's that may have a default */ 1.319 + TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) { 1.320 + lnet->ssthresh = asoc->peers_rwnd; 1.321 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE|SCTP_CWND_LOGGING_ENABLE)) { 1.322 + sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_INITIALIZATION); 1.323 + } 1.324 + 1.325 + } 1.326 + } 1.327 + SCTP_TCB_SEND_LOCK(stcb); 1.328 + if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) { 1.329 + unsigned int newcnt; 1.330 + struct sctp_stream_out *outs; 1.331 + struct sctp_stream_queue_pending *sp, *nsp; 1.332 + struct sctp_tmit_chunk *chk, *nchk; 1.333 + 1.334 + /* abandon the upper streams */ 1.335 + newcnt = ntohs(init->num_inbound_streams); 1.336 + TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { 1.337 + if (chk->rec.data.stream_number >= newcnt) { 1.338 + TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); 1.339 + asoc->send_queue_cnt--; 1.340 + if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 1.341 + asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 1.342 +#ifdef INVARIANTS 1.343 + } else { 1.344 + panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 1.345 +#endif 1.346 + } 1.347 + if (chk->data != NULL) { 1.348 + sctp_free_bufspace(stcb, asoc, chk, 1); 1.349 + sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 1.350 + 0, chk, SCTP_SO_NOT_LOCKED); 1.351 + if (chk->data) { 1.352 + sctp_m_freem(chk->data); 1.353 + chk->data = NULL; 1.354 + } 1.355 + } 1.356 + sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 1.357 + /*sa_ignore FREED_MEMORY*/ 1.358 + } 1.359 + } 1.360 + if (asoc->strmout) { 1.361 + for (i = newcnt; i < asoc->pre_open_streams; i++) { 1.362 + outs = &asoc->strmout[i]; 1.363 + TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { 1.364 + TAILQ_REMOVE(&outs->outqueue, sp, next); 1.365 + asoc->stream_queue_cnt--; 1.366 + sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, 1.367 + stcb, 0, sp, SCTP_SO_NOT_LOCKED); 1.368 + if (sp->data) { 1.369 + sctp_m_freem(sp->data); 1.370 + sp->data = NULL; 1.371 + } 1.372 + if (sp->net) { 1.373 + sctp_free_remote_addr(sp->net); 1.374 + sp->net = NULL; 1.375 + } 1.376 + /* Free the chunk */ 1.377 + sctp_free_a_strmoq(stcb, sp, SCTP_SO_NOT_LOCKED); 1.378 + /*sa_ignore FREED_MEMORY*/ 1.379 + } 1.380 + } 1.381 + } 1.382 + /* cut back the count */ 1.383 + asoc->pre_open_streams = newcnt; 1.384 + } 1.385 + SCTP_TCB_SEND_UNLOCK(stcb); 1.386 + asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams; 1.387 + 1.388 + /* EY - nr_sack: initialize highest tsn in nr_mapping_array */ 1.389 + asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 1.390 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 1.391 + sctp_log_map(0, 5, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 1.392 + } 1.393 + /* This is the next one we expect */ 1.394 + asoc->str_reset_seq_in = asoc->asconf_seq_in + 1; 1.395 + 1.396 + asoc->mapping_array_base_tsn = ntohl(init->initial_tsn); 1.397 + asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->asconf_seq_in; 1.398 + 1.399 + asoc->advanced_peer_ack_point = asoc->last_acked_seq; 1.400 + /* open the requested streams */ 1.401 + 1.402 + if (asoc->strmin != NULL) { 1.403 + /* Free the old ones */ 1.404 + struct sctp_queued_to_read *ctl, *nctl; 1.405 + 1.406 + for (i = 0; i < asoc->streamincnt; i++) { 1.407 + TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) { 1.408 + TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next); 1.409 + sctp_free_remote_addr(ctl->whoFrom); 1.410 + ctl->whoFrom = NULL; 1.411 + sctp_m_freem(ctl->data); 1.412 + ctl->data = NULL; 1.413 + sctp_free_a_readq(stcb, ctl); 1.414 + } 1.415 + } 1.416 + SCTP_FREE(asoc->strmin, SCTP_M_STRMI); 1.417 + } 1.418 + if (asoc->max_inbound_streams > ntohs(init->num_outbound_streams)) { 1.419 + asoc->streamincnt = ntohs(init->num_outbound_streams); 1.420 + } else { 1.421 + asoc->streamincnt = asoc->max_inbound_streams; 1.422 + } 1.423 + SCTP_MALLOC(asoc->strmin, struct sctp_stream_in *, asoc->streamincnt * 1.424 + sizeof(struct sctp_stream_in), SCTP_M_STRMI); 1.425 + if (asoc->strmin == NULL) { 1.426 + /* we didn't get memory for the streams! */ 1.427 + SCTPDBG(SCTP_DEBUG_INPUT2, "process_init: couldn't get memory for the streams!\n"); 1.428 + return (-1); 1.429 + } 1.430 + for (i = 0; i < asoc->streamincnt; i++) { 1.431 + asoc->strmin[i].stream_no = i; 1.432 + asoc->strmin[i].last_sequence_delivered = 0xffff; 1.433 + TAILQ_INIT(&asoc->strmin[i].inqueue); 1.434 + asoc->strmin[i].delivery_started = 0; 1.435 + } 1.436 + /* 1.437 + * load_address_from_init will put the addresses into the 1.438 + * association when the COOKIE is processed or the INIT-ACK is 1.439 + * processed. Both types of COOKIE's existing and new call this 1.440 + * routine. It will remove addresses that are no longer in the 1.441 + * association (for the restarting case where addresses are 1.442 + * removed). Up front when the INIT arrives we will discard it if it 1.443 + * is a restart and new addresses have been added. 1.444 + */ 1.445 + /* sa_ignore MEMLEAK */ 1.446 + return (0); 1.447 +} 1.448 + 1.449 +/* 1.450 + * INIT-ACK message processing/consumption returns value < 0 on error 1.451 + */ 1.452 +static int 1.453 +sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, 1.454 + struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 1.455 + struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 1.456 + struct sctp_nets *net, int *abort_no_unlock, 1.457 +#if defined(__FreeBSD__) 1.458 + uint8_t use_mflowid, uint32_t mflowid, 1.459 +#endif 1.460 + uint32_t vrf_id) 1.461 +{ 1.462 + struct sctp_association *asoc; 1.463 + struct mbuf *op_err; 1.464 + int retval, abort_flag; 1.465 + uint32_t initack_limit; 1.466 + int nat_friendly = 0; 1.467 + 1.468 + /* First verify that we have no illegal param's */ 1.469 + abort_flag = 0; 1.470 + 1.471 + op_err = sctp_arethere_unrecognized_parameters(m, 1.472 + (offset + sizeof(struct sctp_init_chunk)), 1.473 + &abort_flag, (struct sctp_chunkhdr *)cp, &nat_friendly); 1.474 + if (abort_flag) { 1.475 + /* Send an abort and notify peer */ 1.476 + sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED); 1.477 + *abort_no_unlock = 1; 1.478 + return (-1); 1.479 + } 1.480 + asoc = &stcb->asoc; 1.481 + asoc->peer_supports_nat = (uint8_t)nat_friendly; 1.482 + /* process the peer's parameters in the INIT-ACK */ 1.483 + retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb); 1.484 + if (retval < 0) { 1.485 + return (retval); 1.486 + } 1.487 + initack_limit = offset + ntohs(cp->ch.chunk_length); 1.488 + /* load all addresses */ 1.489 + if ((retval = sctp_load_addresses_from_init(stcb, m, 1.490 + (offset + sizeof(struct sctp_init_chunk)), initack_limit, 1.491 + src, dst, NULL))) { 1.492 + /* Huh, we should abort */ 1.493 + SCTPDBG(SCTP_DEBUG_INPUT1, 1.494 + "Load addresses from INIT causes an abort %d\n", 1.495 + retval); 1.496 + sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1.497 + src, dst, sh, NULL, 1.498 +#if defined(__FreeBSD__) 1.499 + use_mflowid, mflowid, 1.500 +#endif 1.501 + vrf_id, net->port); 1.502 + *abort_no_unlock = 1; 1.503 + return (-1); 1.504 + } 1.505 + /* if the peer doesn't support asconf, flush the asconf queue */ 1.506 + if (asoc->peer_supports_asconf == 0) { 1.507 + struct sctp_asconf_addr *param, *nparam; 1.508 + 1.509 + TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) { 1.510 + TAILQ_REMOVE(&asoc->asconf_queue, param, next); 1.511 + SCTP_FREE(param, SCTP_M_ASC_ADDR); 1.512 + } 1.513 + } 1.514 + 1.515 + stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs, 1.516 + stcb->asoc.local_hmacs); 1.517 + if (op_err) { 1.518 + sctp_queue_op_err(stcb, op_err); 1.519 + /* queuing will steal away the mbuf chain to the out queue */ 1.520 + op_err = NULL; 1.521 + } 1.522 + /* extract the cookie and queue it to "echo" it back... */ 1.523 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.524 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.525 + stcb->asoc.overall_error_count, 1.526 + 0, 1.527 + SCTP_FROM_SCTP_INPUT, 1.528 + __LINE__); 1.529 + } 1.530 + stcb->asoc.overall_error_count = 0; 1.531 + net->error_count = 0; 1.532 + 1.533 + /* 1.534 + * Cancel the INIT timer, We do this first before queueing the 1.535 + * cookie. We always cancel at the primary to assue that we are 1.536 + * canceling the timer started by the INIT which always goes to the 1.537 + * primary. 1.538 + */ 1.539 + sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb, 1.540 + asoc->primary_destination, SCTP_FROM_SCTP_INPUT+SCTP_LOC_4); 1.541 + 1.542 + /* calculate the RTO */ 1.543 + net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy, 1.544 + SCTP_RTT_FROM_NON_DATA); 1.545 + 1.546 + retval = sctp_send_cookie_echo(m, offset, stcb, net); 1.547 + if (retval < 0) { 1.548 + /* 1.549 + * No cookie, we probably should send a op error. But in any 1.550 + * case if there is no cookie in the INIT-ACK, we can 1.551 + * abandon the peer, its broke. 1.552 + */ 1.553 + if (retval == -3) { 1.554 + /* We abort with an error of missing mandatory param */ 1.555 + op_err = 1.556 + sctp_generate_invmanparam(SCTP_CAUSE_MISSING_PARAM); 1.557 + if (op_err) { 1.558 + /* 1.559 + * Expand beyond to include the mandatory 1.560 + * param cookie 1.561 + */ 1.562 + struct sctp_inv_mandatory_param *mp; 1.563 + 1.564 + SCTP_BUF_LEN(op_err) = 1.565 + sizeof(struct sctp_inv_mandatory_param); 1.566 + mp = mtod(op_err, 1.567 + struct sctp_inv_mandatory_param *); 1.568 + /* Subtract the reserved param */ 1.569 + mp->length = 1.570 + htons(sizeof(struct sctp_inv_mandatory_param) - 2); 1.571 + mp->num_param = htonl(1); 1.572 + mp->param = htons(SCTP_STATE_COOKIE); 1.573 + mp->resv = 0; 1.574 + } 1.575 + sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1.576 + src, dst, sh, op_err, 1.577 +#if defined(__FreeBSD__) 1.578 + use_mflowid, mflowid, 1.579 +#endif 1.580 + vrf_id, net->port); 1.581 + *abort_no_unlock = 1; 1.582 + } 1.583 + return (retval); 1.584 + } 1.585 + 1.586 + return (0); 1.587 +} 1.588 + 1.589 +static void 1.590 +sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp, 1.591 + struct sctp_tcb *stcb, struct sctp_nets *net) 1.592 +{ 1.593 + struct sockaddr_storage store; 1.594 + struct sctp_nets *r_net, *f_net; 1.595 + struct timeval tv; 1.596 + int req_prim = 0; 1.597 + uint16_t old_error_counter; 1.598 +#ifdef INET 1.599 + struct sockaddr_in *sin; 1.600 +#endif 1.601 +#ifdef INET6 1.602 + struct sockaddr_in6 *sin6; 1.603 +#endif 1.604 +#if defined(__Userspace__) 1.605 + struct sockaddr_conn *sconn; 1.606 +#endif 1.607 + 1.608 + if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) { 1.609 + /* Invalid length */ 1.610 + return; 1.611 + } 1.612 + 1.613 + memset(&store, 0, sizeof(store)); 1.614 + switch (cp->heartbeat.hb_info.addr_family) { 1.615 +#ifdef INET 1.616 + case AF_INET: 1.617 + if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) { 1.618 + sin = (struct sockaddr_in *)&store; 1.619 + sin->sin_family = cp->heartbeat.hb_info.addr_family; 1.620 +#ifdef HAVE_SIN_LEN 1.621 + sin->sin_len = cp->heartbeat.hb_info.addr_len; 1.622 +#endif 1.623 + sin->sin_port = stcb->rport; 1.624 + memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address, 1.625 + sizeof(sin->sin_addr)); 1.626 + } else { 1.627 + return; 1.628 + } 1.629 + break; 1.630 +#endif 1.631 +#ifdef INET6 1.632 + case AF_INET6: 1.633 + if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) { 1.634 + sin6 = (struct sockaddr_in6 *)&store; 1.635 + sin6->sin6_family = cp->heartbeat.hb_info.addr_family; 1.636 +#ifdef HAVE_SIN6_LEN 1.637 + sin6->sin6_len = cp->heartbeat.hb_info.addr_len; 1.638 +#endif 1.639 + sin6->sin6_port = stcb->rport; 1.640 + memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address, 1.641 + sizeof(sin6->sin6_addr)); 1.642 + } else { 1.643 + return; 1.644 + } 1.645 + break; 1.646 +#endif 1.647 +#if defined(__Userspace__) 1.648 + case AF_CONN: 1.649 + if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_conn)) { 1.650 + sconn = (struct sockaddr_conn *)&store; 1.651 + sconn->sconn_family = cp->heartbeat.hb_info.addr_family; 1.652 +#ifdef HAVE_SCONN_LEN 1.653 + sconn->sconn_len = cp->heartbeat.hb_info.addr_len; 1.654 +#endif 1.655 + sconn->sconn_port = stcb->rport; 1.656 + memcpy(&sconn->sconn_addr, cp->heartbeat.hb_info.address, 1.657 + sizeof(sconn->sconn_addr)); 1.658 + } else { 1.659 + return; 1.660 + } 1.661 + break; 1.662 +#endif 1.663 + default: 1.664 + return; 1.665 + } 1.666 + r_net = sctp_findnet(stcb, (struct sockaddr *)&store); 1.667 + if (r_net == NULL) { 1.668 + SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n"); 1.669 + return; 1.670 + } 1.671 + if ((r_net && (r_net->dest_state & SCTP_ADDR_UNCONFIRMED)) && 1.672 + (r_net->heartbeat_random1 == cp->heartbeat.hb_info.random_value1) && 1.673 + (r_net->heartbeat_random2 == cp->heartbeat.hb_info.random_value2)) { 1.674 + /* 1.675 + * If the its a HB and it's random value is correct when can 1.676 + * confirm the destination. 1.677 + */ 1.678 + r_net->dest_state &= ~SCTP_ADDR_UNCONFIRMED; 1.679 + if (r_net->dest_state & SCTP_ADDR_REQ_PRIMARY) { 1.680 + stcb->asoc.primary_destination = r_net; 1.681 + r_net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY; 1.682 + f_net = TAILQ_FIRST(&stcb->asoc.nets); 1.683 + if (f_net != r_net) { 1.684 + /* first one on the list is NOT the primary 1.685 + * sctp_cmpaddr() is much more efficent if 1.686 + * the primary is the first on the list, make it 1.687 + * so. 1.688 + */ 1.689 + TAILQ_REMOVE(&stcb->asoc.nets, r_net, sctp_next); 1.690 + TAILQ_INSERT_HEAD(&stcb->asoc.nets, r_net, sctp_next); 1.691 + } 1.692 + req_prim = 1; 1.693 + } 1.694 + sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 1.695 + stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED); 1.696 + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 1.697 + sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 1.698 + } 1.699 + old_error_counter = r_net->error_count; 1.700 + r_net->error_count = 0; 1.701 + r_net->hb_responded = 1; 1.702 + tv.tv_sec = cp->heartbeat.hb_info.time_value_1; 1.703 + tv.tv_usec = cp->heartbeat.hb_info.time_value_2; 1.704 + /* Now lets do a RTO with this */ 1.705 + r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy, 1.706 + SCTP_RTT_FROM_NON_DATA); 1.707 + if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) { 1.708 + r_net->dest_state |= SCTP_ADDR_REACHABLE; 1.709 + sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 1.710 + 0, (void *)r_net, SCTP_SO_NOT_LOCKED); 1.711 + } 1.712 + if (r_net->dest_state & SCTP_ADDR_PF) { 1.713 + r_net->dest_state &= ~SCTP_ADDR_PF; 1.714 + stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net); 1.715 + } 1.716 + if (old_error_counter > 0) { 1.717 + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3); 1.718 + sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net); 1.719 + } 1.720 + if (r_net == stcb->asoc.primary_destination) { 1.721 + if (stcb->asoc.alternate) { 1.722 + /* release the alternate, primary is good */ 1.723 + sctp_free_remote_addr(stcb->asoc.alternate); 1.724 + stcb->asoc.alternate = NULL; 1.725 + } 1.726 + } 1.727 + /* Mobility adaptation */ 1.728 + if (req_prim) { 1.729 + if ((sctp_is_mobility_feature_on(stcb->sctp_ep, 1.730 + SCTP_MOBILITY_BASE) || 1.731 + sctp_is_mobility_feature_on(stcb->sctp_ep, 1.732 + SCTP_MOBILITY_FASTHANDOFF)) && 1.733 + sctp_is_mobility_feature_on(stcb->sctp_ep, 1.734 + SCTP_MOBILITY_PRIM_DELETED)) { 1.735 + 1.736 + sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER+SCTP_LOC_7); 1.737 + if (sctp_is_mobility_feature_on(stcb->sctp_ep, 1.738 + SCTP_MOBILITY_FASTHANDOFF)) { 1.739 + sctp_assoc_immediate_retrans(stcb, 1.740 + stcb->asoc.primary_destination); 1.741 + } 1.742 + if (sctp_is_mobility_feature_on(stcb->sctp_ep, 1.743 + SCTP_MOBILITY_BASE)) { 1.744 + sctp_move_chunks_from_net(stcb, 1.745 + stcb->asoc.deleted_primary); 1.746 + } 1.747 + sctp_delete_prim_timer(stcb->sctp_ep, stcb, 1.748 + stcb->asoc.deleted_primary); 1.749 + } 1.750 + } 1.751 +} 1.752 + 1.753 +static int 1.754 +sctp_handle_nat_colliding_state(struct sctp_tcb *stcb) 1.755 +{ 1.756 + /* return 0 means we want you to proceed with the abort 1.757 + * non-zero means no abort processing 1.758 + */ 1.759 + struct sctpasochead *head; 1.760 + 1.761 + if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) { 1.762 + /* generate a new vtag and send init */ 1.763 + LIST_REMOVE(stcb, sctp_asocs); 1.764 + stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 1.765 + head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 1.766 + /* put it in the bucket in the vtag hash of assoc's for the system */ 1.767 + LIST_INSERT_HEAD(head, stcb, sctp_asocs); 1.768 + sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 1.769 + return (1); 1.770 + } 1.771 + if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) { 1.772 + /* treat like a case where the cookie expired i.e.: 1.773 + * - dump current cookie. 1.774 + * - generate a new vtag. 1.775 + * - resend init. 1.776 + */ 1.777 + /* generate a new vtag and send init */ 1.778 + LIST_REMOVE(stcb, sctp_asocs); 1.779 + stcb->asoc.state &= ~SCTP_STATE_COOKIE_ECHOED; 1.780 + stcb->asoc.state |= SCTP_STATE_COOKIE_WAIT; 1.781 + sctp_stop_all_cookie_timers(stcb); 1.782 + sctp_toss_old_cookies(stcb, &stcb->asoc); 1.783 + stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 1.784 + head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))]; 1.785 + /* put it in the bucket in the vtag hash of assoc's for the system */ 1.786 + LIST_INSERT_HEAD(head, stcb, sctp_asocs); 1.787 + sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 1.788 + return (1); 1.789 + } 1.790 + return (0); 1.791 +} 1.792 + 1.793 +static int 1.794 +sctp_handle_nat_missing_state(struct sctp_tcb *stcb, 1.795 + struct sctp_nets *net) 1.796 + 1.797 +{ 1.798 + /* return 0 means we want you to proceed with the abort 1.799 + * non-zero means no abort processing 1.800 + */ 1.801 + if (stcb->asoc.peer_supports_auth == 0) { 1.802 + SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n"); 1.803 + return (0); 1.804 + } 1.805 + sctp_asconf_send_nat_state_update(stcb, net); 1.806 + return (1); 1.807 +} 1.808 + 1.809 + 1.810 +static void 1.811 +sctp_handle_abort(struct sctp_abort_chunk *abort, 1.812 + struct sctp_tcb *stcb, struct sctp_nets *net) 1.813 +{ 1.814 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.815 + struct socket *so; 1.816 +#endif 1.817 + uint16_t len; 1.818 + uint16_t error; 1.819 + 1.820 + SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n"); 1.821 + if (stcb == NULL) 1.822 + return; 1.823 + 1.824 + len = ntohs(abort->ch.chunk_length); 1.825 + if (len > sizeof (struct sctp_chunkhdr)) { 1.826 + /* Need to check the cause codes for our 1.827 + * two magic nat aborts which don't kill the assoc 1.828 + * necessarily. 1.829 + */ 1.830 + struct sctp_missing_nat_state *natc; 1.831 + 1.832 + natc = (struct sctp_missing_nat_state *)(abort + 1); 1.833 + error = ntohs(natc->cause); 1.834 + if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) { 1.835 + SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 1.836 + abort->ch.chunk_flags); 1.837 + if (sctp_handle_nat_colliding_state(stcb)) { 1.838 + return; 1.839 + } 1.840 + } else if (error == SCTP_CAUSE_NAT_MISSING_STATE) { 1.841 + SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 1.842 + abort->ch.chunk_flags); 1.843 + if (sctp_handle_nat_missing_state(stcb, net)) { 1.844 + return; 1.845 + } 1.846 + } 1.847 + } else { 1.848 + error = 0; 1.849 + } 1.850 + /* stop any receive timers */ 1.851 + sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_6); 1.852 + /* notify user of the abort and clean up... */ 1.853 + sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED); 1.854 + /* free the tcb */ 1.855 + SCTP_STAT_INCR_COUNTER32(sctps_aborted); 1.856 + if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 1.857 + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 1.858 + SCTP_STAT_DECR_GAUGE32(sctps_currestab); 1.859 + } 1.860 +#ifdef SCTP_ASOCLOG_OF_TSNS 1.861 + sctp_print_out_track_log(stcb); 1.862 +#endif 1.863 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.864 + so = SCTP_INP_SO(stcb->sctp_ep); 1.865 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.866 + SCTP_TCB_UNLOCK(stcb); 1.867 + SCTP_SOCKET_LOCK(so, 1); 1.868 + SCTP_TCB_LOCK(stcb); 1.869 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.870 +#endif 1.871 + stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 1.872 + (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 1.873 + SCTP_FROM_SCTP_INPUT+SCTP_LOC_6); 1.874 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.875 + SCTP_SOCKET_UNLOCK(so, 1); 1.876 +#endif 1.877 + SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n"); 1.878 +} 1.879 + 1.880 +static void 1.881 +sctp_start_net_timers(struct sctp_tcb *stcb) 1.882 +{ 1.883 + uint32_t cnt_hb_sent; 1.884 + struct sctp_nets *net; 1.885 + 1.886 + cnt_hb_sent = 0; 1.887 + TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1.888 + /* For each network start: 1.889 + * 1) A pmtu timer. 1.890 + * 2) A HB timer 1.891 + * 3) If the dest in unconfirmed send 1.892 + * a hb as well if under max_hb_burst have 1.893 + * been sent. 1.894 + */ 1.895 + sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net); 1.896 + sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 1.897 + if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) && 1.898 + (cnt_hb_sent < SCTP_BASE_SYSCTL(sctp_hb_maxburst))) { 1.899 + sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 1.900 + cnt_hb_sent++; 1.901 + } 1.902 + } 1.903 + if (cnt_hb_sent) { 1.904 + sctp_chunk_output(stcb->sctp_ep, stcb, 1.905 + SCTP_OUTPUT_FROM_COOKIE_ACK, 1.906 + SCTP_SO_NOT_LOCKED); 1.907 + } 1.908 +} 1.909 + 1.910 + 1.911 +static void 1.912 +sctp_handle_shutdown(struct sctp_shutdown_chunk *cp, 1.913 + struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag) 1.914 +{ 1.915 + struct sctp_association *asoc; 1.916 + int some_on_streamwheel; 1.917 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.918 + struct socket *so; 1.919 +#endif 1.920 + 1.921 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.922 + "sctp_handle_shutdown: handling SHUTDOWN\n"); 1.923 + if (stcb == NULL) 1.924 + return; 1.925 + asoc = &stcb->asoc; 1.926 + if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 1.927 + (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 1.928 + return; 1.929 + } 1.930 + if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) { 1.931 + /* Shutdown NOT the expected size */ 1.932 + return; 1.933 + } else { 1.934 + sctp_update_acked(stcb, cp, abort_flag); 1.935 + if (*abort_flag) { 1.936 + return; 1.937 + } 1.938 + } 1.939 + if (asoc->control_pdapi) { 1.940 + /* With a normal shutdown 1.941 + * we assume the end of last record. 1.942 + */ 1.943 + SCTP_INP_READ_LOCK(stcb->sctp_ep); 1.944 + asoc->control_pdapi->end_added = 1; 1.945 + asoc->control_pdapi->pdapi_aborted = 1; 1.946 + asoc->control_pdapi = NULL; 1.947 + SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 1.948 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.949 + so = SCTP_INP_SO(stcb->sctp_ep); 1.950 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.951 + SCTP_TCB_UNLOCK(stcb); 1.952 + SCTP_SOCKET_LOCK(so, 1); 1.953 + SCTP_TCB_LOCK(stcb); 1.954 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.955 + if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1.956 + /* assoc was freed while we were unlocked */ 1.957 + SCTP_SOCKET_UNLOCK(so, 1); 1.958 + return; 1.959 + } 1.960 +#endif 1.961 + sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 1.962 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.963 + SCTP_SOCKET_UNLOCK(so, 1); 1.964 +#endif 1.965 + } 1.966 + /* goto SHUTDOWN_RECEIVED state to block new requests */ 1.967 + if (stcb->sctp_socket) { 1.968 + if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 1.969 + (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) && 1.970 + (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 1.971 + SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_RECEIVED); 1.972 + SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 1.973 + /* notify upper layer that peer has initiated a shutdown */ 1.974 + sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1.975 + 1.976 + /* reset time */ 1.977 + (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 1.978 + } 1.979 + } 1.980 + if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) { 1.981 + /* 1.982 + * stop the shutdown timer, since we WILL move to 1.983 + * SHUTDOWN-ACK-SENT. 1.984 + */ 1.985 + sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_8); 1.986 + } 1.987 + /* Now is there unsent data on a stream somewhere? */ 1.988 + some_on_streamwheel = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED); 1.989 + 1.990 + if (!TAILQ_EMPTY(&asoc->send_queue) || 1.991 + !TAILQ_EMPTY(&asoc->sent_queue) || 1.992 + some_on_streamwheel) { 1.993 + /* By returning we will push more data out */ 1.994 + return; 1.995 + } else { 1.996 + /* no outstanding data to send, so move on... */ 1.997 + /* send SHUTDOWN-ACK */ 1.998 + /* move to SHUTDOWN-ACK-SENT state */ 1.999 + if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) || 1.1000 + (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 1.1001 + SCTP_STAT_DECR_GAUGE32(sctps_currestab); 1.1002 + } 1.1003 + SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT); 1.1004 + SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING); 1.1005 + sctp_stop_timers_for_shutdown(stcb); 1.1006 + sctp_send_shutdown_ack(stcb, net); 1.1007 + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, 1.1008 + stcb, net); 1.1009 + } 1.1010 +} 1.1011 + 1.1012 +static void 1.1013 +sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED, 1.1014 + struct sctp_tcb *stcb, 1.1015 + struct sctp_nets *net) 1.1016 +{ 1.1017 + struct sctp_association *asoc; 1.1018 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1019 + struct socket *so; 1.1020 + 1.1021 + so = SCTP_INP_SO(stcb->sctp_ep); 1.1022 +#endif 1.1023 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.1024 + "sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n"); 1.1025 + if (stcb == NULL) 1.1026 + return; 1.1027 + 1.1028 + asoc = &stcb->asoc; 1.1029 + /* process according to association state */ 1.1030 + if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) || 1.1031 + (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) { 1.1032 + /* unexpected SHUTDOWN-ACK... do OOTB handling... */ 1.1033 + sctp_send_shutdown_complete(stcb, net, 1); 1.1034 + SCTP_TCB_UNLOCK(stcb); 1.1035 + return; 1.1036 + } 1.1037 + if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) && 1.1038 + (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) { 1.1039 + /* unexpected SHUTDOWN-ACK... so ignore... */ 1.1040 + SCTP_TCB_UNLOCK(stcb); 1.1041 + return; 1.1042 + } 1.1043 + if (asoc->control_pdapi) { 1.1044 + /* With a normal shutdown 1.1045 + * we assume the end of last record. 1.1046 + */ 1.1047 + SCTP_INP_READ_LOCK(stcb->sctp_ep); 1.1048 + asoc->control_pdapi->end_added = 1; 1.1049 + asoc->control_pdapi->pdapi_aborted = 1; 1.1050 + asoc->control_pdapi = NULL; 1.1051 + SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 1.1052 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1053 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.1054 + SCTP_TCB_UNLOCK(stcb); 1.1055 + SCTP_SOCKET_LOCK(so, 1); 1.1056 + SCTP_TCB_LOCK(stcb); 1.1057 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.1058 + if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1.1059 + /* assoc was freed while we were unlocked */ 1.1060 + SCTP_SOCKET_UNLOCK(so, 1); 1.1061 + return; 1.1062 + } 1.1063 +#endif 1.1064 + sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 1.1065 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1066 + SCTP_SOCKET_UNLOCK(so, 1); 1.1067 +#endif 1.1068 + } 1.1069 +#ifdef INVARIANTS 1.1070 + if (!TAILQ_EMPTY(&asoc->send_queue) || 1.1071 + !TAILQ_EMPTY(&asoc->sent_queue) || 1.1072 + !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 1.1073 + panic("Queues are not empty when handling SHUTDOWN-ACK"); 1.1074 + } 1.1075 +#endif 1.1076 + /* stop the timer */ 1.1077 + sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_9); 1.1078 + /* send SHUTDOWN-COMPLETE */ 1.1079 + sctp_send_shutdown_complete(stcb, net, 0); 1.1080 + /* notify upper layer protocol */ 1.1081 + if (stcb->sctp_socket) { 1.1082 + if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1.1083 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 1.1084 + stcb->sctp_socket->so_snd.sb_cc = 0; 1.1085 + } 1.1086 + sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1.1087 + } 1.1088 + SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 1.1089 + /* free the TCB but first save off the ep */ 1.1090 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1091 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.1092 + SCTP_TCB_UNLOCK(stcb); 1.1093 + SCTP_SOCKET_LOCK(so, 1); 1.1094 + SCTP_TCB_LOCK(stcb); 1.1095 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.1096 +#endif 1.1097 + (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 1.1098 + SCTP_FROM_SCTP_INPUT+SCTP_LOC_10); 1.1099 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1100 + SCTP_SOCKET_UNLOCK(so, 1); 1.1101 +#endif 1.1102 +} 1.1103 + 1.1104 +/* 1.1105 + * Skip past the param header and then we will find the chunk that caused the 1.1106 + * problem. There are two possiblities ASCONF or FWD-TSN other than that and 1.1107 + * our peer must be broken. 1.1108 + */ 1.1109 +static void 1.1110 +sctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr, 1.1111 + struct sctp_nets *net) 1.1112 +{ 1.1113 + struct sctp_chunkhdr *chk; 1.1114 + 1.1115 + chk = (struct sctp_chunkhdr *)((caddr_t)phdr + sizeof(*phdr)); 1.1116 + switch (chk->chunk_type) { 1.1117 + case SCTP_ASCONF_ACK: 1.1118 + case SCTP_ASCONF: 1.1119 + sctp_asconf_cleanup(stcb, net); 1.1120 + break; 1.1121 + case SCTP_FORWARD_CUM_TSN: 1.1122 + stcb->asoc.peer_supports_prsctp = 0; 1.1123 + break; 1.1124 + default: 1.1125 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.1126 + "Peer does not support chunk type %d(%x)??\n", 1.1127 + chk->chunk_type, (uint32_t) chk->chunk_type); 1.1128 + break; 1.1129 + } 1.1130 +} 1.1131 + 1.1132 +/* 1.1133 + * Skip past the param header and then we will find the param that caused the 1.1134 + * problem. There are a number of param's in a ASCONF OR the prsctp param 1.1135 + * these will turn of specific features. 1.1136 + */ 1.1137 +static void 1.1138 +sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr) 1.1139 +{ 1.1140 + struct sctp_paramhdr *pbad; 1.1141 + 1.1142 + pbad = phdr + 1; 1.1143 + switch (ntohs(pbad->param_type)) { 1.1144 + /* pr-sctp draft */ 1.1145 + case SCTP_PRSCTP_SUPPORTED: 1.1146 + stcb->asoc.peer_supports_prsctp = 0; 1.1147 + break; 1.1148 + case SCTP_SUPPORTED_CHUNK_EXT: 1.1149 + break; 1.1150 + /* draft-ietf-tsvwg-addip-sctp */ 1.1151 + case SCTP_HAS_NAT_SUPPORT: 1.1152 + stcb->asoc.peer_supports_nat = 0; 1.1153 + break; 1.1154 + case SCTP_ADD_IP_ADDRESS: 1.1155 + case SCTP_DEL_IP_ADDRESS: 1.1156 + case SCTP_SET_PRIM_ADDR: 1.1157 + stcb->asoc.peer_supports_asconf = 0; 1.1158 + break; 1.1159 + case SCTP_SUCCESS_REPORT: 1.1160 + case SCTP_ERROR_CAUSE_IND: 1.1161 + SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support success? or error cause?\n"); 1.1162 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.1163 + "Turning off ASCONF to this strange peer\n"); 1.1164 + stcb->asoc.peer_supports_asconf = 0; 1.1165 + break; 1.1166 + default: 1.1167 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.1168 + "Peer does not support param type %d(%x)??\n", 1.1169 + pbad->param_type, (uint32_t) pbad->param_type); 1.1170 + break; 1.1171 + } 1.1172 +} 1.1173 + 1.1174 +static int 1.1175 +sctp_handle_error(struct sctp_chunkhdr *ch, 1.1176 + struct sctp_tcb *stcb, struct sctp_nets *net) 1.1177 +{ 1.1178 + int chklen; 1.1179 + struct sctp_paramhdr *phdr; 1.1180 + uint16_t error, error_type; 1.1181 + uint16_t error_len; 1.1182 + struct sctp_association *asoc; 1.1183 + int adjust; 1.1184 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1185 + struct socket *so; 1.1186 +#endif 1.1187 + 1.1188 + /* parse through all of the errors and process */ 1.1189 + asoc = &stcb->asoc; 1.1190 + phdr = (struct sctp_paramhdr *)((caddr_t)ch + 1.1191 + sizeof(struct sctp_chunkhdr)); 1.1192 + chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr); 1.1193 + error = 0; 1.1194 + while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) { 1.1195 + /* Process an Error Cause */ 1.1196 + error_type = ntohs(phdr->param_type); 1.1197 + error_len = ntohs(phdr->param_length); 1.1198 + if ((error_len > chklen) || (error_len == 0)) { 1.1199 + /* invalid param length for this param */ 1.1200 + SCTPDBG(SCTP_DEBUG_INPUT1, "Bogus length in error param- chunk left:%d errorlen:%d\n", 1.1201 + chklen, error_len); 1.1202 + return (0); 1.1203 + } 1.1204 + if (error == 0) { 1.1205 + /* report the first error cause */ 1.1206 + error = error_type; 1.1207 + } 1.1208 + switch (error_type) { 1.1209 + case SCTP_CAUSE_INVALID_STREAM: 1.1210 + case SCTP_CAUSE_MISSING_PARAM: 1.1211 + case SCTP_CAUSE_INVALID_PARAM: 1.1212 + case SCTP_CAUSE_NO_USER_DATA: 1.1213 + SCTPDBG(SCTP_DEBUG_INPUT1, "Software error we got a %d back? We have a bug :/ (or do they?)\n", 1.1214 + error_type); 1.1215 + break; 1.1216 + case SCTP_CAUSE_NAT_COLLIDING_STATE: 1.1217 + SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", 1.1218 + ch->chunk_flags); 1.1219 + if (sctp_handle_nat_colliding_state(stcb)) { 1.1220 + return (0); 1.1221 + } 1.1222 + break; 1.1223 + case SCTP_CAUSE_NAT_MISSING_STATE: 1.1224 + SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n", 1.1225 + ch->chunk_flags); 1.1226 + if (sctp_handle_nat_missing_state(stcb, net)) { 1.1227 + return (0); 1.1228 + } 1.1229 + break; 1.1230 + case SCTP_CAUSE_STALE_COOKIE: 1.1231 + /* 1.1232 + * We only act if we have echoed a cookie and are 1.1233 + * waiting. 1.1234 + */ 1.1235 + if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 1.1236 + int *p; 1.1237 + 1.1238 + p = (int *)((caddr_t)phdr + sizeof(*phdr)); 1.1239 + /* Save the time doubled */ 1.1240 + asoc->cookie_preserve_req = ntohl(*p) << 1; 1.1241 + asoc->stale_cookie_count++; 1.1242 + if (asoc->stale_cookie_count > 1.1243 + asoc->max_init_times) { 1.1244 + sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); 1.1245 + /* now free the asoc */ 1.1246 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1247 + so = SCTP_INP_SO(stcb->sctp_ep); 1.1248 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.1249 + SCTP_TCB_UNLOCK(stcb); 1.1250 + SCTP_SOCKET_LOCK(so, 1); 1.1251 + SCTP_TCB_LOCK(stcb); 1.1252 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.1253 +#endif 1.1254 + (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, 1.1255 + SCTP_FROM_SCTP_INPUT+SCTP_LOC_11); 1.1256 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1257 + SCTP_SOCKET_UNLOCK(so, 1); 1.1258 +#endif 1.1259 + return (-1); 1.1260 + } 1.1261 + /* blast back to INIT state */ 1.1262 + sctp_toss_old_cookies(stcb, &stcb->asoc); 1.1263 + asoc->state &= ~SCTP_STATE_COOKIE_ECHOED; 1.1264 + asoc->state |= SCTP_STATE_COOKIE_WAIT; 1.1265 + sctp_stop_all_cookie_timers(stcb); 1.1266 + sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 1.1267 + } 1.1268 + break; 1.1269 + case SCTP_CAUSE_UNRESOLVABLE_ADDR: 1.1270 + /* 1.1271 + * Nothing we can do here, we don't do hostname 1.1272 + * addresses so if the peer does not like my IPv6 1.1273 + * (or IPv4 for that matter) it does not matter. If 1.1274 + * they don't support that type of address, they can 1.1275 + * NOT possibly get that packet type... i.e. with no 1.1276 + * IPv6 you can't recieve a IPv6 packet. so we can 1.1277 + * safely ignore this one. If we ever added support 1.1278 + * for HOSTNAME Addresses, then we would need to do 1.1279 + * something here. 1.1280 + */ 1.1281 + break; 1.1282 + case SCTP_CAUSE_UNRECOG_CHUNK: 1.1283 + sctp_process_unrecog_chunk(stcb, phdr, net); 1.1284 + break; 1.1285 + case SCTP_CAUSE_UNRECOG_PARAM: 1.1286 + sctp_process_unrecog_param(stcb, phdr); 1.1287 + break; 1.1288 + case SCTP_CAUSE_COOKIE_IN_SHUTDOWN: 1.1289 + /* 1.1290 + * We ignore this since the timer will drive out a 1.1291 + * new cookie anyway and there timer will drive us 1.1292 + * to send a SHUTDOWN_COMPLETE. We can't send one 1.1293 + * here since we don't have their tag. 1.1294 + */ 1.1295 + break; 1.1296 + case SCTP_CAUSE_DELETING_LAST_ADDR: 1.1297 + case SCTP_CAUSE_RESOURCE_SHORTAGE: 1.1298 + case SCTP_CAUSE_DELETING_SRC_ADDR: 1.1299 + /* 1.1300 + * We should NOT get these here, but in a 1.1301 + * ASCONF-ACK. 1.1302 + */ 1.1303 + SCTPDBG(SCTP_DEBUG_INPUT2, "Peer sends ASCONF errors in a Operational Error?<%d>?\n", 1.1304 + error_type); 1.1305 + break; 1.1306 + case SCTP_CAUSE_OUT_OF_RESC: 1.1307 + /* 1.1308 + * And what, pray tell do we do with the fact that 1.1309 + * the peer is out of resources? Not really sure we 1.1310 + * could do anything but abort. I suspect this 1.1311 + * should have came WITH an abort instead of in a 1.1312 + * OP-ERROR. 1.1313 + */ 1.1314 + break; 1.1315 + default: 1.1316 + SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_handle_error: unknown error type = 0x%xh\n", 1.1317 + error_type); 1.1318 + break; 1.1319 + } 1.1320 + adjust = SCTP_SIZE32(error_len); 1.1321 + chklen -= adjust; 1.1322 + phdr = (struct sctp_paramhdr *)((caddr_t)phdr + adjust); 1.1323 + } 1.1324 + sctp_ulp_notify(SCTP_NOTIFY_REMOTE_ERROR, stcb, error, ch, SCTP_SO_NOT_LOCKED); 1.1325 + return (0); 1.1326 +} 1.1327 + 1.1328 +static int 1.1329 +sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, 1.1330 + struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh, 1.1331 + struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb, 1.1332 + struct sctp_nets *net, int *abort_no_unlock, 1.1333 +#if defined(__FreeBSD__) 1.1334 + uint8_t use_mflowid, uint32_t mflowid, 1.1335 +#endif 1.1336 + uint32_t vrf_id) 1.1337 +{ 1.1338 + struct sctp_init_ack *init_ack; 1.1339 + struct mbuf *op_err; 1.1340 + 1.1341 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.1342 + "sctp_handle_init_ack: handling INIT-ACK\n"); 1.1343 + 1.1344 + if (stcb == NULL) { 1.1345 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.1346 + "sctp_handle_init_ack: TCB is null\n"); 1.1347 + return (-1); 1.1348 + } 1.1349 + if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) { 1.1350 + /* Invalid length */ 1.1351 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1.1352 + sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1.1353 + src, dst, sh, op_err, 1.1354 +#if defined(__FreeBSD__) 1.1355 + use_mflowid, mflowid, 1.1356 +#endif 1.1357 + vrf_id, net->port); 1.1358 + *abort_no_unlock = 1; 1.1359 + return (-1); 1.1360 + } 1.1361 + init_ack = &cp->init; 1.1362 + /* validate parameters */ 1.1363 + if (init_ack->initiate_tag == 0) { 1.1364 + /* protocol error... send an abort */ 1.1365 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1.1366 + sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1.1367 + src, dst, sh, op_err, 1.1368 +#if defined(__FreeBSD__) 1.1369 + use_mflowid, mflowid, 1.1370 +#endif 1.1371 + vrf_id, net->port); 1.1372 + *abort_no_unlock = 1; 1.1373 + return (-1); 1.1374 + } 1.1375 + if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) { 1.1376 + /* protocol error... send an abort */ 1.1377 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1.1378 + sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1.1379 + src, dst, sh, op_err, 1.1380 +#if defined(__FreeBSD__) 1.1381 + use_mflowid, mflowid, 1.1382 +#endif 1.1383 + vrf_id, net->port); 1.1384 + *abort_no_unlock = 1; 1.1385 + return (-1); 1.1386 + } 1.1387 + if (init_ack->num_inbound_streams == 0) { 1.1388 + /* protocol error... send an abort */ 1.1389 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1.1390 + sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1.1391 + src, dst, sh, op_err, 1.1392 +#if defined(__FreeBSD__) 1.1393 + use_mflowid, mflowid, 1.1394 +#endif 1.1395 + vrf_id, net->port); 1.1396 + *abort_no_unlock = 1; 1.1397 + return (-1); 1.1398 + } 1.1399 + if (init_ack->num_outbound_streams == 0) { 1.1400 + /* protocol error... send an abort */ 1.1401 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); 1.1402 + sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, 1.1403 + src, dst, sh, op_err, 1.1404 +#if defined(__FreeBSD__) 1.1405 + use_mflowid, mflowid, 1.1406 +#endif 1.1407 + vrf_id, net->port); 1.1408 + *abort_no_unlock = 1; 1.1409 + return (-1); 1.1410 + } 1.1411 + /* process according to association state... */ 1.1412 + switch (stcb->asoc.state & SCTP_STATE_MASK) { 1.1413 + case SCTP_STATE_COOKIE_WAIT: 1.1414 + /* this is the expected state for this chunk */ 1.1415 + /* process the INIT-ACK parameters */ 1.1416 + if (stcb->asoc.primary_destination->dest_state & 1.1417 + SCTP_ADDR_UNCONFIRMED) { 1.1418 + /* 1.1419 + * The primary is where we sent the INIT, we can 1.1420 + * always consider it confirmed when the INIT-ACK is 1.1421 + * returned. Do this before we load addresses 1.1422 + * though. 1.1423 + */ 1.1424 + stcb->asoc.primary_destination->dest_state &= 1.1425 + ~SCTP_ADDR_UNCONFIRMED; 1.1426 + sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 1.1427 + stcb, 0, (void *)stcb->asoc.primary_destination, SCTP_SO_NOT_LOCKED); 1.1428 + } 1.1429 + if (sctp_process_init_ack(m, iphlen, offset, src, dst, sh, cp, stcb, 1.1430 + net, abort_no_unlock, 1.1431 +#if defined(__FreeBSD__) 1.1432 + use_mflowid, mflowid, 1.1433 +#endif 1.1434 + vrf_id) < 0) { 1.1435 + /* error in parsing parameters */ 1.1436 + return (-1); 1.1437 + } 1.1438 + /* update our state */ 1.1439 + SCTPDBG(SCTP_DEBUG_INPUT2, "moving to COOKIE-ECHOED state\n"); 1.1440 + SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_ECHOED); 1.1441 + 1.1442 + /* reset the RTO calc */ 1.1443 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.1444 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.1445 + stcb->asoc.overall_error_count, 1.1446 + 0, 1.1447 + SCTP_FROM_SCTP_INPUT, 1.1448 + __LINE__); 1.1449 + } 1.1450 + stcb->asoc.overall_error_count = 0; 1.1451 + (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 1.1452 + /* 1.1453 + * collapse the init timer back in case of a exponential 1.1454 + * backoff 1.1455 + */ 1.1456 + sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep, 1.1457 + stcb, net); 1.1458 + /* 1.1459 + * the send at the end of the inbound data processing will 1.1460 + * cause the cookie to be sent 1.1461 + */ 1.1462 + break; 1.1463 + case SCTP_STATE_SHUTDOWN_SENT: 1.1464 + /* incorrect state... discard */ 1.1465 + break; 1.1466 + case SCTP_STATE_COOKIE_ECHOED: 1.1467 + /* incorrect state... discard */ 1.1468 + break; 1.1469 + case SCTP_STATE_OPEN: 1.1470 + /* incorrect state... discard */ 1.1471 + break; 1.1472 + case SCTP_STATE_EMPTY: 1.1473 + case SCTP_STATE_INUSE: 1.1474 + default: 1.1475 + /* incorrect state... discard */ 1.1476 + return (-1); 1.1477 + break; 1.1478 + } 1.1479 + SCTPDBG(SCTP_DEBUG_INPUT1, "Leaving handle-init-ack end\n"); 1.1480 + return (0); 1.1481 +} 1.1482 + 1.1483 +static struct sctp_tcb * 1.1484 +sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 1.1485 + struct sockaddr *src, struct sockaddr *dst, 1.1486 + struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 1.1487 + struct sctp_inpcb *inp, struct sctp_nets **netp, 1.1488 + struct sockaddr *init_src, int *notification, 1.1489 + int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1.1490 +#if defined(__FreeBSD__) 1.1491 + uint8_t use_mflowid, uint32_t mflowid, 1.1492 +#endif 1.1493 + uint32_t vrf_id, uint16_t port); 1.1494 + 1.1495 + 1.1496 +/* 1.1497 + * handle a state cookie for an existing association m: input packet mbuf 1.1498 + * chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a 1.1499 + * "split" mbuf and the cookie signature does not exist offset: offset into 1.1500 + * mbuf to the cookie-echo chunk 1.1501 + */ 1.1502 +static struct sctp_tcb * 1.1503 +sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, 1.1504 + struct sockaddr *src, struct sockaddr *dst, 1.1505 + struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 1.1506 + struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp, 1.1507 + struct sockaddr *init_src, int *notification, 1.1508 + int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1.1509 +#if defined(__FreeBSD__) 1.1510 + uint8_t use_mflowid, uint32_t mflowid, 1.1511 +#endif 1.1512 + uint32_t vrf_id, uint16_t port) 1.1513 +{ 1.1514 + struct sctp_association *asoc; 1.1515 + struct sctp_init_chunk *init_cp, init_buf; 1.1516 + struct sctp_init_ack_chunk *initack_cp, initack_buf; 1.1517 + struct sctp_nets *net; 1.1518 + struct mbuf *op_err; 1.1519 + struct sctp_paramhdr *ph; 1.1520 + int init_offset, initack_offset, i; 1.1521 + int retval; 1.1522 + int spec_flag = 0; 1.1523 + uint32_t how_indx; 1.1524 + 1.1525 + net = *netp; 1.1526 + /* I know that the TCB is non-NULL from the caller */ 1.1527 + asoc = &stcb->asoc; 1.1528 + for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); how_indx++) { 1.1529 + if (asoc->cookie_how[how_indx] == 0) 1.1530 + break; 1.1531 + } 1.1532 + if (how_indx < sizeof(asoc->cookie_how)) { 1.1533 + asoc->cookie_how[how_indx] = 1; 1.1534 + } 1.1535 + if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 1.1536 + /* SHUTDOWN came in after sending INIT-ACK */ 1.1537 + sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination); 1.1538 + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 1.1539 + 0, M_NOWAIT, 1, MT_DATA); 1.1540 + if (op_err == NULL) { 1.1541 + /* FOOBAR */ 1.1542 + return (NULL); 1.1543 + } 1.1544 + /* Set the len */ 1.1545 + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); 1.1546 + ph = mtod(op_err, struct sctp_paramhdr *); 1.1547 + ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN); 1.1548 + ph->param_length = htons(sizeof(struct sctp_paramhdr)); 1.1549 + sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, 1.1550 +#if defined(__FreeBSD__) 1.1551 + use_mflowid, mflowid, 1.1552 +#endif 1.1553 + vrf_id, net->port); 1.1554 + if (how_indx < sizeof(asoc->cookie_how)) 1.1555 + asoc->cookie_how[how_indx] = 2; 1.1556 + return (NULL); 1.1557 + } 1.1558 + /* 1.1559 + * find and validate the INIT chunk in the cookie (peer's info) the 1.1560 + * INIT should start after the cookie-echo header struct (chunk 1.1561 + * header, state cookie header struct) 1.1562 + */ 1.1563 + init_offset = offset += sizeof(struct sctp_cookie_echo_chunk); 1.1564 + 1.1565 + init_cp = (struct sctp_init_chunk *) 1.1566 + sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 1.1567 + (uint8_t *) & init_buf); 1.1568 + if (init_cp == NULL) { 1.1569 + /* could not pull a INIT chunk in cookie */ 1.1570 + return (NULL); 1.1571 + } 1.1572 + if (init_cp->ch.chunk_type != SCTP_INITIATION) { 1.1573 + return (NULL); 1.1574 + } 1.1575 + /* 1.1576 + * find and validate the INIT-ACK chunk in the cookie (my info) the 1.1577 + * INIT-ACK follows the INIT chunk 1.1578 + */ 1.1579 + initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 1.1580 + initack_cp = (struct sctp_init_ack_chunk *) 1.1581 + sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 1.1582 + (uint8_t *) & initack_buf); 1.1583 + if (initack_cp == NULL) { 1.1584 + /* could not pull INIT-ACK chunk in cookie */ 1.1585 + return (NULL); 1.1586 + } 1.1587 + if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 1.1588 + return (NULL); 1.1589 + } 1.1590 + if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1.1591 + (ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag)) { 1.1592 + /* 1.1593 + * case D in Section 5.2.4 Table 2: MMAA process accordingly 1.1594 + * to get into the OPEN state 1.1595 + */ 1.1596 + if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 1.1597 + /*- 1.1598 + * Opps, this means that we somehow generated two vtag's 1.1599 + * the same. I.e. we did: 1.1600 + * Us Peer 1.1601 + * <---INIT(tag=a)------ 1.1602 + * ----INIT-ACK(tag=t)--> 1.1603 + * ----INIT(tag=t)------> *1 1.1604 + * <---INIT-ACK(tag=a)--- 1.1605 + * <----CE(tag=t)------------- *2 1.1606 + * 1.1607 + * At point *1 we should be generating a different 1.1608 + * tag t'. Which means we would throw away the CE and send 1.1609 + * ours instead. Basically this is case C (throw away side). 1.1610 + */ 1.1611 + if (how_indx < sizeof(asoc->cookie_how)) 1.1612 + asoc->cookie_how[how_indx] = 17; 1.1613 + return (NULL); 1.1614 + 1.1615 + } 1.1616 + switch (SCTP_GET_STATE(asoc)) { 1.1617 + case SCTP_STATE_COOKIE_WAIT: 1.1618 + case SCTP_STATE_COOKIE_ECHOED: 1.1619 + /* 1.1620 + * INIT was sent but got a COOKIE_ECHO with the 1.1621 + * correct tags... just accept it...but we must 1.1622 + * process the init so that we can make sure we 1.1623 + * have the right seq no's. 1.1624 + */ 1.1625 + /* First we must process the INIT !! */ 1.1626 + retval = sctp_process_init(init_cp, stcb); 1.1627 + if (retval < 0) { 1.1628 + if (how_indx < sizeof(asoc->cookie_how)) 1.1629 + asoc->cookie_how[how_indx] = 3; 1.1630 + return (NULL); 1.1631 + } 1.1632 + /* we have already processed the INIT so no problem */ 1.1633 + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, 1.1634 + net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_12); 1.1635 + sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_13); 1.1636 + /* update current state */ 1.1637 + if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 1.1638 + SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 1.1639 + else 1.1640 + SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1.1641 + 1.1642 + SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1.1643 + if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1.1644 + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1.1645 + stcb->sctp_ep, stcb, asoc->primary_destination); 1.1646 + } 1.1647 + SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1.1648 + sctp_stop_all_cookie_timers(stcb); 1.1649 + if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1.1650 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1.1651 + (inp->sctp_socket->so_qlimit == 0) 1.1652 + ) { 1.1653 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1654 + struct socket *so; 1.1655 +#endif 1.1656 + /* 1.1657 + * Here is where collision would go if we 1.1658 + * did a connect() and instead got a 1.1659 + * init/init-ack/cookie done before the 1.1660 + * init-ack came back.. 1.1661 + */ 1.1662 + stcb->sctp_ep->sctp_flags |= 1.1663 + SCTP_PCB_FLAGS_CONNECTED; 1.1664 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1665 + so = SCTP_INP_SO(stcb->sctp_ep); 1.1666 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.1667 + SCTP_TCB_UNLOCK(stcb); 1.1668 + SCTP_SOCKET_LOCK(so, 1); 1.1669 + SCTP_TCB_LOCK(stcb); 1.1670 + atomic_add_int(&stcb->asoc.refcnt, -1); 1.1671 + if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1.1672 + SCTP_SOCKET_UNLOCK(so, 1); 1.1673 + return (NULL); 1.1674 + } 1.1675 +#endif 1.1676 + soisconnected(stcb->sctp_socket); 1.1677 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1678 + SCTP_SOCKET_UNLOCK(so, 1); 1.1679 +#endif 1.1680 + } 1.1681 + /* notify upper layer */ 1.1682 + *notification = SCTP_NOTIFY_ASSOC_UP; 1.1683 + /* 1.1684 + * since we did not send a HB make sure we 1.1685 + * don't double things 1.1686 + */ 1.1687 + net->hb_responded = 1; 1.1688 + net->RTO = sctp_calculate_rto(stcb, asoc, net, 1.1689 + &cookie->time_entered, 1.1690 + sctp_align_unsafe_makecopy, 1.1691 + SCTP_RTT_FROM_NON_DATA); 1.1692 + 1.1693 + if (stcb->asoc.sctp_autoclose_ticks && 1.1694 + (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) { 1.1695 + sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 1.1696 + inp, stcb, NULL); 1.1697 + } 1.1698 + break; 1.1699 + default: 1.1700 + /* 1.1701 + * we're in the OPEN state (or beyond), so 1.1702 + * peer must have simply lost the COOKIE-ACK 1.1703 + */ 1.1704 + break; 1.1705 + } /* end switch */ 1.1706 + sctp_stop_all_cookie_timers(stcb); 1.1707 + /* 1.1708 + * We ignore the return code here.. not sure if we should 1.1709 + * somehow abort.. but we do have an existing asoc. This 1.1710 + * really should not fail. 1.1711 + */ 1.1712 + if (sctp_load_addresses_from_init(stcb, m, 1.1713 + init_offset + sizeof(struct sctp_init_chunk), 1.1714 + initack_offset, src, dst, init_src)) { 1.1715 + if (how_indx < sizeof(asoc->cookie_how)) 1.1716 + asoc->cookie_how[how_indx] = 4; 1.1717 + return (NULL); 1.1718 + } 1.1719 + /* respond with a COOKIE-ACK */ 1.1720 + sctp_toss_old_cookies(stcb, asoc); 1.1721 + sctp_send_cookie_ack(stcb); 1.1722 + if (how_indx < sizeof(asoc->cookie_how)) 1.1723 + asoc->cookie_how[how_indx] = 5; 1.1724 + return (stcb); 1.1725 + } 1.1726 + 1.1727 + if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 1.1728 + ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag && 1.1729 + cookie->tie_tag_my_vtag == 0 && 1.1730 + cookie->tie_tag_peer_vtag == 0) { 1.1731 + /* 1.1732 + * case C in Section 5.2.4 Table 2: XMOO silently discard 1.1733 + */ 1.1734 + if (how_indx < sizeof(asoc->cookie_how)) 1.1735 + asoc->cookie_how[how_indx] = 6; 1.1736 + return (NULL); 1.1737 + } 1.1738 + /* If nat support, and the below and stcb is established, 1.1739 + * send back a ABORT(colliding state) if we are established. 1.1740 + */ 1.1741 + if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) && 1.1742 + (asoc->peer_supports_nat) && 1.1743 + ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1.1744 + ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 1.1745 + (asoc->peer_vtag == 0)))) { 1.1746 + /* Special case - Peer's support nat. We may have 1.1747 + * two init's that we gave out the same tag on since 1.1748 + * one was not established.. i.e. we get INIT from host-1 1.1749 + * behind the nat and we respond tag-a, we get a INIT from 1.1750 + * host-2 behind the nat and we get tag-a again. Then we 1.1751 + * bring up host-1 (or 2's) assoc, Then comes the cookie 1.1752 + * from hsot-2 (or 1). Now we have colliding state. We must 1.1753 + * send an abort here with colliding state indication. 1.1754 + */ 1.1755 + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 1.1756 + 0, M_NOWAIT, 1, MT_DATA); 1.1757 + if (op_err == NULL) { 1.1758 + /* FOOBAR */ 1.1759 + return (NULL); 1.1760 + } 1.1761 + /* pre-reserve some space */ 1.1762 +#ifdef INET6 1.1763 + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); 1.1764 +#else 1.1765 + SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); 1.1766 +#endif 1.1767 + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); 1.1768 + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); 1.1769 + /* Set the len */ 1.1770 + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); 1.1771 + ph = mtod(op_err, struct sctp_paramhdr *); 1.1772 + ph->param_type = htons(SCTP_CAUSE_NAT_COLLIDING_STATE); 1.1773 + ph->param_length = htons(sizeof(struct sctp_paramhdr)); 1.1774 + sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, 1.1775 +#if defined(__FreeBSD__) 1.1776 + use_mflowid, mflowid, 1.1777 +#endif 1.1778 + vrf_id, port); 1.1779 + return (NULL); 1.1780 + } 1.1781 + if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) && 1.1782 + ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) || 1.1783 + (asoc->peer_vtag == 0))) { 1.1784 + /* 1.1785 + * case B in Section 5.2.4 Table 2: MXAA or MOAA my info 1.1786 + * should be ok, re-accept peer info 1.1787 + */ 1.1788 + if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { 1.1789 + /* Extension of case C. 1.1790 + * If we hit this, then the random number 1.1791 + * generator returned the same vtag when we 1.1792 + * first sent our INIT-ACK and when we later sent 1.1793 + * our INIT. The side with the seq numbers that are 1.1794 + * different will be the one that normnally would 1.1795 + * have hit case C. This in effect "extends" our vtags 1.1796 + * in this collision case to be 64 bits. The same collision 1.1797 + * could occur aka you get both vtag and seq number the 1.1798 + * same twice in a row.. but is much less likely. If it 1.1799 + * did happen then we would proceed through and bring 1.1800 + * up the assoc.. we may end up with the wrong stream 1.1801 + * setup however.. which would be bad.. but there is 1.1802 + * no way to tell.. until we send on a stream that does 1.1803 + * not exist :-) 1.1804 + */ 1.1805 + if (how_indx < sizeof(asoc->cookie_how)) 1.1806 + asoc->cookie_how[how_indx] = 7; 1.1807 + 1.1808 + return (NULL); 1.1809 + } 1.1810 + if (how_indx < sizeof(asoc->cookie_how)) 1.1811 + asoc->cookie_how[how_indx] = 8; 1.1812 + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_14); 1.1813 + sctp_stop_all_cookie_timers(stcb); 1.1814 + /* 1.1815 + * since we did not send a HB make sure we don't double 1.1816 + * things 1.1817 + */ 1.1818 + net->hb_responded = 1; 1.1819 + if (stcb->asoc.sctp_autoclose_ticks && 1.1820 + sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 1.1821 + sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, 1.1822 + NULL); 1.1823 + } 1.1824 + asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 1.1825 + asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 1.1826 + 1.1827 + if (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) { 1.1828 + /* Ok the peer probably discarded our 1.1829 + * data (if we echoed a cookie+data). So anything 1.1830 + * on the sent_queue should be marked for 1.1831 + * retransmit, we may not get something to 1.1832 + * kick us so it COULD still take a timeout 1.1833 + * to move these.. but it can't hurt to mark them. 1.1834 + */ 1.1835 + struct sctp_tmit_chunk *chk; 1.1836 + TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 1.1837 + if (chk->sent < SCTP_DATAGRAM_RESEND) { 1.1838 + chk->sent = SCTP_DATAGRAM_RESEND; 1.1839 + sctp_flight_size_decrease(chk); 1.1840 + sctp_total_flight_decrease(stcb, chk); 1.1841 + sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1.1842 + spec_flag++; 1.1843 + } 1.1844 + } 1.1845 + 1.1846 + } 1.1847 + /* process the INIT info (peer's info) */ 1.1848 + retval = sctp_process_init(init_cp, stcb); 1.1849 + if (retval < 0) { 1.1850 + if (how_indx < sizeof(asoc->cookie_how)) 1.1851 + asoc->cookie_how[how_indx] = 9; 1.1852 + return (NULL); 1.1853 + } 1.1854 + if (sctp_load_addresses_from_init(stcb, m, 1.1855 + init_offset + sizeof(struct sctp_init_chunk), 1.1856 + initack_offset, src, dst, init_src)) { 1.1857 + if (how_indx < sizeof(asoc->cookie_how)) 1.1858 + asoc->cookie_how[how_indx] = 10; 1.1859 + return (NULL); 1.1860 + } 1.1861 + if ((asoc->state & SCTP_STATE_COOKIE_WAIT) || 1.1862 + (asoc->state & SCTP_STATE_COOKIE_ECHOED)) { 1.1863 + *notification = SCTP_NOTIFY_ASSOC_UP; 1.1864 + 1.1865 + if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1.1866 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1.1867 + (inp->sctp_socket->so_qlimit == 0)) { 1.1868 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1869 + struct socket *so; 1.1870 +#endif 1.1871 + stcb->sctp_ep->sctp_flags |= 1.1872 + SCTP_PCB_FLAGS_CONNECTED; 1.1873 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1874 + so = SCTP_INP_SO(stcb->sctp_ep); 1.1875 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.1876 + SCTP_TCB_UNLOCK(stcb); 1.1877 + SCTP_SOCKET_LOCK(so, 1); 1.1878 + SCTP_TCB_LOCK(stcb); 1.1879 + atomic_add_int(&stcb->asoc.refcnt, -1); 1.1880 + if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1.1881 + SCTP_SOCKET_UNLOCK(so, 1); 1.1882 + return (NULL); 1.1883 + } 1.1884 +#endif 1.1885 + soisconnected(stcb->sctp_socket); 1.1886 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1887 + SCTP_SOCKET_UNLOCK(so, 1); 1.1888 +#endif 1.1889 + } 1.1890 + if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) 1.1891 + SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 1.1892 + else 1.1893 + SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1.1894 + SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1.1895 + } else if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 1.1896 + SCTP_STAT_INCR_COUNTER32(sctps_restartestab); 1.1897 + } else { 1.1898 + SCTP_STAT_INCR_COUNTER32(sctps_collisionestab); 1.1899 + } 1.1900 + SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1.1901 + if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1.1902 + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1.1903 + stcb->sctp_ep, stcb, asoc->primary_destination); 1.1904 + } 1.1905 + sctp_stop_all_cookie_timers(stcb); 1.1906 + sctp_toss_old_cookies(stcb, asoc); 1.1907 + sctp_send_cookie_ack(stcb); 1.1908 + if (spec_flag) { 1.1909 + /* only if we have retrans set do we do this. What 1.1910 + * this call does is get only the COOKIE-ACK out 1.1911 + * and then when we return the normal call to 1.1912 + * sctp_chunk_output will get the retrans out 1.1913 + * behind this. 1.1914 + */ 1.1915 + sctp_chunk_output(inp,stcb, SCTP_OUTPUT_FROM_COOKIE_ACK, SCTP_SO_NOT_LOCKED); 1.1916 + } 1.1917 + if (how_indx < sizeof(asoc->cookie_how)) 1.1918 + asoc->cookie_how[how_indx] = 11; 1.1919 + 1.1920 + return (stcb); 1.1921 + } 1.1922 + if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && 1.1923 + ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) && 1.1924 + cookie->tie_tag_my_vtag == asoc->my_vtag_nonce && 1.1925 + cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce && 1.1926 + cookie->tie_tag_peer_vtag != 0) { 1.1927 + struct sctpasochead *head; 1.1928 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1929 + struct socket *so; 1.1930 +#endif 1.1931 + 1.1932 + if (asoc->peer_supports_nat) { 1.1933 + /* This is a gross gross hack. 1.1934 + * Just call the cookie_new code since we 1.1935 + * are allowing a duplicate association. 1.1936 + * I hope this works... 1.1937 + */ 1.1938 + return (sctp_process_cookie_new(m, iphlen, offset, src, dst, 1.1939 + sh, cookie, cookie_len, 1.1940 + inp, netp, init_src,notification, 1.1941 + auth_skipped, auth_offset, auth_len, 1.1942 +#if defined(__FreeBSD__) 1.1943 + use_mflowid, mflowid, 1.1944 +#endif 1.1945 + vrf_id, port)); 1.1946 + } 1.1947 + /* 1.1948 + * case A in Section 5.2.4 Table 2: XXMM (peer restarted) 1.1949 + */ 1.1950 + /* temp code */ 1.1951 + if (how_indx < sizeof(asoc->cookie_how)) 1.1952 + asoc->cookie_how[how_indx] = 12; 1.1953 + sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_15); 1.1954 + sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_16); 1.1955 + 1.1956 + /* notify upper layer */ 1.1957 + *notification = SCTP_NOTIFY_ASSOC_RESTART; 1.1958 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.1959 + if ((SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN) && 1.1960 + (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) && 1.1961 + (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) { 1.1962 + SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1.1963 + } 1.1964 + if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) { 1.1965 + SCTP_STAT_INCR_GAUGE32(sctps_restartestab); 1.1966 + } else if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) { 1.1967 + SCTP_STAT_INCR_GAUGE32(sctps_collisionestab); 1.1968 + } 1.1969 + if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1.1970 + SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1.1971 + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1.1972 + stcb->sctp_ep, stcb, asoc->primary_destination); 1.1973 + 1.1974 + } else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) { 1.1975 + /* move to OPEN state, if not in SHUTDOWN_SENT */ 1.1976 + SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1.1977 + } 1.1978 + asoc->pre_open_streams = 1.1979 + ntohs(initack_cp->init.num_outbound_streams); 1.1980 + asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 1.1981 + asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 1.1982 + asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 1.1983 + 1.1984 + asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 1.1985 + 1.1986 + asoc->str_reset_seq_in = asoc->init_seq_number; 1.1987 + 1.1988 + asoc->advanced_peer_ack_point = asoc->last_acked_seq; 1.1989 + if (asoc->mapping_array) { 1.1990 + memset(asoc->mapping_array, 0, 1.1991 + asoc->mapping_array_size); 1.1992 + } 1.1993 + if (asoc->nr_mapping_array) { 1.1994 + memset(asoc->nr_mapping_array, 0, 1.1995 + asoc->mapping_array_size); 1.1996 + } 1.1997 + SCTP_TCB_UNLOCK(stcb); 1.1998 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1999 + so = SCTP_INP_SO(stcb->sctp_ep); 1.2000 + SCTP_SOCKET_LOCK(so, 1); 1.2001 +#endif 1.2002 + SCTP_INP_INFO_WLOCK(); 1.2003 + SCTP_INP_WLOCK(stcb->sctp_ep); 1.2004 + SCTP_TCB_LOCK(stcb); 1.2005 + atomic_add_int(&stcb->asoc.refcnt, -1); 1.2006 + /* send up all the data */ 1.2007 + SCTP_TCB_SEND_LOCK(stcb); 1.2008 + 1.2009 + sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED); 1.2010 + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 1.2011 + stcb->asoc.strmout[i].chunks_on_queues = 0; 1.2012 + stcb->asoc.strmout[i].stream_no = i; 1.2013 + stcb->asoc.strmout[i].next_sequence_send = 0; 1.2014 + stcb->asoc.strmout[i].last_msg_incomplete = 0; 1.2015 + } 1.2016 + /* process the INIT-ACK info (my info) */ 1.2017 + asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 1.2018 + asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 1.2019 + 1.2020 + /* pull from vtag hash */ 1.2021 + LIST_REMOVE(stcb, sctp_asocs); 1.2022 + /* re-insert to new vtag position */ 1.2023 + head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, 1.2024 + SCTP_BASE_INFO(hashasocmark))]; 1.2025 + /* 1.2026 + * put it in the bucket in the vtag hash of assoc's for the 1.2027 + * system 1.2028 + */ 1.2029 + LIST_INSERT_HEAD(head, stcb, sctp_asocs); 1.2030 + 1.2031 + SCTP_TCB_SEND_UNLOCK(stcb); 1.2032 + SCTP_INP_WUNLOCK(stcb->sctp_ep); 1.2033 + SCTP_INP_INFO_WUNLOCK(); 1.2034 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2035 + SCTP_SOCKET_UNLOCK(so, 1); 1.2036 +#endif 1.2037 + asoc->total_flight = 0; 1.2038 + asoc->total_flight_count = 0; 1.2039 + /* process the INIT info (peer's info) */ 1.2040 + retval = sctp_process_init(init_cp, stcb); 1.2041 + if (retval < 0) { 1.2042 + if (how_indx < sizeof(asoc->cookie_how)) 1.2043 + asoc->cookie_how[how_indx] = 13; 1.2044 + 1.2045 + return (NULL); 1.2046 + } 1.2047 + /* 1.2048 + * since we did not send a HB make sure we don't double 1.2049 + * things 1.2050 + */ 1.2051 + net->hb_responded = 1; 1.2052 + 1.2053 + if (sctp_load_addresses_from_init(stcb, m, 1.2054 + init_offset + sizeof(struct sctp_init_chunk), 1.2055 + initack_offset, src, dst, init_src)) { 1.2056 + if (how_indx < sizeof(asoc->cookie_how)) 1.2057 + asoc->cookie_how[how_indx] = 14; 1.2058 + 1.2059 + return (NULL); 1.2060 + } 1.2061 + /* respond with a COOKIE-ACK */ 1.2062 + sctp_stop_all_cookie_timers(stcb); 1.2063 + sctp_toss_old_cookies(stcb, asoc); 1.2064 + sctp_send_cookie_ack(stcb); 1.2065 + if (how_indx < sizeof(asoc->cookie_how)) 1.2066 + asoc->cookie_how[how_indx] = 15; 1.2067 + 1.2068 + return (stcb); 1.2069 + } 1.2070 + if (how_indx < sizeof(asoc->cookie_how)) 1.2071 + asoc->cookie_how[how_indx] = 16; 1.2072 + /* all other cases... */ 1.2073 + return (NULL); 1.2074 +} 1.2075 + 1.2076 + 1.2077 +/* 1.2078 + * handle a state cookie for a new association m: input packet mbuf chain-- 1.2079 + * assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a "split" mbuf 1.2080 + * and the cookie signature does not exist offset: offset into mbuf to the 1.2081 + * cookie-echo chunk length: length of the cookie chunk to: where the init 1.2082 + * was from returns a new TCB 1.2083 + */ 1.2084 +static struct sctp_tcb * 1.2085 +sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, 1.2086 + struct sockaddr *src, struct sockaddr *dst, 1.2087 + struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len, 1.2088 + struct sctp_inpcb *inp, struct sctp_nets **netp, 1.2089 + struct sockaddr *init_src, int *notification, 1.2090 + int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1.2091 +#if defined(__FreeBSD__) 1.2092 + uint8_t use_mflowid, uint32_t mflowid, 1.2093 +#endif 1.2094 + uint32_t vrf_id, uint16_t port) 1.2095 +{ 1.2096 + struct sctp_tcb *stcb; 1.2097 + struct sctp_init_chunk *init_cp, init_buf; 1.2098 + struct sctp_init_ack_chunk *initack_cp, initack_buf; 1.2099 + struct sockaddr_storage sa_store; 1.2100 + struct sockaddr *initack_src = (struct sockaddr *)&sa_store; 1.2101 + struct sctp_association *asoc; 1.2102 + int init_offset, initack_offset, initack_limit; 1.2103 + int retval; 1.2104 + int error = 0; 1.2105 + uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE]; 1.2106 +#ifdef INET 1.2107 + struct sockaddr_in *sin; 1.2108 +#endif 1.2109 +#ifdef INET6 1.2110 + struct sockaddr_in6 *sin6; 1.2111 +#endif 1.2112 +#if defined(__Userspace__) 1.2113 + struct sockaddr_conn *sconn; 1.2114 +#endif 1.2115 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2116 + struct socket *so; 1.2117 + 1.2118 + so = SCTP_INP_SO(inp); 1.2119 +#endif 1.2120 + 1.2121 + /* 1.2122 + * find and validate the INIT chunk in the cookie (peer's info) the 1.2123 + * INIT should start after the cookie-echo header struct (chunk 1.2124 + * header, state cookie header struct) 1.2125 + */ 1.2126 + init_offset = offset + sizeof(struct sctp_cookie_echo_chunk); 1.2127 + init_cp = (struct sctp_init_chunk *) 1.2128 + sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk), 1.2129 + (uint8_t *) & init_buf); 1.2130 + if (init_cp == NULL) { 1.2131 + /* could not pull a INIT chunk in cookie */ 1.2132 + SCTPDBG(SCTP_DEBUG_INPUT1, 1.2133 + "process_cookie_new: could not pull INIT chunk hdr\n"); 1.2134 + return (NULL); 1.2135 + } 1.2136 + if (init_cp->ch.chunk_type != SCTP_INITIATION) { 1.2137 + SCTPDBG(SCTP_DEBUG_INPUT1, "HUH? process_cookie_new: could not find INIT chunk!\n"); 1.2138 + return (NULL); 1.2139 + } 1.2140 + initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length)); 1.2141 + /* 1.2142 + * find and validate the INIT-ACK chunk in the cookie (my info) the 1.2143 + * INIT-ACK follows the INIT chunk 1.2144 + */ 1.2145 + initack_cp = (struct sctp_init_ack_chunk *) 1.2146 + sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk), 1.2147 + (uint8_t *) & initack_buf); 1.2148 + if (initack_cp == NULL) { 1.2149 + /* could not pull INIT-ACK chunk in cookie */ 1.2150 + SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: could not pull INIT-ACK chunk hdr\n"); 1.2151 + return (NULL); 1.2152 + } 1.2153 + if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) { 1.2154 + return (NULL); 1.2155 + } 1.2156 + /* 1.2157 + * NOTE: We can't use the INIT_ACK's chk_length to determine the 1.2158 + * "initack_limit" value. This is because the chk_length field 1.2159 + * includes the length of the cookie, but the cookie is omitted when 1.2160 + * the INIT and INIT_ACK are tacked onto the cookie... 1.2161 + */ 1.2162 + initack_limit = offset + cookie_len; 1.2163 + 1.2164 + /* 1.2165 + * now that we know the INIT/INIT-ACK are in place, create a new TCB 1.2166 + * and popluate 1.2167 + */ 1.2168 + 1.2169 + /* 1.2170 + * Here we do a trick, we set in NULL for the proc/thread argument. We 1.2171 + * do this since in effect we only use the p argument when 1.2172 + * the socket is unbound and we must do an implicit bind. 1.2173 + * Since we are getting a cookie, we cannot be unbound. 1.2174 + */ 1.2175 + stcb = sctp_aloc_assoc(inp, init_src, &error, 1.2176 + ntohl(initack_cp->init.initiate_tag), vrf_id, 1.2177 +#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 1.2178 + (struct thread *)NULL 1.2179 +#elif defined(__Windows__) 1.2180 + (PKTHREAD)NULL 1.2181 +#else 1.2182 + (struct proc *)NULL 1.2183 +#endif 1.2184 + ); 1.2185 + if (stcb == NULL) { 1.2186 + struct mbuf *op_err; 1.2187 + 1.2188 + /* memory problem? */ 1.2189 + SCTPDBG(SCTP_DEBUG_INPUT1, 1.2190 + "process_cookie_new: no room for another TCB!\n"); 1.2191 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); 1.2192 + 1.2193 + sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 1.2194 + src, dst, sh, op_err, 1.2195 +#if defined(__FreeBSD__) 1.2196 + use_mflowid, mflowid, 1.2197 +#endif 1.2198 + vrf_id, port); 1.2199 + return (NULL); 1.2200 + } 1.2201 + /* get the correct sctp_nets */ 1.2202 + if (netp) 1.2203 + *netp = sctp_findnet(stcb, init_src); 1.2204 + 1.2205 + asoc = &stcb->asoc; 1.2206 + /* get scope variables out of cookie */ 1.2207 + asoc->scope.ipv4_local_scope = cookie->ipv4_scope; 1.2208 + asoc->scope.site_scope = cookie->site_scope; 1.2209 + asoc->scope.local_scope = cookie->local_scope; 1.2210 + asoc->scope.loopback_scope = cookie->loopback_scope; 1.2211 + 1.2212 +#if defined(__Userspace__) 1.2213 + if ((asoc->scope.ipv4_addr_legal != cookie->ipv4_addr_legal) || 1.2214 + (asoc->scope.ipv6_addr_legal != cookie->ipv6_addr_legal) || 1.2215 + (asoc->scope.conn_addr_legal != cookie->conn_addr_legal)) { 1.2216 +#else 1.2217 + if ((asoc->scope.ipv4_addr_legal != cookie->ipv4_addr_legal) || 1.2218 + (asoc->scope.ipv6_addr_legal != cookie->ipv6_addr_legal)) { 1.2219 +#endif 1.2220 + struct mbuf *op_err; 1.2221 + 1.2222 + /* 1.2223 + * Houston we have a problem. The EP changed while the 1.2224 + * cookie was in flight. Only recourse is to abort the 1.2225 + * association. 1.2226 + */ 1.2227 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.2228 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); 1.2229 + sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, 1.2230 + src, dst, sh, op_err, 1.2231 +#if defined(__FreeBSD__) 1.2232 + use_mflowid, mflowid, 1.2233 +#endif 1.2234 + vrf_id, port); 1.2235 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2236 + SCTP_TCB_UNLOCK(stcb); 1.2237 + SCTP_SOCKET_LOCK(so, 1); 1.2238 + SCTP_TCB_LOCK(stcb); 1.2239 +#endif 1.2240 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 1.2241 + SCTP_FROM_SCTP_INPUT+SCTP_LOC_16); 1.2242 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2243 + SCTP_SOCKET_UNLOCK(so, 1); 1.2244 +#endif 1.2245 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.2246 + return (NULL); 1.2247 + } 1.2248 + /* process the INIT-ACK info (my info) */ 1.2249 + asoc->my_vtag = ntohl(initack_cp->init.initiate_tag); 1.2250 + asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd); 1.2251 + asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams); 1.2252 + asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn); 1.2253 + asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number; 1.2254 + asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 1.2255 + asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1; 1.2256 + asoc->str_reset_seq_in = asoc->init_seq_number; 1.2257 + 1.2258 + asoc->advanced_peer_ack_point = asoc->last_acked_seq; 1.2259 + 1.2260 + /* process the INIT info (peer's info) */ 1.2261 + if (netp) 1.2262 + retval = sctp_process_init(init_cp, stcb); 1.2263 + else 1.2264 + retval = 0; 1.2265 + if (retval < 0) { 1.2266 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.2267 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2268 + SCTP_TCB_UNLOCK(stcb); 1.2269 + SCTP_SOCKET_LOCK(so, 1); 1.2270 + SCTP_TCB_LOCK(stcb); 1.2271 +#endif 1.2272 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_16); 1.2273 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2274 + SCTP_SOCKET_UNLOCK(so, 1); 1.2275 +#endif 1.2276 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.2277 + return (NULL); 1.2278 + } 1.2279 + /* load all addresses */ 1.2280 + if (sctp_load_addresses_from_init(stcb, m, 1.2281 + init_offset + sizeof(struct sctp_init_chunk), initack_offset, 1.2282 + src, dst, init_src)) { 1.2283 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.2284 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2285 + SCTP_TCB_UNLOCK(stcb); 1.2286 + SCTP_SOCKET_LOCK(so, 1); 1.2287 + SCTP_TCB_LOCK(stcb); 1.2288 +#endif 1.2289 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_17); 1.2290 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2291 + SCTP_SOCKET_UNLOCK(so, 1); 1.2292 +#endif 1.2293 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.2294 + return (NULL); 1.2295 + } 1.2296 + /* 1.2297 + * verify any preceding AUTH chunk that was skipped 1.2298 + */ 1.2299 + /* pull the local authentication parameters from the cookie/init-ack */ 1.2300 + sctp_auth_get_cookie_params(stcb, m, 1.2301 + initack_offset + sizeof(struct sctp_init_ack_chunk), 1.2302 + initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk))); 1.2303 + if (auth_skipped) { 1.2304 + struct sctp_auth_chunk *auth; 1.2305 + 1.2306 + auth = (struct sctp_auth_chunk *) 1.2307 + sctp_m_getptr(m, auth_offset, auth_len, auth_chunk_buf); 1.2308 + if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, auth_offset)) { 1.2309 + /* auth HMAC failed, dump the assoc and packet */ 1.2310 + SCTPDBG(SCTP_DEBUG_AUTH1, 1.2311 + "COOKIE-ECHO: AUTH failed\n"); 1.2312 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.2313 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2314 + SCTP_TCB_UNLOCK(stcb); 1.2315 + SCTP_SOCKET_LOCK(so, 1); 1.2316 + SCTP_TCB_LOCK(stcb); 1.2317 +#endif 1.2318 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_18); 1.2319 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2320 + SCTP_SOCKET_UNLOCK(so, 1); 1.2321 +#endif 1.2322 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.2323 + return (NULL); 1.2324 + } else { 1.2325 + /* remaining chunks checked... good to go */ 1.2326 + stcb->asoc.authenticated = 1; 1.2327 + } 1.2328 + } 1.2329 + /* update current state */ 1.2330 + SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 1.2331 + SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1.2332 + if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1.2333 + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1.2334 + stcb->sctp_ep, stcb, asoc->primary_destination); 1.2335 + } 1.2336 + sctp_stop_all_cookie_timers(stcb); 1.2337 + SCTP_STAT_INCR_COUNTER32(sctps_passiveestab); 1.2338 + SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1.2339 + 1.2340 + /* 1.2341 + * if we're doing ASCONFs, check to see if we have any new local 1.2342 + * addresses that need to get added to the peer (eg. addresses 1.2343 + * changed while cookie echo in flight). This needs to be done 1.2344 + * after we go to the OPEN state to do the correct asconf 1.2345 + * processing. else, make sure we have the correct addresses in our 1.2346 + * lists 1.2347 + */ 1.2348 + 1.2349 + /* warning, we re-use sin, sin6, sa_store here! */ 1.2350 + /* pull in local_address (our "from" address) */ 1.2351 + switch (cookie->laddr_type) { 1.2352 +#ifdef INET 1.2353 + case SCTP_IPV4_ADDRESS: 1.2354 + /* source addr is IPv4 */ 1.2355 + sin = (struct sockaddr_in *)initack_src; 1.2356 + memset(sin, 0, sizeof(*sin)); 1.2357 + sin->sin_family = AF_INET; 1.2358 +#ifdef HAVE_SIN_LEN 1.2359 + sin->sin_len = sizeof(struct sockaddr_in); 1.2360 +#endif 1.2361 + sin->sin_addr.s_addr = cookie->laddress[0]; 1.2362 + break; 1.2363 +#endif 1.2364 +#ifdef INET6 1.2365 + case SCTP_IPV6_ADDRESS: 1.2366 + /* source addr is IPv6 */ 1.2367 + sin6 = (struct sockaddr_in6 *)initack_src; 1.2368 + memset(sin6, 0, sizeof(*sin6)); 1.2369 + sin6->sin6_family = AF_INET6; 1.2370 +#ifdef HAVE_SIN6_LEN 1.2371 + sin6->sin6_len = sizeof(struct sockaddr_in6); 1.2372 +#endif 1.2373 + sin6->sin6_scope_id = cookie->scope_id; 1.2374 + memcpy(&sin6->sin6_addr, cookie->laddress, 1.2375 + sizeof(sin6->sin6_addr)); 1.2376 + break; 1.2377 +#endif 1.2378 +#if defined(__Userspace__) 1.2379 + case SCTP_CONN_ADDRESS: 1.2380 + /* source addr is IPv4 */ 1.2381 + sconn = (struct sockaddr_conn *)initack_src; 1.2382 + memset(sconn, 0, sizeof(struct sockaddr_conn)); 1.2383 + sconn->sconn_family = AF_CONN; 1.2384 +#ifdef HAVE_SCONN_LEN 1.2385 + sconn->sconn_len = sizeof(struct sockaddr_conn); 1.2386 +#endif 1.2387 + memcpy(&sconn->sconn_addr, cookie->laddress, sizeof(void *)); 1.2388 + break; 1.2389 +#endif 1.2390 + default: 1.2391 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.2392 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2393 + SCTP_TCB_UNLOCK(stcb); 1.2394 + SCTP_SOCKET_LOCK(so, 1); 1.2395 + SCTP_TCB_LOCK(stcb); 1.2396 +#endif 1.2397 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_19); 1.2398 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2399 + SCTP_SOCKET_UNLOCK(so, 1); 1.2400 +#endif 1.2401 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.2402 + return (NULL); 1.2403 + } 1.2404 + 1.2405 + /* set up to notify upper layer */ 1.2406 + *notification = SCTP_NOTIFY_ASSOC_UP; 1.2407 + if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1.2408 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1.2409 + (inp->sctp_socket->so_qlimit == 0)) { 1.2410 + /* 1.2411 + * This is an endpoint that called connect() how it got a 1.2412 + * cookie that is NEW is a bit of a mystery. It must be that 1.2413 + * the INIT was sent, but before it got there.. a complete 1.2414 + * INIT/INIT-ACK/COOKIE arrived. But of course then it 1.2415 + * should have went to the other code.. not here.. oh well.. 1.2416 + * a bit of protection is worth having.. 1.2417 + */ 1.2418 + stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 1.2419 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2420 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.2421 + SCTP_TCB_UNLOCK(stcb); 1.2422 + SCTP_SOCKET_LOCK(so, 1); 1.2423 + SCTP_TCB_LOCK(stcb); 1.2424 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.2425 + if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1.2426 + SCTP_SOCKET_UNLOCK(so, 1); 1.2427 + return (NULL); 1.2428 + } 1.2429 +#endif 1.2430 + soisconnected(stcb->sctp_socket); 1.2431 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2432 + SCTP_SOCKET_UNLOCK(so, 1); 1.2433 +#endif 1.2434 + } else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 1.2435 + (inp->sctp_socket->so_qlimit)) { 1.2436 + /* 1.2437 + * We don't want to do anything with this one. Since it is 1.2438 + * the listening guy. The timer will get started for 1.2439 + * accepted connections in the caller. 1.2440 + */ 1.2441 + ; 1.2442 + } 1.2443 + /* since we did not send a HB make sure we don't double things */ 1.2444 + if ((netp) && (*netp)) 1.2445 + (*netp)->hb_responded = 1; 1.2446 + 1.2447 + if (stcb->asoc.sctp_autoclose_ticks && 1.2448 + sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) { 1.2449 + sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL); 1.2450 + } 1.2451 + /* calculate the RTT */ 1.2452 + (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 1.2453 + if ((netp) && (*netp)) { 1.2454 + (*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp, 1.2455 + &cookie->time_entered, sctp_align_unsafe_makecopy, 1.2456 + SCTP_RTT_FROM_NON_DATA); 1.2457 + } 1.2458 + /* respond with a COOKIE-ACK */ 1.2459 + sctp_send_cookie_ack(stcb); 1.2460 + 1.2461 + /* 1.2462 + * check the address lists for any ASCONFs that need to be sent 1.2463 + * AFTER the cookie-ack is sent 1.2464 + */ 1.2465 + sctp_check_address_list(stcb, m, 1.2466 + initack_offset + sizeof(struct sctp_init_ack_chunk), 1.2467 + initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)), 1.2468 + initack_src, cookie->local_scope, cookie->site_scope, 1.2469 + cookie->ipv4_scope, cookie->loopback_scope); 1.2470 + 1.2471 + 1.2472 + return (stcb); 1.2473 +} 1.2474 + 1.2475 +/* 1.2476 + * CODE LIKE THIS NEEDS TO RUN IF the peer supports the NAT extension, i.e 1.2477 + * we NEED to make sure we are not already using the vtag. If so we 1.2478 + * need to send back an ABORT-TRY-AGAIN-WITH-NEW-TAG No middle box bit! 1.2479 + head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag, 1.2480 + SCTP_BASE_INFO(hashasocmark))]; 1.2481 + LIST_FOREACH(stcb, head, sctp_asocs) { 1.2482 + if ((stcb->asoc.my_vtag == tag) && (stcb->rport == rport) && (inp == stcb->sctp_ep)) { 1.2483 + -- SEND ABORT - TRY AGAIN -- 1.2484 + } 1.2485 + } 1.2486 +*/ 1.2487 + 1.2488 +/* 1.2489 + * handles a COOKIE-ECHO message stcb: modified to either a new or left as 1.2490 + * existing (non-NULL) TCB 1.2491 + */ 1.2492 +static struct mbuf * 1.2493 +sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, 1.2494 + struct sockaddr *src, struct sockaddr *dst, 1.2495 + struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp, 1.2496 + struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp, 1.2497 + int auth_skipped, uint32_t auth_offset, uint32_t auth_len, 1.2498 + struct sctp_tcb **locked_tcb, 1.2499 +#if defined(__FreeBSD__) 1.2500 + uint8_t use_mflowid, uint32_t mflowid, 1.2501 +#endif 1.2502 + uint32_t vrf_id, uint16_t port) 1.2503 +{ 1.2504 + struct sctp_state_cookie *cookie; 1.2505 + struct sctp_tcb *l_stcb = *stcb; 1.2506 + struct sctp_inpcb *l_inp; 1.2507 + struct sockaddr *to; 1.2508 + struct sctp_pcb *ep; 1.2509 + struct mbuf *m_sig; 1.2510 + uint8_t calc_sig[SCTP_SIGNATURE_SIZE], tmp_sig[SCTP_SIGNATURE_SIZE]; 1.2511 + uint8_t *sig; 1.2512 + uint8_t cookie_ok = 0; 1.2513 + unsigned int sig_offset, cookie_offset; 1.2514 + unsigned int cookie_len; 1.2515 + struct timeval now; 1.2516 + struct timeval time_expires; 1.2517 + int notification = 0; 1.2518 + struct sctp_nets *netl; 1.2519 + int had_a_existing_tcb = 0; 1.2520 + int send_int_conf = 0; 1.2521 +#ifdef INET 1.2522 + struct sockaddr_in sin; 1.2523 +#endif 1.2524 +#ifdef INET6 1.2525 + struct sockaddr_in6 sin6; 1.2526 +#endif 1.2527 +#if defined(__Userspace__) 1.2528 + struct sockaddr_conn sconn; 1.2529 +#endif 1.2530 + 1.2531 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.2532 + "sctp_handle_cookie: handling COOKIE-ECHO\n"); 1.2533 + 1.2534 + if (inp_p == NULL) { 1.2535 + return (NULL); 1.2536 + } 1.2537 + cookie = &cp->cookie; 1.2538 + cookie_offset = offset + sizeof(struct sctp_chunkhdr); 1.2539 + cookie_len = ntohs(cp->ch.chunk_length); 1.2540 + 1.2541 + if ((cookie->peerport != sh->src_port) && 1.2542 + (cookie->myport != sh->dest_port) && 1.2543 + (cookie->my_vtag != sh->v_tag)) { 1.2544 + /* 1.2545 + * invalid ports or bad tag. Note that we always leave the 1.2546 + * v_tag in the header in network order and when we stored 1.2547 + * it in the my_vtag slot we also left it in network order. 1.2548 + * This maintains the match even though it may be in the 1.2549 + * opposite byte order of the machine :-> 1.2550 + */ 1.2551 + return (NULL); 1.2552 + } 1.2553 + if (cookie_len < sizeof(struct sctp_cookie_echo_chunk) + 1.2554 + sizeof(struct sctp_init_chunk) + 1.2555 + sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) { 1.2556 + /* cookie too small */ 1.2557 + return (NULL); 1.2558 + } 1.2559 + /* 1.2560 + * split off the signature into its own mbuf (since it should not be 1.2561 + * calculated in the sctp_hmac_m() call). 1.2562 + */ 1.2563 + sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE; 1.2564 + m_sig = m_split(m, sig_offset, M_NOWAIT); 1.2565 + if (m_sig == NULL) { 1.2566 + /* out of memory or ?? */ 1.2567 + return (NULL); 1.2568 + } 1.2569 +#ifdef SCTP_MBUF_LOGGING 1.2570 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 1.2571 + struct mbuf *mat; 1.2572 + 1.2573 + for (mat = m_sig; mat; mat = SCTP_BUF_NEXT(mat)) { 1.2574 + if (SCTP_BUF_IS_EXTENDED(mat)) { 1.2575 + sctp_log_mb(mat, SCTP_MBUF_SPLIT); 1.2576 + } 1.2577 + } 1.2578 + } 1.2579 +#endif 1.2580 + 1.2581 + /* 1.2582 + * compute the signature/digest for the cookie 1.2583 + */ 1.2584 + ep = &(*inp_p)->sctp_ep; 1.2585 + l_inp = *inp_p; 1.2586 + if (l_stcb) { 1.2587 + SCTP_TCB_UNLOCK(l_stcb); 1.2588 + } 1.2589 + SCTP_INP_RLOCK(l_inp); 1.2590 + if (l_stcb) { 1.2591 + SCTP_TCB_LOCK(l_stcb); 1.2592 + } 1.2593 + /* which cookie is it? */ 1.2594 + if ((cookie->time_entered.tv_sec < (long)ep->time_of_secret_change) && 1.2595 + (ep->current_secret_number != ep->last_secret_number)) { 1.2596 + /* it's the old cookie */ 1.2597 + (void)sctp_hmac_m(SCTP_HMAC, 1.2598 + (uint8_t *)ep->secret_key[(int)ep->last_secret_number], 1.2599 + SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 1.2600 + } else { 1.2601 + /* it's the current cookie */ 1.2602 + (void)sctp_hmac_m(SCTP_HMAC, 1.2603 + (uint8_t *)ep->secret_key[(int)ep->current_secret_number], 1.2604 + SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 1.2605 + } 1.2606 + /* get the signature */ 1.2607 + SCTP_INP_RUNLOCK(l_inp); 1.2608 + sig = (uint8_t *) sctp_m_getptr(m_sig, 0, SCTP_SIGNATURE_SIZE, (uint8_t *) & tmp_sig); 1.2609 + if (sig == NULL) { 1.2610 + /* couldn't find signature */ 1.2611 + sctp_m_freem(m_sig); 1.2612 + return (NULL); 1.2613 + } 1.2614 + /* compare the received digest with the computed digest */ 1.2615 + if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) != 0) { 1.2616 + /* try the old cookie? */ 1.2617 + if ((cookie->time_entered.tv_sec == (long)ep->time_of_secret_change) && 1.2618 + (ep->current_secret_number != ep->last_secret_number)) { 1.2619 + /* compute digest with old */ 1.2620 + (void)sctp_hmac_m(SCTP_HMAC, 1.2621 + (uint8_t *)ep->secret_key[(int)ep->last_secret_number], 1.2622 + SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0); 1.2623 + /* compare */ 1.2624 + if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) == 0) 1.2625 + cookie_ok = 1; 1.2626 + } 1.2627 + } else { 1.2628 + cookie_ok = 1; 1.2629 + } 1.2630 + 1.2631 + /* 1.2632 + * Now before we continue we must reconstruct our mbuf so that 1.2633 + * normal processing of any other chunks will work. 1.2634 + */ 1.2635 + { 1.2636 + struct mbuf *m_at; 1.2637 + 1.2638 + m_at = m; 1.2639 + while (SCTP_BUF_NEXT(m_at) != NULL) { 1.2640 + m_at = SCTP_BUF_NEXT(m_at); 1.2641 + } 1.2642 + SCTP_BUF_NEXT(m_at) = m_sig; 1.2643 + } 1.2644 + 1.2645 + if (cookie_ok == 0) { 1.2646 + SCTPDBG(SCTP_DEBUG_INPUT2, "handle_cookie_echo: cookie signature validation failed!\n"); 1.2647 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.2648 + "offset = %u, cookie_offset = %u, sig_offset = %u\n", 1.2649 + (uint32_t) offset, cookie_offset, sig_offset); 1.2650 + return (NULL); 1.2651 + } 1.2652 + 1.2653 + /* 1.2654 + * check the cookie timestamps to be sure it's not stale 1.2655 + */ 1.2656 + (void)SCTP_GETTIME_TIMEVAL(&now); 1.2657 + /* Expire time is in Ticks, so we convert to seconds */ 1.2658 + time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life); 1.2659 + time_expires.tv_usec = cookie->time_entered.tv_usec; 1.2660 + /* TODO sctp_constants.h needs alternative time macros when 1.2661 + * _KERNEL is undefined. 1.2662 + */ 1.2663 +#ifndef __FreeBSD__ 1.2664 + if (timercmp(&now, &time_expires, >)) 1.2665 +#else 1.2666 + if (timevalcmp(&now, &time_expires, >)) 1.2667 +#endif 1.2668 + { 1.2669 + /* cookie is stale! */ 1.2670 + struct mbuf *op_err; 1.2671 + struct sctp_stale_cookie_msg *scm; 1.2672 + uint32_t tim; 1.2673 + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg), 1.2674 + 0, M_NOWAIT, 1, MT_DATA); 1.2675 + if (op_err == NULL) { 1.2676 + /* FOOBAR */ 1.2677 + return (NULL); 1.2678 + } 1.2679 + /* Set the len */ 1.2680 + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg); 1.2681 + scm = mtod(op_err, struct sctp_stale_cookie_msg *); 1.2682 + scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE); 1.2683 + scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) + 1.2684 + (sizeof(uint32_t)))); 1.2685 + /* seconds to usec */ 1.2686 + tim = (now.tv_sec - time_expires.tv_sec) * 1000000; 1.2687 + /* add in usec */ 1.2688 + if (tim == 0) 1.2689 + tim = now.tv_usec - cookie->time_entered.tv_usec; 1.2690 + scm->time_usec = htonl(tim); 1.2691 + sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, 1.2692 +#if defined(__FreeBSD__) 1.2693 + use_mflowid, mflowid, 1.2694 +#endif 1.2695 + vrf_id, port); 1.2696 + return (NULL); 1.2697 + } 1.2698 + /* 1.2699 + * Now we must see with the lookup address if we have an existing 1.2700 + * asoc. This will only happen if we were in the COOKIE-WAIT state 1.2701 + * and a INIT collided with us and somewhere the peer sent the 1.2702 + * cookie on another address besides the single address our assoc 1.2703 + * had for him. In this case we will have one of the tie-tags set at 1.2704 + * least AND the address field in the cookie can be used to look it 1.2705 + * up. 1.2706 + */ 1.2707 + to = NULL; 1.2708 + switch (cookie->addr_type) { 1.2709 +#ifdef INET6 1.2710 + case SCTP_IPV6_ADDRESS: 1.2711 + memset(&sin6, 0, sizeof(sin6)); 1.2712 + sin6.sin6_family = AF_INET6; 1.2713 +#ifdef HAVE_SIN6_LEN 1.2714 + sin6.sin6_len = sizeof(sin6); 1.2715 +#endif 1.2716 + sin6.sin6_port = sh->src_port; 1.2717 + sin6.sin6_scope_id = cookie->scope_id; 1.2718 + memcpy(&sin6.sin6_addr.s6_addr, cookie->address, 1.2719 + sizeof(sin6.sin6_addr.s6_addr)); 1.2720 + to = (struct sockaddr *)&sin6; 1.2721 + break; 1.2722 +#endif 1.2723 +#ifdef INET 1.2724 + case SCTP_IPV4_ADDRESS: 1.2725 + memset(&sin, 0, sizeof(sin)); 1.2726 + sin.sin_family = AF_INET; 1.2727 +#ifdef HAVE_SIN_LEN 1.2728 + sin.sin_len = sizeof(sin); 1.2729 +#endif 1.2730 + sin.sin_port = sh->src_port; 1.2731 + sin.sin_addr.s_addr = cookie->address[0]; 1.2732 + to = (struct sockaddr *)&sin; 1.2733 + break; 1.2734 +#endif 1.2735 +#if defined(__Userspace__) 1.2736 + case SCTP_CONN_ADDRESS: 1.2737 + memset(&sconn, 0, sizeof(struct sockaddr_conn)); 1.2738 + sconn.sconn_family = AF_CONN; 1.2739 +#ifdef HAVE_SCONN_LEN 1.2740 + sconn.sconn_len = sizeof(struct sockaddr_conn); 1.2741 +#endif 1.2742 + sconn.sconn_port = sh->src_port; 1.2743 + memcpy(&sconn.sconn_addr, cookie->address, sizeof(void *)); 1.2744 + to = (struct sockaddr *)&sconn; 1.2745 + break; 1.2746 +#endif 1.2747 + default: 1.2748 + /* This should not happen */ 1.2749 + return (NULL); 1.2750 + } 1.2751 + if ((*stcb == NULL) && to) { 1.2752 + /* Yep, lets check */ 1.2753 + *stcb = sctp_findassociation_ep_addr(inp_p, to, netp, dst, NULL); 1.2754 + if (*stcb == NULL) { 1.2755 + /* 1.2756 + * We should have only got back the same inp. If we 1.2757 + * got back a different ep we have a problem. The 1.2758 + * original findep got back l_inp and now 1.2759 + */ 1.2760 + if (l_inp != *inp_p) { 1.2761 + SCTP_PRINTF("Bad problem find_ep got a diff inp then special_locate?\n"); 1.2762 + } 1.2763 + } else { 1.2764 + if (*locked_tcb == NULL) { 1.2765 + /* In this case we found the assoc only 1.2766 + * after we locked the create lock. This means 1.2767 + * we are in a colliding case and we must make 1.2768 + * sure that we unlock the tcb if its one of the 1.2769 + * cases where we throw away the incoming packets. 1.2770 + */ 1.2771 + *locked_tcb = *stcb; 1.2772 + 1.2773 + /* We must also increment the inp ref count 1.2774 + * since the ref_count flags was set when we 1.2775 + * did not find the TCB, now we found it which 1.2776 + * reduces the refcount.. we must raise it back 1.2777 + * out to balance it all :-) 1.2778 + */ 1.2779 + SCTP_INP_INCR_REF((*stcb)->sctp_ep); 1.2780 + if ((*stcb)->sctp_ep != l_inp) { 1.2781 + SCTP_PRINTF("Huh? ep:%p diff then l_inp:%p?\n", 1.2782 + (void *)(*stcb)->sctp_ep, (void *)l_inp); 1.2783 + } 1.2784 + } 1.2785 + } 1.2786 + } 1.2787 + if (to == NULL) { 1.2788 + return (NULL); 1.2789 + } 1.2790 + 1.2791 + cookie_len -= SCTP_SIGNATURE_SIZE; 1.2792 + if (*stcb == NULL) { 1.2793 + /* this is the "normal" case... get a new TCB */ 1.2794 + *stcb = sctp_process_cookie_new(m, iphlen, offset, src, dst, sh, 1.2795 + cookie, cookie_len, *inp_p, 1.2796 + netp, to, ¬ification, 1.2797 + auth_skipped, auth_offset, auth_len, 1.2798 +#if defined(__FreeBSD__) 1.2799 + use_mflowid, mflowid, 1.2800 +#endif 1.2801 + vrf_id, port); 1.2802 + } else { 1.2803 + /* this is abnormal... cookie-echo on existing TCB */ 1.2804 + had_a_existing_tcb = 1; 1.2805 + *stcb = sctp_process_cookie_existing(m, iphlen, offset, 1.2806 + src, dst, sh, 1.2807 + cookie, cookie_len, *inp_p, *stcb, netp, to, 1.2808 + ¬ification, auth_skipped, auth_offset, auth_len, 1.2809 +#if defined(__FreeBSD__) 1.2810 + use_mflowid, mflowid, 1.2811 +#endif 1.2812 + vrf_id, port); 1.2813 + } 1.2814 + 1.2815 + if (*stcb == NULL) { 1.2816 + /* still no TCB... must be bad cookie-echo */ 1.2817 + return (NULL); 1.2818 + } 1.2819 +#if defined(__FreeBSD__) 1.2820 + if ((*netp != NULL) && (use_mflowid != 0)) { 1.2821 + (*netp)->flowid = mflowid; 1.2822 +#ifdef INVARIANTS 1.2823 + (*netp)->flowidset = 1; 1.2824 +#endif 1.2825 + } 1.2826 +#endif 1.2827 + /* 1.2828 + * Ok, we built an association so confirm the address we sent the 1.2829 + * INIT-ACK to. 1.2830 + */ 1.2831 + netl = sctp_findnet(*stcb, to); 1.2832 + /* 1.2833 + * This code should in theory NOT run but 1.2834 + */ 1.2835 + if (netl == NULL) { 1.2836 + /* TSNH! Huh, why do I need to add this address here? */ 1.2837 + if (sctp_add_remote_addr(*stcb, to, NULL, SCTP_DONOT_SETSCOPE, SCTP_IN_COOKIE_PROC)) { 1.2838 + return (NULL); 1.2839 + } 1.2840 + netl = sctp_findnet(*stcb, to); 1.2841 + } 1.2842 + if (netl) { 1.2843 + if (netl->dest_state & SCTP_ADDR_UNCONFIRMED) { 1.2844 + netl->dest_state &= ~SCTP_ADDR_UNCONFIRMED; 1.2845 + (void)sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL, 1.2846 + netl); 1.2847 + send_int_conf = 1; 1.2848 + } 1.2849 + } 1.2850 + sctp_start_net_timers(*stcb); 1.2851 + if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) { 1.2852 + if (!had_a_existing_tcb || 1.2853 + (((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) { 1.2854 + /* 1.2855 + * If we have a NEW cookie or the connect never 1.2856 + * reached the connected state during collision we 1.2857 + * must do the TCP accept thing. 1.2858 + */ 1.2859 + struct socket *so, *oso; 1.2860 + struct sctp_inpcb *inp; 1.2861 + 1.2862 + if (notification == SCTP_NOTIFY_ASSOC_RESTART) { 1.2863 + /* 1.2864 + * For a restart we will keep the same 1.2865 + * socket, no need to do anything. I THINK!! 1.2866 + */ 1.2867 + sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1.2868 + if (send_int_conf) { 1.2869 + sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 1.2870 + (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 1.2871 + } 1.2872 + return (m); 1.2873 + } 1.2874 + oso = (*inp_p)->sctp_socket; 1.2875 +#if (defined(__FreeBSD__) && __FreeBSD_version < 700000) 1.2876 + /* 1.2877 + * We do this to keep the sockets side happy during 1.2878 + * the sonewcon ONLY. 1.2879 + */ 1.2880 + NET_LOCK_GIANT(); 1.2881 +#endif 1.2882 + atomic_add_int(&(*stcb)->asoc.refcnt, 1); 1.2883 + SCTP_TCB_UNLOCK((*stcb)); 1.2884 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.2885 + CURVNET_SET(oso->so_vnet); 1.2886 +#endif 1.2887 +#if defined(__APPLE__) 1.2888 + SCTP_SOCKET_LOCK(oso, 1); 1.2889 +#endif 1.2890 + so = sonewconn(oso, 0 1.2891 +#if defined(__APPLE__) 1.2892 + ,NULL 1.2893 +#endif 1.2894 +#ifdef __Panda__ 1.2895 + ,NULL , (*inp_p)->def_vrf_id 1.2896 +#endif 1.2897 + ); 1.2898 +#if (defined(__FreeBSD__) && __FreeBSD_version < 700000) 1.2899 + NET_UNLOCK_GIANT(); 1.2900 +#endif 1.2901 +#if defined(__APPLE__) 1.2902 + SCTP_SOCKET_UNLOCK(oso, 1); 1.2903 +#endif 1.2904 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.2905 + CURVNET_RESTORE(); 1.2906 +#endif 1.2907 + SCTP_TCB_LOCK((*stcb)); 1.2908 + atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 1.2909 + 1.2910 + if (so == NULL) { 1.2911 + struct mbuf *op_err; 1.2912 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2913 + struct socket *pcb_so; 1.2914 +#endif 1.2915 + /* Too many sockets */ 1.2916 + SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n"); 1.2917 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); 1.2918 + sctp_abort_association(*inp_p, NULL, m, iphlen, 1.2919 + src, dst, sh, op_err, 1.2920 +#if defined(__FreeBSD__) 1.2921 + use_mflowid, mflowid, 1.2922 +#endif 1.2923 + vrf_id, port); 1.2924 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2925 + pcb_so = SCTP_INP_SO(*inp_p); 1.2926 + atomic_add_int(&(*stcb)->asoc.refcnt, 1); 1.2927 + SCTP_TCB_UNLOCK((*stcb)); 1.2928 + SCTP_SOCKET_LOCK(pcb_so, 1); 1.2929 + SCTP_TCB_LOCK((*stcb)); 1.2930 + atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 1.2931 +#endif 1.2932 + (void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_20); 1.2933 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2934 + SCTP_SOCKET_UNLOCK(pcb_so, 1); 1.2935 +#endif 1.2936 + return (NULL); 1.2937 + } 1.2938 + inp = (struct sctp_inpcb *)so->so_pcb; 1.2939 + SCTP_INP_INCR_REF(inp); 1.2940 + /* 1.2941 + * We add the unbound flag here so that 1.2942 + * if we get an soabort() before we get the 1.2943 + * move_pcb done, we will properly cleanup. 1.2944 + */ 1.2945 + inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE | 1.2946 + SCTP_PCB_FLAGS_CONNECTED | 1.2947 + SCTP_PCB_FLAGS_IN_TCPPOOL | 1.2948 + SCTP_PCB_FLAGS_UNBOUND | 1.2949 + (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) | 1.2950 + SCTP_PCB_FLAGS_DONT_WAKE); 1.2951 + inp->sctp_features = (*inp_p)->sctp_features; 1.2952 + inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features; 1.2953 + inp->sctp_socket = so; 1.2954 + inp->sctp_frag_point = (*inp_p)->sctp_frag_point; 1.2955 + inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off; 1.2956 + inp->sctp_ecn_enable = (*inp_p)->sctp_ecn_enable; 1.2957 + inp->partial_delivery_point = (*inp_p)->partial_delivery_point; 1.2958 + inp->sctp_context = (*inp_p)->sctp_context; 1.2959 + inp->local_strreset_support = (*inp_p)->local_strreset_support; 1.2960 + inp->inp_starting_point_for_iterator = NULL; 1.2961 +#if defined(__Userspace__) 1.2962 + inp->ulp_info = (*inp_p)->ulp_info; 1.2963 + inp->recv_callback = (*inp_p)->recv_callback; 1.2964 + inp->send_callback = (*inp_p)->send_callback; 1.2965 + inp->send_sb_threshold = (*inp_p)->send_sb_threshold; 1.2966 +#endif 1.2967 + /* 1.2968 + * copy in the authentication parameters from the 1.2969 + * original endpoint 1.2970 + */ 1.2971 + if (inp->sctp_ep.local_hmacs) 1.2972 + sctp_free_hmaclist(inp->sctp_ep.local_hmacs); 1.2973 + inp->sctp_ep.local_hmacs = 1.2974 + sctp_copy_hmaclist((*inp_p)->sctp_ep.local_hmacs); 1.2975 + if (inp->sctp_ep.local_auth_chunks) 1.2976 + sctp_free_chunklist(inp->sctp_ep.local_auth_chunks); 1.2977 + inp->sctp_ep.local_auth_chunks = 1.2978 + sctp_copy_chunklist((*inp_p)->sctp_ep.local_auth_chunks); 1.2979 + 1.2980 + /* 1.2981 + * Now we must move it from one hash table to 1.2982 + * another and get the tcb in the right place. 1.2983 + */ 1.2984 + 1.2985 + /* This is where the one-2-one socket is put into 1.2986 + * the accept state waiting for the accept! 1.2987 + */ 1.2988 + if (*stcb) { 1.2989 + (*stcb)->asoc.state |= SCTP_STATE_IN_ACCEPT_QUEUE; 1.2990 + } 1.2991 + sctp_move_pcb_and_assoc(*inp_p, inp, *stcb); 1.2992 + 1.2993 + atomic_add_int(&(*stcb)->asoc.refcnt, 1); 1.2994 + SCTP_TCB_UNLOCK((*stcb)); 1.2995 + 1.2996 +#if defined(__FreeBSD__) 1.2997 + sctp_pull_off_control_to_new_inp((*inp_p), inp, *stcb, 1.2998 + 0); 1.2999 +#else 1.3000 + sctp_pull_off_control_to_new_inp((*inp_p), inp, *stcb, M_NOWAIT); 1.3001 +#endif 1.3002 + SCTP_TCB_LOCK((*stcb)); 1.3003 + atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 1.3004 + 1.3005 + 1.3006 + /* now we must check to see if we were aborted while 1.3007 + * the move was going on and the lock/unlock happened. 1.3008 + */ 1.3009 + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 1.3010 + /* yep it was, we leave the 1.3011 + * assoc attached to the socket since 1.3012 + * the sctp_inpcb_free() call will send 1.3013 + * an abort for us. 1.3014 + */ 1.3015 + SCTP_INP_DECR_REF(inp); 1.3016 + return (NULL); 1.3017 + } 1.3018 + SCTP_INP_DECR_REF(inp); 1.3019 + /* Switch over to the new guy */ 1.3020 + *inp_p = inp; 1.3021 + sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1.3022 + if (send_int_conf) { 1.3023 + sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 1.3024 + (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 1.3025 + } 1.3026 + 1.3027 + /* Pull it from the incomplete queue and wake the guy */ 1.3028 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3029 + atomic_add_int(&(*stcb)->asoc.refcnt, 1); 1.3030 + SCTP_TCB_UNLOCK((*stcb)); 1.3031 + SCTP_SOCKET_LOCK(so, 1); 1.3032 +#endif 1.3033 + soisconnected(so); 1.3034 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3035 + SCTP_TCB_LOCK((*stcb)); 1.3036 + atomic_subtract_int(&(*stcb)->asoc.refcnt, 1); 1.3037 + SCTP_SOCKET_UNLOCK(so, 1); 1.3038 +#endif 1.3039 + return (m); 1.3040 + } 1.3041 + } 1.3042 + if (notification) { 1.3043 + sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1.3044 + } 1.3045 + if (send_int_conf) { 1.3046 + sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED, 1.3047 + (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED); 1.3048 + } 1.3049 + return (m); 1.3050 +} 1.3051 + 1.3052 +static void 1.3053 +sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED, 1.3054 + struct sctp_tcb *stcb, struct sctp_nets *net) 1.3055 +{ 1.3056 + /* cp must not be used, others call this without a c-ack :-) */ 1.3057 + struct sctp_association *asoc; 1.3058 + 1.3059 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.3060 + "sctp_handle_cookie_ack: handling COOKIE-ACK\n"); 1.3061 + if (stcb == NULL) 1.3062 + return; 1.3063 + 1.3064 + asoc = &stcb->asoc; 1.3065 + 1.3066 + sctp_stop_all_cookie_timers(stcb); 1.3067 + /* process according to association state */ 1.3068 + if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) { 1.3069 + /* state change only needed when I am in right state */ 1.3070 + SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n"); 1.3071 + SCTP_SET_STATE(asoc, SCTP_STATE_OPEN); 1.3072 + sctp_start_net_timers(stcb); 1.3073 + if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) { 1.3074 + sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, 1.3075 + stcb->sctp_ep, stcb, asoc->primary_destination); 1.3076 + 1.3077 + } 1.3078 + /* update RTO */ 1.3079 + SCTP_STAT_INCR_COUNTER32(sctps_activeestab); 1.3080 + SCTP_STAT_INCR_GAUGE32(sctps_currestab); 1.3081 + if (asoc->overall_error_count == 0) { 1.3082 + net->RTO = sctp_calculate_rto(stcb, asoc, net, 1.3083 + &asoc->time_entered, sctp_align_safe_nocopy, 1.3084 + SCTP_RTT_FROM_NON_DATA); 1.3085 + } 1.3086 + (void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered); 1.3087 + sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1.3088 + if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1.3089 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 1.3090 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3091 + struct socket *so; 1.3092 + 1.3093 +#endif 1.3094 + stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 1.3095 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3096 + so = SCTP_INP_SO(stcb->sctp_ep); 1.3097 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.3098 + SCTP_TCB_UNLOCK(stcb); 1.3099 + SCTP_SOCKET_LOCK(so, 1); 1.3100 + SCTP_TCB_LOCK(stcb); 1.3101 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.3102 +#endif 1.3103 + if ((stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) == 0) { 1.3104 + soisconnected(stcb->sctp_socket); 1.3105 + } 1.3106 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3107 + SCTP_SOCKET_UNLOCK(so, 1); 1.3108 +#endif 1.3109 + } 1.3110 + /* 1.3111 + * since we did not send a HB make sure we don't double 1.3112 + * things 1.3113 + */ 1.3114 + net->hb_responded = 1; 1.3115 + 1.3116 + if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1.3117 + /* We don't need to do the asconf thing, 1.3118 + * nor hb or autoclose if the socket is closed. 1.3119 + */ 1.3120 + goto closed_socket; 1.3121 + } 1.3122 + 1.3123 + sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, 1.3124 + stcb, net); 1.3125 + 1.3126 + 1.3127 + if (stcb->asoc.sctp_autoclose_ticks && 1.3128 + sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTOCLOSE)) { 1.3129 + sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, 1.3130 + stcb->sctp_ep, stcb, NULL); 1.3131 + } 1.3132 + /* 1.3133 + * send ASCONF if parameters are pending and ASCONFs are 1.3134 + * allowed (eg. addresses changed when init/cookie echo were 1.3135 + * in flight) 1.3136 + */ 1.3137 + if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) && 1.3138 + (stcb->asoc.peer_supports_asconf) && 1.3139 + (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) { 1.3140 +#ifdef SCTP_TIMER_BASED_ASCONF 1.3141 + sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, 1.3142 + stcb->sctp_ep, stcb, 1.3143 + stcb->asoc.primary_destination); 1.3144 +#else 1.3145 + sctp_send_asconf(stcb, stcb->asoc.primary_destination, 1.3146 + SCTP_ADDR_NOT_LOCKED); 1.3147 +#endif 1.3148 + } 1.3149 + } 1.3150 +closed_socket: 1.3151 + /* Toss the cookie if I can */ 1.3152 + sctp_toss_old_cookies(stcb, asoc); 1.3153 + if (!TAILQ_EMPTY(&asoc->sent_queue)) { 1.3154 + /* Restart the timer if we have pending data */ 1.3155 + struct sctp_tmit_chunk *chk; 1.3156 + 1.3157 + chk = TAILQ_FIRST(&asoc->sent_queue); 1.3158 + sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 1.3159 + } 1.3160 +} 1.3161 + 1.3162 +static void 1.3163 +sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp, 1.3164 + struct sctp_tcb *stcb) 1.3165 +{ 1.3166 + struct sctp_nets *net; 1.3167 + struct sctp_tmit_chunk *lchk; 1.3168 + struct sctp_ecne_chunk bkup; 1.3169 + uint8_t override_bit; 1.3170 + uint32_t tsn, window_data_tsn; 1.3171 + int len; 1.3172 + unsigned int pkt_cnt; 1.3173 + 1.3174 + len = ntohs(cp->ch.chunk_length); 1.3175 + if ((len != sizeof(struct sctp_ecne_chunk)) && 1.3176 + (len != sizeof(struct old_sctp_ecne_chunk))) { 1.3177 + return; 1.3178 + } 1.3179 + if (len == sizeof(struct old_sctp_ecne_chunk)) { 1.3180 + /* Its the old format */ 1.3181 + memcpy(&bkup, cp, sizeof(struct old_sctp_ecne_chunk)); 1.3182 + bkup.num_pkts_since_cwr = htonl(1); 1.3183 + cp = &bkup; 1.3184 + } 1.3185 + SCTP_STAT_INCR(sctps_recvecne); 1.3186 + tsn = ntohl(cp->tsn); 1.3187 + pkt_cnt = ntohl(cp->num_pkts_since_cwr); 1.3188 + lchk = TAILQ_LAST(&stcb->asoc.send_queue, sctpchunk_listhead); 1.3189 + if (lchk == NULL) { 1.3190 + window_data_tsn = stcb->asoc.sending_seq - 1; 1.3191 + } else { 1.3192 + window_data_tsn = lchk->rec.data.TSN_seq; 1.3193 + } 1.3194 + 1.3195 + /* Find where it was sent to if possible. */ 1.3196 + net = NULL; 1.3197 + TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) { 1.3198 + if (lchk->rec.data.TSN_seq == tsn) { 1.3199 + net = lchk->whoTo; 1.3200 + net->ecn_prev_cwnd = lchk->rec.data.cwnd_at_send; 1.3201 + break; 1.3202 + } 1.3203 + if (SCTP_TSN_GT(lchk->rec.data.TSN_seq, tsn)) { 1.3204 + break; 1.3205 + } 1.3206 + } 1.3207 + if (net == NULL) { 1.3208 + /* 1.3209 + * What to do. A previous send of a 1.3210 + * CWR was possibly lost. See how old it is, we 1.3211 + * may have it marked on the actual net. 1.3212 + */ 1.3213 + TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 1.3214 + if (tsn == net->last_cwr_tsn) { 1.3215 + /* Found him, send it off */ 1.3216 + break; 1.3217 + } 1.3218 + } 1.3219 + if (net == NULL) { 1.3220 + /* 1.3221 + * If we reach here, we need to send a special 1.3222 + * CWR that says hey, we did this a long time 1.3223 + * ago and you lost the response. 1.3224 + */ 1.3225 + net = TAILQ_FIRST(&stcb->asoc.nets); 1.3226 + if (net == NULL) { 1.3227 + /* TSNH */ 1.3228 + return; 1.3229 + } 1.3230 + override_bit = SCTP_CWR_REDUCE_OVERRIDE; 1.3231 + } else { 1.3232 + override_bit = 0; 1.3233 + } 1.3234 + } else { 1.3235 + override_bit = 0; 1.3236 + } 1.3237 + if (SCTP_TSN_GT(tsn, net->cwr_window_tsn) && 1.3238 + ((override_bit&SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 1.3239 + /* JRS - Use the congestion control given in the pluggable CC module */ 1.3240 + stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 0, pkt_cnt); 1.3241 + /* 1.3242 + * We reduce once every RTT. So we will only lower cwnd at 1.3243 + * the next sending seq i.e. the window_data_tsn 1.3244 + */ 1.3245 + net->cwr_window_tsn = window_data_tsn; 1.3246 + net->ecn_ce_pkt_cnt += pkt_cnt; 1.3247 + net->lost_cnt = pkt_cnt; 1.3248 + net->last_cwr_tsn = tsn; 1.3249 + } else { 1.3250 + override_bit |= SCTP_CWR_IN_SAME_WINDOW; 1.3251 + if (SCTP_TSN_GT(tsn, net->last_cwr_tsn) && 1.3252 + ((override_bit&SCTP_CWR_REDUCE_OVERRIDE) == 0)) { 1.3253 + /* 1.3254 + * Another loss in the same window update how 1.3255 + * many marks/packets lost we have had. 1.3256 + */ 1.3257 + int cnt = 1; 1.3258 + if (pkt_cnt > net->lost_cnt) { 1.3259 + /* Should be the case */ 1.3260 + cnt = (pkt_cnt - net->lost_cnt); 1.3261 + net->ecn_ce_pkt_cnt += cnt; 1.3262 + } 1.3263 + net->lost_cnt = pkt_cnt; 1.3264 + net->last_cwr_tsn = tsn; 1.3265 + /* 1.3266 + * Most CC functions will ignore this call, since we are in-window 1.3267 + * yet of the initial CE the peer saw. 1.3268 + */ 1.3269 + stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 1, cnt); 1.3270 + } 1.3271 + } 1.3272 + /* 1.3273 + * We always send a CWR this way if our previous one was lost our 1.3274 + * peer will get an update, or if it is not time again to reduce we 1.3275 + * still get the cwr to the peer. Note we set the override when we 1.3276 + * could not find the TSN on the chunk or the destination network. 1.3277 + */ 1.3278 + sctp_send_cwr(stcb, net, net->last_cwr_tsn, override_bit); 1.3279 +} 1.3280 + 1.3281 +static void 1.3282 +sctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sctp_nets *net) 1.3283 +{ 1.3284 + /* 1.3285 + * Here we get a CWR from the peer. We must look in the outqueue and 1.3286 + * make sure that we have a covered ECNE in the control chunk part. 1.3287 + * If so remove it. 1.3288 + */ 1.3289 + struct sctp_tmit_chunk *chk; 1.3290 + struct sctp_ecne_chunk *ecne; 1.3291 + int override; 1.3292 + uint32_t cwr_tsn; 1.3293 + cwr_tsn = ntohl(cp->tsn); 1.3294 + 1.3295 + override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE; 1.3296 + TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) { 1.3297 + if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) { 1.3298 + continue; 1.3299 + } 1.3300 + if ((override == 0) && (chk->whoTo != net)) { 1.3301 + /* Must be from the right src unless override is set */ 1.3302 + continue; 1.3303 + } 1.3304 + ecne = mtod(chk->data, struct sctp_ecne_chunk *); 1.3305 + if (SCTP_TSN_GE(cwr_tsn, ntohl(ecne->tsn))) { 1.3306 + /* this covers this ECNE, we can remove it */ 1.3307 + stcb->asoc.ecn_echo_cnt_onq--; 1.3308 + TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk, 1.3309 + sctp_next); 1.3310 + if (chk->data) { 1.3311 + sctp_m_freem(chk->data); 1.3312 + chk->data = NULL; 1.3313 + } 1.3314 + stcb->asoc.ctrl_queue_cnt--; 1.3315 + sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 1.3316 + if (override == 0) { 1.3317 + break; 1.3318 + } 1.3319 + } 1.3320 + } 1.3321 +} 1.3322 + 1.3323 +static void 1.3324 +sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSED, 1.3325 + struct sctp_tcb *stcb, struct sctp_nets *net) 1.3326 +{ 1.3327 + struct sctp_association *asoc; 1.3328 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3329 + struct socket *so; 1.3330 +#endif 1.3331 + 1.3332 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.3333 + "sctp_handle_shutdown_complete: handling SHUTDOWN-COMPLETE\n"); 1.3334 + if (stcb == NULL) 1.3335 + return; 1.3336 + 1.3337 + asoc = &stcb->asoc; 1.3338 + /* process according to association state */ 1.3339 + if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) { 1.3340 + /* unexpected SHUTDOWN-COMPLETE... so ignore... */ 1.3341 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.3342 + "sctp_handle_shutdown_complete: not in SCTP_STATE_SHUTDOWN_ACK_SENT --- ignore\n"); 1.3343 + SCTP_TCB_UNLOCK(stcb); 1.3344 + return; 1.3345 + } 1.3346 + /* notify upper layer protocol */ 1.3347 + if (stcb->sctp_socket) { 1.3348 + sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1.3349 + } 1.3350 +#ifdef INVARIANTS 1.3351 + if (!TAILQ_EMPTY(&asoc->send_queue) || 1.3352 + !TAILQ_EMPTY(&asoc->sent_queue) || 1.3353 + !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) { 1.3354 + panic("Queues are not empty when handling SHUTDOWN-COMPLETE"); 1.3355 + } 1.3356 +#endif 1.3357 + /* stop the timer */ 1.3358 + sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_22); 1.3359 + SCTP_STAT_INCR_COUNTER32(sctps_shutdown); 1.3360 + /* free the TCB */ 1.3361 + SCTPDBG(SCTP_DEBUG_INPUT2, 1.3362 + "sctp_handle_shutdown_complete: calls free-asoc\n"); 1.3363 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3364 + so = SCTP_INP_SO(stcb->sctp_ep); 1.3365 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.3366 + SCTP_TCB_UNLOCK(stcb); 1.3367 + SCTP_SOCKET_LOCK(so, 1); 1.3368 + SCTP_TCB_LOCK(stcb); 1.3369 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.3370 +#endif 1.3371 + (void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_23); 1.3372 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3373 + SCTP_SOCKET_UNLOCK(so, 1); 1.3374 +#endif 1.3375 + return; 1.3376 +} 1.3377 + 1.3378 +static int 1.3379 +process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc, 1.3380 + struct sctp_nets *net, uint8_t flg) 1.3381 +{ 1.3382 + switch (desc->chunk_type) { 1.3383 + case SCTP_DATA: 1.3384 + /* find the tsn to resend (possibly */ 1.3385 + { 1.3386 + uint32_t tsn; 1.3387 + struct sctp_tmit_chunk *tp1; 1.3388 + 1.3389 + tsn = ntohl(desc->tsn_ifany); 1.3390 + TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 1.3391 + if (tp1->rec.data.TSN_seq == tsn) { 1.3392 + /* found it */ 1.3393 + break; 1.3394 + } 1.3395 + if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, tsn)) { 1.3396 + /* not found */ 1.3397 + tp1 = NULL; 1.3398 + break; 1.3399 + } 1.3400 + } 1.3401 + if (tp1 == NULL) { 1.3402 + /* 1.3403 + * Do it the other way , aka without paying 1.3404 + * attention to queue seq order. 1.3405 + */ 1.3406 + SCTP_STAT_INCR(sctps_pdrpdnfnd); 1.3407 + TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 1.3408 + if (tp1->rec.data.TSN_seq == tsn) { 1.3409 + /* found it */ 1.3410 + break; 1.3411 + } 1.3412 + } 1.3413 + } 1.3414 + if (tp1 == NULL) { 1.3415 + SCTP_STAT_INCR(sctps_pdrptsnnf); 1.3416 + } 1.3417 + if ((tp1) && (tp1->sent < SCTP_DATAGRAM_ACKED)) { 1.3418 + uint8_t *ddp; 1.3419 + 1.3420 + if (((flg & SCTP_BADCRC) == 0) && 1.3421 + ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 1.3422 + return (0); 1.3423 + } 1.3424 + if ((stcb->asoc.peers_rwnd == 0) && 1.3425 + ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) { 1.3426 + SCTP_STAT_INCR(sctps_pdrpdiwnp); 1.3427 + return (0); 1.3428 + } 1.3429 + if (stcb->asoc.peers_rwnd == 0 && 1.3430 + (flg & SCTP_FROM_MIDDLE_BOX)) { 1.3431 + SCTP_STAT_INCR(sctps_pdrpdizrw); 1.3432 + return (0); 1.3433 + } 1.3434 + ddp = (uint8_t *) (mtod(tp1->data, caddr_t) + 1.3435 + sizeof(struct sctp_data_chunk)); 1.3436 + { 1.3437 + unsigned int iii; 1.3438 + 1.3439 + for (iii = 0; iii < sizeof(desc->data_bytes); 1.3440 + iii++) { 1.3441 + if (ddp[iii] != desc->data_bytes[iii]) { 1.3442 + SCTP_STAT_INCR(sctps_pdrpbadd); 1.3443 + return (-1); 1.3444 + } 1.3445 + } 1.3446 + } 1.3447 + 1.3448 + if (tp1->do_rtt) { 1.3449 + /* 1.3450 + * this guy had a RTO calculation 1.3451 + * pending on it, cancel it 1.3452 + */ 1.3453 + if (tp1->whoTo->rto_needed == 0) { 1.3454 + tp1->whoTo->rto_needed = 1; 1.3455 + } 1.3456 + tp1->do_rtt = 0; 1.3457 + } 1.3458 + SCTP_STAT_INCR(sctps_pdrpmark); 1.3459 + if (tp1->sent != SCTP_DATAGRAM_RESEND) 1.3460 + sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1.3461 + /* 1.3462 + * mark it as if we were doing a FR, since 1.3463 + * we will be getting gap ack reports behind 1.3464 + * the info from the router. 1.3465 + */ 1.3466 + tp1->rec.data.doing_fast_retransmit = 1; 1.3467 + /* 1.3468 + * mark the tsn with what sequences can 1.3469 + * cause a new FR. 1.3470 + */ 1.3471 + if (TAILQ_EMPTY(&stcb->asoc.send_queue)) { 1.3472 + tp1->rec.data.fast_retran_tsn = stcb->asoc.sending_seq; 1.3473 + } else { 1.3474 + tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq; 1.3475 + } 1.3476 + 1.3477 + /* restart the timer */ 1.3478 + sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 1.3479 + stcb, tp1->whoTo, SCTP_FROM_SCTP_INPUT+SCTP_LOC_24); 1.3480 + sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, 1.3481 + stcb, tp1->whoTo); 1.3482 + 1.3483 + /* fix counts and things */ 1.3484 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) { 1.3485 + sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP, 1.3486 + tp1->whoTo->flight_size, 1.3487 + tp1->book_size, 1.3488 + (uintptr_t)stcb, 1.3489 + tp1->rec.data.TSN_seq); 1.3490 + } 1.3491 + if (tp1->sent < SCTP_DATAGRAM_RESEND) { 1.3492 + sctp_flight_size_decrease(tp1); 1.3493 + sctp_total_flight_decrease(stcb, tp1); 1.3494 + } 1.3495 + tp1->sent = SCTP_DATAGRAM_RESEND; 1.3496 + } { 1.3497 + /* audit code */ 1.3498 + unsigned int audit; 1.3499 + 1.3500 + audit = 0; 1.3501 + TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) { 1.3502 + if (tp1->sent == SCTP_DATAGRAM_RESEND) 1.3503 + audit++; 1.3504 + } 1.3505 + TAILQ_FOREACH(tp1, &stcb->asoc.control_send_queue, 1.3506 + sctp_next) { 1.3507 + if (tp1->sent == SCTP_DATAGRAM_RESEND) 1.3508 + audit++; 1.3509 + } 1.3510 + if (audit != stcb->asoc.sent_queue_retran_cnt) { 1.3511 + SCTP_PRINTF("**Local Audit finds cnt:%d asoc cnt:%d\n", 1.3512 + audit, stcb->asoc.sent_queue_retran_cnt); 1.3513 +#ifndef SCTP_AUDITING_ENABLED 1.3514 + stcb->asoc.sent_queue_retran_cnt = audit; 1.3515 +#endif 1.3516 + } 1.3517 + } 1.3518 + } 1.3519 + break; 1.3520 + case SCTP_ASCONF: 1.3521 + { 1.3522 + struct sctp_tmit_chunk *asconf; 1.3523 + 1.3524 + TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue, 1.3525 + sctp_next) { 1.3526 + if (asconf->rec.chunk_id.id == SCTP_ASCONF) { 1.3527 + break; 1.3528 + } 1.3529 + } 1.3530 + if (asconf) { 1.3531 + if (asconf->sent != SCTP_DATAGRAM_RESEND) 1.3532 + sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1.3533 + asconf->sent = SCTP_DATAGRAM_RESEND; 1.3534 + asconf->snd_count--; 1.3535 + } 1.3536 + } 1.3537 + break; 1.3538 + case SCTP_INITIATION: 1.3539 + /* resend the INIT */ 1.3540 + stcb->asoc.dropped_special_cnt++; 1.3541 + if (stcb->asoc.dropped_special_cnt < SCTP_RETRY_DROPPED_THRESH) { 1.3542 + /* 1.3543 + * If we can get it in, in a few attempts we do 1.3544 + * this, otherwise we let the timer fire. 1.3545 + */ 1.3546 + sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, 1.3547 + stcb, net, SCTP_FROM_SCTP_INPUT+SCTP_LOC_25); 1.3548 + sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED); 1.3549 + } 1.3550 + break; 1.3551 + case SCTP_SELECTIVE_ACK: 1.3552 + case SCTP_NR_SELECTIVE_ACK: 1.3553 + /* resend the sack */ 1.3554 + sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 1.3555 + break; 1.3556 + case SCTP_HEARTBEAT_REQUEST: 1.3557 + /* resend a demand HB */ 1.3558 + if ((stcb->asoc.overall_error_count + 3) < stcb->asoc.max_send_times) { 1.3559 + /* Only retransmit if we KNOW we wont destroy the tcb */ 1.3560 + sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED); 1.3561 + } 1.3562 + break; 1.3563 + case SCTP_SHUTDOWN: 1.3564 + sctp_send_shutdown(stcb, net); 1.3565 + break; 1.3566 + case SCTP_SHUTDOWN_ACK: 1.3567 + sctp_send_shutdown_ack(stcb, net); 1.3568 + break; 1.3569 + case SCTP_COOKIE_ECHO: 1.3570 + { 1.3571 + struct sctp_tmit_chunk *cookie; 1.3572 + 1.3573 + cookie = NULL; 1.3574 + TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue, 1.3575 + sctp_next) { 1.3576 + if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) { 1.3577 + break; 1.3578 + } 1.3579 + } 1.3580 + if (cookie) { 1.3581 + if (cookie->sent != SCTP_DATAGRAM_RESEND) 1.3582 + sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt); 1.3583 + cookie->sent = SCTP_DATAGRAM_RESEND; 1.3584 + sctp_stop_all_cookie_timers(stcb); 1.3585 + } 1.3586 + } 1.3587 + break; 1.3588 + case SCTP_COOKIE_ACK: 1.3589 + sctp_send_cookie_ack(stcb); 1.3590 + break; 1.3591 + case SCTP_ASCONF_ACK: 1.3592 + /* resend last asconf ack */ 1.3593 + sctp_send_asconf_ack(stcb); 1.3594 + break; 1.3595 + case SCTP_FORWARD_CUM_TSN: 1.3596 + send_forward_tsn(stcb, &stcb->asoc); 1.3597 + break; 1.3598 + /* can't do anything with these */ 1.3599 + case SCTP_PACKET_DROPPED: 1.3600 + case SCTP_INITIATION_ACK: /* this should not happen */ 1.3601 + case SCTP_HEARTBEAT_ACK: 1.3602 + case SCTP_ABORT_ASSOCIATION: 1.3603 + case SCTP_OPERATION_ERROR: 1.3604 + case SCTP_SHUTDOWN_COMPLETE: 1.3605 + case SCTP_ECN_ECHO: 1.3606 + case SCTP_ECN_CWR: 1.3607 + default: 1.3608 + break; 1.3609 + } 1.3610 + return (0); 1.3611 +} 1.3612 + 1.3613 +void 1.3614 +sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *list) 1.3615 +{ 1.3616 + uint32_t i; 1.3617 + uint16_t temp; 1.3618 + 1.3619 + /* 1.3620 + * We set things to 0xffff since this is the last delivered sequence 1.3621 + * and we will be sending in 0 after the reset. 1.3622 + */ 1.3623 + 1.3624 + if (number_entries) { 1.3625 + for (i = 0; i < number_entries; i++) { 1.3626 + temp = ntohs(list[i]); 1.3627 + if (temp >= stcb->asoc.streamincnt) { 1.3628 + continue; 1.3629 + } 1.3630 + stcb->asoc.strmin[temp].last_sequence_delivered = 0xffff; 1.3631 + } 1.3632 + } else { 1.3633 + list = NULL; 1.3634 + for (i = 0; i < stcb->asoc.streamincnt; i++) { 1.3635 + stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 1.3636 + } 1.3637 + } 1.3638 + sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 1.3639 +} 1.3640 + 1.3641 +static void 1.3642 +sctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *list) 1.3643 +{ 1.3644 + uint32_t i; 1.3645 + uint16_t temp; 1.3646 + 1.3647 + if (number_entries > 0) { 1.3648 + for (i = 0; i < number_entries; i++) { 1.3649 + temp = ntohs(list[i]); 1.3650 + if (temp >= stcb->asoc.streamoutcnt) { 1.3651 + /* no such stream */ 1.3652 + continue; 1.3653 + } 1.3654 + stcb->asoc.strmout[temp].next_sequence_send = 0; 1.3655 + } 1.3656 + } else { 1.3657 + for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 1.3658 + stcb->asoc.strmout[i].next_sequence_send = 0; 1.3659 + } 1.3660 + } 1.3661 + sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED); 1.3662 +} 1.3663 + 1.3664 + 1.3665 +struct sctp_stream_reset_out_request * 1.3666 +sctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk) 1.3667 +{ 1.3668 + struct sctp_association *asoc; 1.3669 + struct sctp_chunkhdr *ch; 1.3670 + struct sctp_stream_reset_out_request *r; 1.3671 + struct sctp_tmit_chunk *chk; 1.3672 + int len, clen; 1.3673 + 1.3674 + asoc = &stcb->asoc; 1.3675 + if (TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 1.3676 + asoc->stream_reset_outstanding = 0; 1.3677 + return (NULL); 1.3678 + } 1.3679 + if (stcb->asoc.str_reset == NULL) { 1.3680 + asoc->stream_reset_outstanding = 0; 1.3681 + return (NULL); 1.3682 + } 1.3683 + chk = stcb->asoc.str_reset; 1.3684 + if (chk->data == NULL) { 1.3685 + return (NULL); 1.3686 + } 1.3687 + if (bchk) { 1.3688 + /* he wants a copy of the chk pointer */ 1.3689 + *bchk = chk; 1.3690 + } 1.3691 + clen = chk->send_size; 1.3692 + ch = mtod(chk->data, struct sctp_chunkhdr *); 1.3693 + r = (struct sctp_stream_reset_out_request *)(ch + 1); 1.3694 + if (ntohl(r->request_seq) == seq) { 1.3695 + /* found it */ 1.3696 + return (r); 1.3697 + } 1.3698 + len = SCTP_SIZE32(ntohs(r->ph.param_length)); 1.3699 + if (clen > (len + (int)sizeof(struct sctp_chunkhdr))) { 1.3700 + /* move to the next one, there can only be a max of two */ 1.3701 + r = (struct sctp_stream_reset_out_request *)((caddr_t)r + len); 1.3702 + if (ntohl(r->request_seq) == seq) { 1.3703 + return (r); 1.3704 + } 1.3705 + } 1.3706 + /* that seq is not here */ 1.3707 + return (NULL); 1.3708 +} 1.3709 + 1.3710 +static void 1.3711 +sctp_clean_up_stream_reset(struct sctp_tcb *stcb) 1.3712 +{ 1.3713 + struct sctp_association *asoc; 1.3714 + struct sctp_tmit_chunk *chk = stcb->asoc.str_reset; 1.3715 + 1.3716 + if (stcb->asoc.str_reset == NULL) { 1.3717 + return; 1.3718 + } 1.3719 + asoc = &stcb->asoc; 1.3720 + 1.3721 + sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo, SCTP_FROM_SCTP_INPUT+SCTP_LOC_26); 1.3722 + TAILQ_REMOVE(&asoc->control_send_queue, 1.3723 + chk, 1.3724 + sctp_next); 1.3725 + if (chk->data) { 1.3726 + sctp_m_freem(chk->data); 1.3727 + chk->data = NULL; 1.3728 + } 1.3729 + asoc->ctrl_queue_cnt--; 1.3730 + sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 1.3731 + /*sa_ignore NO_NULL_CHK*/ 1.3732 + stcb->asoc.str_reset = NULL; 1.3733 +} 1.3734 + 1.3735 + 1.3736 +static int 1.3737 +sctp_handle_stream_reset_response(struct sctp_tcb *stcb, 1.3738 + uint32_t seq, uint32_t action, 1.3739 + struct sctp_stream_reset_response *respin) 1.3740 +{ 1.3741 + uint16_t type; 1.3742 + int lparm_len; 1.3743 + struct sctp_association *asoc = &stcb->asoc; 1.3744 + struct sctp_tmit_chunk *chk; 1.3745 + struct sctp_stream_reset_out_request *srparam; 1.3746 + uint32_t number_entries; 1.3747 + 1.3748 + if (asoc->stream_reset_outstanding == 0) { 1.3749 + /* duplicate */ 1.3750 + return (0); 1.3751 + } 1.3752 + if (seq == stcb->asoc.str_reset_seq_out) { 1.3753 + srparam = sctp_find_stream_reset(stcb, seq, &chk); 1.3754 + if (srparam) { 1.3755 + stcb->asoc.str_reset_seq_out++; 1.3756 + type = ntohs(srparam->ph.param_type); 1.3757 + lparm_len = ntohs(srparam->ph.param_length); 1.3758 + if (type == SCTP_STR_RESET_OUT_REQUEST) { 1.3759 + number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t); 1.3760 + asoc->stream_reset_out_is_outstanding = 0; 1.3761 + if (asoc->stream_reset_outstanding) 1.3762 + asoc->stream_reset_outstanding--; 1.3763 + if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 1.3764 + /* do it */ 1.3765 + sctp_reset_out_streams(stcb, number_entries, srparam->list_of_streams); 1.3766 + } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 1.3767 + sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 1.3768 + } else { 1.3769 + sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 1.3770 + } 1.3771 + } else if (type == SCTP_STR_RESET_IN_REQUEST) { 1.3772 + /* Answered my request */ 1.3773 + number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t); 1.3774 + if (asoc->stream_reset_outstanding) 1.3775 + asoc->stream_reset_outstanding--; 1.3776 + if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 1.3777 + sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_IN, stcb, 1.3778 + number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 1.3779 + } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 1.3780 + sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb, 1.3781 + number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED); 1.3782 + } 1.3783 + } else if (type == SCTP_STR_RESET_ADD_OUT_STREAMS) { 1.3784 + /* Ok we now may have more streams */ 1.3785 + int num_stream; 1.3786 + 1.3787 + num_stream = stcb->asoc.strm_pending_add_size; 1.3788 + if (num_stream > (stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt)) { 1.3789 + /* TSNH */ 1.3790 + num_stream = stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt; 1.3791 + } 1.3792 + stcb->asoc.strm_pending_add_size = 0; 1.3793 + if (asoc->stream_reset_outstanding) 1.3794 + asoc->stream_reset_outstanding--; 1.3795 + if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 1.3796 + /* Put the new streams into effect */ 1.3797 + stcb->asoc.streamoutcnt += num_stream; 1.3798 + sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 1.3799 + } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 1.3800 + sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 1.3801 + SCTP_STREAM_CHANGE_DENIED); 1.3802 + } else { 1.3803 + sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 1.3804 + SCTP_STREAM_CHANGE_FAILED); 1.3805 + } 1.3806 + } else if (type == SCTP_STR_RESET_ADD_IN_STREAMS) { 1.3807 + if (asoc->stream_reset_outstanding) 1.3808 + asoc->stream_reset_outstanding--; 1.3809 + if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 1.3810 + sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 1.3811 + SCTP_STREAM_CHANGE_DENIED); 1.3812 + } else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) { 1.3813 + sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 1.3814 + SCTP_STREAM_CHANGE_FAILED); 1.3815 + } 1.3816 + } else if (type == SCTP_STR_RESET_TSN_REQUEST) { 1.3817 + /** 1.3818 + * a) Adopt the new in tsn. 1.3819 + * b) reset the map 1.3820 + * c) Adopt the new out-tsn 1.3821 + */ 1.3822 + struct sctp_stream_reset_response_tsn *resp; 1.3823 + struct sctp_forward_tsn_chunk fwdtsn; 1.3824 + int abort_flag = 0; 1.3825 + if (respin == NULL) { 1.3826 + /* huh ? */ 1.3827 + return (0); 1.3828 + } 1.3829 + if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) { 1.3830 + resp = (struct sctp_stream_reset_response_tsn *)respin; 1.3831 + asoc->stream_reset_outstanding--; 1.3832 + fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 1.3833 + fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 1.3834 + fwdtsn.new_cumulative_tsn = htonl(ntohl(resp->senders_next_tsn) - 1); 1.3835 + sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 1.3836 + if (abort_flag) { 1.3837 + return (1); 1.3838 + } 1.3839 + stcb->asoc.highest_tsn_inside_map = (ntohl(resp->senders_next_tsn) - 1); 1.3840 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 1.3841 + sctp_log_map(0, 7, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 1.3842 + } 1.3843 + 1.3844 + stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map; 1.3845 + stcb->asoc.mapping_array_base_tsn = ntohl(resp->senders_next_tsn); 1.3846 + memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size); 1.3847 + 1.3848 + stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map; 1.3849 + memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size); 1.3850 + 1.3851 + stcb->asoc.sending_seq = ntohl(resp->receivers_next_tsn); 1.3852 + stcb->asoc.last_acked_seq = stcb->asoc.cumulative_tsn; 1.3853 + 1.3854 + sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 1.3855 + sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 1.3856 + sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 0); 1.3857 + } else if (action == SCTP_STREAM_RESET_RESULT_DENIED) { 1.3858 + sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 1.3859 + SCTP_ASSOC_RESET_DENIED); 1.3860 + } else { 1.3861 + sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 1.3862 + SCTP_ASSOC_RESET_FAILED); 1.3863 + } 1.3864 + } 1.3865 + /* get rid of the request and get the request flags */ 1.3866 + if (asoc->stream_reset_outstanding == 0) { 1.3867 + sctp_clean_up_stream_reset(stcb); 1.3868 + } 1.3869 + } 1.3870 + } 1.3871 + return (0); 1.3872 +} 1.3873 + 1.3874 +static void 1.3875 +sctp_handle_str_reset_request_in(struct sctp_tcb *stcb, 1.3876 + struct sctp_tmit_chunk *chk, 1.3877 + struct sctp_stream_reset_in_request *req, int trunc) 1.3878 +{ 1.3879 + uint32_t seq; 1.3880 + int len, i; 1.3881 + int number_entries; 1.3882 + uint16_t temp; 1.3883 + 1.3884 + /* 1.3885 + * peer wants me to send a str-reset to him for my outgoing seq's if 1.3886 + * seq_in is right. 1.3887 + */ 1.3888 + struct sctp_association *asoc = &stcb->asoc; 1.3889 + 1.3890 + seq = ntohl(req->request_seq); 1.3891 + if (asoc->str_reset_seq_in == seq) { 1.3892 + asoc->last_reset_action[1] = asoc->last_reset_action[0]; 1.3893 + if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 1.3894 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 1.3895 + } else if (trunc) { 1.3896 + /* Can't do it, since they exceeded our buffer size */ 1.3897 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 1.3898 + } else if (stcb->asoc.stream_reset_out_is_outstanding == 0) { 1.3899 + len = ntohs(req->ph.param_length); 1.3900 + number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t)); 1.3901 + for (i = 0; i < number_entries; i++) { 1.3902 + temp = ntohs(req->list_of_streams[i]); 1.3903 + req->list_of_streams[i] = temp; 1.3904 + } 1.3905 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 1.3906 + sctp_add_stream_reset_out(chk, number_entries, req->list_of_streams, 1.3907 + asoc->str_reset_seq_out, 1.3908 + seq, (asoc->sending_seq - 1)); 1.3909 + asoc->stream_reset_out_is_outstanding = 1; 1.3910 + asoc->str_reset = chk; 1.3911 + sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo); 1.3912 + stcb->asoc.stream_reset_outstanding++; 1.3913 + } else { 1.3914 + /* Can't do it, since we have sent one out */ 1.3915 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 1.3916 + } 1.3917 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 1.3918 + asoc->str_reset_seq_in++; 1.3919 + } else if (asoc->str_reset_seq_in - 1 == seq) { 1.3920 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 1.3921 + } else if (asoc->str_reset_seq_in - 2 == seq) { 1.3922 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 1.3923 + } else { 1.3924 + sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 1.3925 + } 1.3926 +} 1.3927 + 1.3928 +static int 1.3929 +sctp_handle_str_reset_request_tsn(struct sctp_tcb *stcb, 1.3930 + struct sctp_tmit_chunk *chk, 1.3931 + struct sctp_stream_reset_tsn_request *req) 1.3932 +{ 1.3933 + /* reset all in and out and update the tsn */ 1.3934 + /* 1.3935 + * A) reset my str-seq's on in and out. B) Select a receive next, 1.3936 + * and set cum-ack to it. Also process this selected number as a 1.3937 + * fwd-tsn as well. C) set in the response my next sending seq. 1.3938 + */ 1.3939 + struct sctp_forward_tsn_chunk fwdtsn; 1.3940 + struct sctp_association *asoc = &stcb->asoc; 1.3941 + int abort_flag = 0; 1.3942 + uint32_t seq; 1.3943 + 1.3944 + seq = ntohl(req->request_seq); 1.3945 + if (asoc->str_reset_seq_in == seq) { 1.3946 + asoc->last_reset_action[1] = stcb->asoc.last_reset_action[0]; 1.3947 + if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 1.3948 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 1.3949 + } else { 1.3950 + fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk)); 1.3951 + fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN; 1.3952 + fwdtsn.ch.chunk_flags = 0; 1.3953 + fwdtsn.new_cumulative_tsn = htonl(stcb->asoc.highest_tsn_inside_map + 1); 1.3954 + sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0); 1.3955 + if (abort_flag) { 1.3956 + return (1); 1.3957 + } 1.3958 + asoc->highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA; 1.3959 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) { 1.3960 + sctp_log_map(0, 10, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT); 1.3961 + } 1.3962 + asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->highest_tsn_inside_map; 1.3963 + asoc->mapping_array_base_tsn = asoc->highest_tsn_inside_map + 1; 1.3964 + memset(asoc->mapping_array, 0, asoc->mapping_array_size); 1.3965 + asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map; 1.3966 + memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size); 1.3967 + atomic_add_int(&asoc->sending_seq, 1); 1.3968 + /* save off historical data for retrans */ 1.3969 + asoc->last_sending_seq[1] = asoc->last_sending_seq[0]; 1.3970 + asoc->last_sending_seq[0] = asoc->sending_seq; 1.3971 + asoc->last_base_tsnsent[1] = asoc->last_base_tsnsent[0]; 1.3972 + asoc->last_base_tsnsent[0] = asoc->mapping_array_base_tsn; 1.3973 + sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL); 1.3974 + sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL); 1.3975 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 1.3976 + sctp_notify_stream_reset_tsn(stcb, asoc->sending_seq, (asoc->mapping_array_base_tsn + 1), 0); 1.3977 + } 1.3978 + sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 1.3979 + asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 1.3980 + asoc->str_reset_seq_in++; 1.3981 + } else if (asoc->str_reset_seq_in - 1 == seq) { 1.3982 + sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0], 1.3983 + asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]); 1.3984 + } else if (asoc->str_reset_seq_in - 2 == seq) { 1.3985 + sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[1], 1.3986 + asoc->last_sending_seq[1], asoc->last_base_tsnsent[1]); 1.3987 + } else { 1.3988 + sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 1.3989 + } 1.3990 + return (0); 1.3991 +} 1.3992 + 1.3993 +static void 1.3994 +sctp_handle_str_reset_request_out(struct sctp_tcb *stcb, 1.3995 + struct sctp_tmit_chunk *chk, 1.3996 + struct sctp_stream_reset_out_request *req, int trunc) 1.3997 +{ 1.3998 + uint32_t seq, tsn; 1.3999 + int number_entries, len; 1.4000 + struct sctp_association *asoc = &stcb->asoc; 1.4001 + 1.4002 + seq = ntohl(req->request_seq); 1.4003 + 1.4004 + /* now if its not a duplicate we process it */ 1.4005 + if (asoc->str_reset_seq_in == seq) { 1.4006 + len = ntohs(req->ph.param_length); 1.4007 + number_entries = ((len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t)); 1.4008 + /* 1.4009 + * the sender is resetting, handle the list issue.. we must 1.4010 + * a) verify if we can do the reset, if so no problem b) If 1.4011 + * we can't do the reset we must copy the request. c) queue 1.4012 + * it, and setup the data in processor to trigger it off 1.4013 + * when needed and dequeue all the queued data. 1.4014 + */ 1.4015 + tsn = ntohl(req->send_reset_at_tsn); 1.4016 + 1.4017 + /* move the reset action back one */ 1.4018 + asoc->last_reset_action[1] = asoc->last_reset_action[0]; 1.4019 + if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) { 1.4020 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 1.4021 + } else if (trunc) { 1.4022 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 1.4023 + } else if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) { 1.4024 + /* we can do it now */ 1.4025 + sctp_reset_in_stream(stcb, number_entries, req->list_of_streams); 1.4026 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 1.4027 + } else { 1.4028 + /* 1.4029 + * we must queue it up and thus wait for the TSN's 1.4030 + * to arrive that are at or before tsn 1.4031 + */ 1.4032 + struct sctp_stream_reset_list *liste; 1.4033 + int siz; 1.4034 + 1.4035 + siz = sizeof(struct sctp_stream_reset_list) + (number_entries * sizeof(uint16_t)); 1.4036 + SCTP_MALLOC(liste, struct sctp_stream_reset_list *, 1.4037 + siz, SCTP_M_STRESET); 1.4038 + if (liste == NULL) { 1.4039 + /* gak out of memory */ 1.4040 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 1.4041 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 1.4042 + return; 1.4043 + } 1.4044 + liste->tsn = tsn; 1.4045 + liste->number_entries = number_entries; 1.4046 + memcpy(&liste->list_of_streams, req->list_of_streams, number_entries * sizeof(uint16_t)); 1.4047 + TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp); 1.4048 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 1.4049 + } 1.4050 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 1.4051 + asoc->str_reset_seq_in++; 1.4052 + } else if ((asoc->str_reset_seq_in - 1) == seq) { 1.4053 + /* 1.4054 + * one seq back, just echo back last action since my 1.4055 + * response was lost. 1.4056 + */ 1.4057 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 1.4058 + } else if ((asoc->str_reset_seq_in - 2) == seq) { 1.4059 + /* 1.4060 + * two seq back, just echo back last action since my 1.4061 + * response was lost. 1.4062 + */ 1.4063 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 1.4064 + } else { 1.4065 + sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 1.4066 + } 1.4067 +} 1.4068 + 1.4069 +static void 1.4070 +sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 1.4071 + struct sctp_stream_reset_add_strm *str_add) 1.4072 +{ 1.4073 + /* 1.4074 + * Peer is requesting to add more streams. 1.4075 + * If its within our max-streams we will 1.4076 + * allow it. 1.4077 + */ 1.4078 + uint32_t num_stream, i; 1.4079 + uint32_t seq; 1.4080 + struct sctp_association *asoc = &stcb->asoc; 1.4081 + struct sctp_queued_to_read *ctl, *nctl; 1.4082 + 1.4083 + /* Get the number. */ 1.4084 + seq = ntohl(str_add->request_seq); 1.4085 + num_stream = ntohs(str_add->number_of_streams); 1.4086 + /* Now what would be the new total? */ 1.4087 + if (asoc->str_reset_seq_in == seq) { 1.4088 + num_stream += stcb->asoc.streamincnt; 1.4089 + stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 1.4090 + if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 1.4091 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 1.4092 + } else if ((num_stream > stcb->asoc.max_inbound_streams) || 1.4093 + (num_stream > 0xffff)) { 1.4094 + /* We must reject it they ask for to many */ 1.4095 + denied: 1.4096 + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 1.4097 + } else { 1.4098 + /* Ok, we can do that :-) */ 1.4099 + struct sctp_stream_in *oldstrm; 1.4100 + 1.4101 + /* save off the old */ 1.4102 + oldstrm = stcb->asoc.strmin; 1.4103 + SCTP_MALLOC(stcb->asoc.strmin, struct sctp_stream_in *, 1.4104 + (num_stream * sizeof(struct sctp_stream_in)), 1.4105 + SCTP_M_STRMI); 1.4106 + if (stcb->asoc.strmin == NULL) { 1.4107 + stcb->asoc.strmin = oldstrm; 1.4108 + goto denied; 1.4109 + } 1.4110 + /* copy off the old data */ 1.4111 + for (i = 0; i < stcb->asoc.streamincnt; i++) { 1.4112 + TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 1.4113 + stcb->asoc.strmin[i].stream_no = i; 1.4114 + stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered; 1.4115 + stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started; 1.4116 + /* now anything on those queues? */ 1.4117 + TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next, nctl) { 1.4118 + TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next); 1.4119 + TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next); 1.4120 + } 1.4121 + } 1.4122 + /* Init the new streams */ 1.4123 + for (i = stcb->asoc.streamincnt; i < num_stream; i++) { 1.4124 + TAILQ_INIT(&stcb->asoc.strmin[i].inqueue); 1.4125 + stcb->asoc.strmin[i].stream_no = i; 1.4126 + stcb->asoc.strmin[i].last_sequence_delivered = 0xffff; 1.4127 + stcb->asoc.strmin[i].delivery_started = 0; 1.4128 + } 1.4129 + SCTP_FREE(oldstrm, SCTP_M_STRMI); 1.4130 + /* update the size */ 1.4131 + stcb->asoc.streamincnt = num_stream; 1.4132 + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 1.4133 + sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0); 1.4134 + } 1.4135 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 1.4136 + asoc->str_reset_seq_in++; 1.4137 + } else if ((asoc->str_reset_seq_in - 1) == seq) { 1.4138 + /* 1.4139 + * one seq back, just echo back last action since my 1.4140 + * response was lost. 1.4141 + */ 1.4142 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 1.4143 + } else if ((asoc->str_reset_seq_in - 2) == seq) { 1.4144 + /* 1.4145 + * two seq back, just echo back last action since my 1.4146 + * response was lost. 1.4147 + */ 1.4148 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 1.4149 + } else { 1.4150 + sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 1.4151 + 1.4152 + } 1.4153 +} 1.4154 + 1.4155 +static void 1.4156 +sctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk, 1.4157 + struct sctp_stream_reset_add_strm *str_add) 1.4158 +{ 1.4159 + /* 1.4160 + * Peer is requesting to add more streams. 1.4161 + * If its within our max-streams we will 1.4162 + * allow it. 1.4163 + */ 1.4164 + uint16_t num_stream; 1.4165 + uint32_t seq; 1.4166 + struct sctp_association *asoc = &stcb->asoc; 1.4167 + 1.4168 + /* Get the number. */ 1.4169 + seq = ntohl(str_add->request_seq); 1.4170 + num_stream = ntohs(str_add->number_of_streams); 1.4171 + /* Now what would be the new total? */ 1.4172 + if (asoc->str_reset_seq_in == seq) { 1.4173 + stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0]; 1.4174 + if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) { 1.4175 + asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 1.4176 + } else if (stcb->asoc.stream_reset_outstanding) { 1.4177 + /* We must reject it we have something pending */ 1.4178 + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS; 1.4179 + } else { 1.4180 + /* Ok, we can do that :-) */ 1.4181 + int mychk; 1.4182 + mychk = stcb->asoc.streamoutcnt; 1.4183 + mychk += num_stream; 1.4184 + if (mychk < 0x10000) { 1.4185 + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED; 1.4186 + if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, 1, num_stream, 0, 1)) { 1.4187 + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 1.4188 + } 1.4189 + } else { 1.4190 + stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED; 1.4191 + } 1.4192 + } 1.4193 + sctp_add_stream_reset_result(chk, seq, stcb->asoc.last_reset_action[0]); 1.4194 + asoc->str_reset_seq_in++; 1.4195 + } else if ((asoc->str_reset_seq_in - 1) == seq) { 1.4196 + /* 1.4197 + * one seq back, just echo back last action since my 1.4198 + * response was lost. 1.4199 + */ 1.4200 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]); 1.4201 + } else if ((asoc->str_reset_seq_in - 2) == seq) { 1.4202 + /* 1.4203 + * two seq back, just echo back last action since my 1.4204 + * response was lost. 1.4205 + */ 1.4206 + sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]); 1.4207 + } else { 1.4208 + sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO); 1.4209 + } 1.4210 +} 1.4211 + 1.4212 +#if !defined(__Panda__) 1.4213 +#ifdef __GNUC__ 1.4214 +__attribute__ ((noinline)) 1.4215 +#endif 1.4216 +#endif 1.4217 +static int 1.4218 +sctp_handle_stream_reset(struct sctp_tcb *stcb, struct mbuf *m, int offset, 1.4219 + struct sctp_chunkhdr *ch_req) 1.4220 +{ 1.4221 + int chk_length, param_len, ptype; 1.4222 + struct sctp_paramhdr pstore; 1.4223 + uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE]; 1.4224 + uint32_t seq = 0; 1.4225 + int num_req = 0; 1.4226 + int trunc = 0; 1.4227 + struct sctp_tmit_chunk *chk; 1.4228 + struct sctp_chunkhdr *ch; 1.4229 + struct sctp_paramhdr *ph; 1.4230 + int ret_code = 0; 1.4231 + int num_param = 0; 1.4232 + 1.4233 + /* now it may be a reset or a reset-response */ 1.4234 + chk_length = ntohs(ch_req->chunk_length); 1.4235 + 1.4236 + /* setup for adding the response */ 1.4237 + sctp_alloc_a_chunk(stcb, chk); 1.4238 + if (chk == NULL) { 1.4239 + return (ret_code); 1.4240 + } 1.4241 + chk->rec.chunk_id.id = SCTP_STREAM_RESET; 1.4242 + chk->rec.chunk_id.can_take_data = 0; 1.4243 + chk->asoc = &stcb->asoc; 1.4244 + chk->no_fr_allowed = 0; 1.4245 + chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr); 1.4246 + chk->book_size_scale = 0; 1.4247 + chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); 1.4248 + if (chk->data == NULL) { 1.4249 + strres_nochunk: 1.4250 + if (chk->data) { 1.4251 + sctp_m_freem(chk->data); 1.4252 + chk->data = NULL; 1.4253 + } 1.4254 + sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED); 1.4255 + return (ret_code); 1.4256 + } 1.4257 + SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD); 1.4258 + 1.4259 + /* setup chunk parameters */ 1.4260 + chk->sent = SCTP_DATAGRAM_UNSENT; 1.4261 + chk->snd_count = 0; 1.4262 + chk->whoTo = NULL; 1.4263 + 1.4264 + ch = mtod(chk->data, struct sctp_chunkhdr *); 1.4265 + ch->chunk_type = SCTP_STREAM_RESET; 1.4266 + ch->chunk_flags = 0; 1.4267 + ch->chunk_length = htons(chk->send_size); 1.4268 + SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size); 1.4269 + offset += sizeof(struct sctp_chunkhdr); 1.4270 + while ((size_t)chk_length >= sizeof(struct sctp_stream_reset_tsn_request)) { 1.4271 + ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(pstore), (uint8_t *)&pstore); 1.4272 + if (ph == NULL) 1.4273 + break; 1.4274 + param_len = ntohs(ph->param_length); 1.4275 + if (param_len < (int)sizeof(struct sctp_stream_reset_tsn_request)) { 1.4276 + /* bad param */ 1.4277 + break; 1.4278 + } 1.4279 + ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, (int)sizeof(cstore)), 1.4280 + (uint8_t *)&cstore); 1.4281 + ptype = ntohs(ph->param_type); 1.4282 + num_param++; 1.4283 + if (param_len > (int)sizeof(cstore)) { 1.4284 + trunc = 1; 1.4285 + } else { 1.4286 + trunc = 0; 1.4287 + } 1.4288 + if (num_param > SCTP_MAX_RESET_PARAMS) { 1.4289 + /* hit the max of parameters already sorry.. */ 1.4290 + break; 1.4291 + } 1.4292 + if (ptype == SCTP_STR_RESET_OUT_REQUEST) { 1.4293 + struct sctp_stream_reset_out_request *req_out; 1.4294 + req_out = (struct sctp_stream_reset_out_request *)ph; 1.4295 + num_req++; 1.4296 + if (stcb->asoc.stream_reset_outstanding) { 1.4297 + seq = ntohl(req_out->response_seq); 1.4298 + if (seq == stcb->asoc.str_reset_seq_out) { 1.4299 + /* implicit ack */ 1.4300 + (void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_RESULT_PERFORMED, NULL); 1.4301 + } 1.4302 + } 1.4303 + sctp_handle_str_reset_request_out(stcb, chk, req_out, trunc); 1.4304 + } else if (ptype == SCTP_STR_RESET_ADD_OUT_STREAMS) { 1.4305 + struct sctp_stream_reset_add_strm *str_add; 1.4306 + str_add = (struct sctp_stream_reset_add_strm *)ph; 1.4307 + num_req++; 1.4308 + sctp_handle_str_reset_add_strm(stcb, chk, str_add); 1.4309 + } else if (ptype == SCTP_STR_RESET_ADD_IN_STREAMS) { 1.4310 + struct sctp_stream_reset_add_strm *str_add; 1.4311 + str_add = (struct sctp_stream_reset_add_strm *)ph; 1.4312 + num_req++; 1.4313 + sctp_handle_str_reset_add_out_strm(stcb, chk, str_add); 1.4314 + } else if (ptype == SCTP_STR_RESET_IN_REQUEST) { 1.4315 + struct sctp_stream_reset_in_request *req_in; 1.4316 + num_req++; 1.4317 + req_in = (struct sctp_stream_reset_in_request *)ph; 1.4318 + sctp_handle_str_reset_request_in(stcb, chk, req_in, trunc); 1.4319 + } else if (ptype == SCTP_STR_RESET_TSN_REQUEST) { 1.4320 + struct sctp_stream_reset_tsn_request *req_tsn; 1.4321 + num_req++; 1.4322 + req_tsn = (struct sctp_stream_reset_tsn_request *)ph; 1.4323 + if (sctp_handle_str_reset_request_tsn(stcb, chk, req_tsn)) { 1.4324 + ret_code = 1; 1.4325 + goto strres_nochunk; 1.4326 + } 1.4327 + /* no more */ 1.4328 + break; 1.4329 + } else if (ptype == SCTP_STR_RESET_RESPONSE) { 1.4330 + struct sctp_stream_reset_response *resp; 1.4331 + uint32_t result; 1.4332 + resp = (struct sctp_stream_reset_response *)ph; 1.4333 + seq = ntohl(resp->response_seq); 1.4334 + result = ntohl(resp->result); 1.4335 + if (sctp_handle_stream_reset_response(stcb, seq, result, resp)) { 1.4336 + ret_code = 1; 1.4337 + goto strres_nochunk; 1.4338 + } 1.4339 + } else { 1.4340 + break; 1.4341 + } 1.4342 + offset += SCTP_SIZE32(param_len); 1.4343 + chk_length -= SCTP_SIZE32(param_len); 1.4344 + } 1.4345 + if (num_req == 0) { 1.4346 + /* we have no response free the stuff */ 1.4347 + goto strres_nochunk; 1.4348 + } 1.4349 + /* ok we have a chunk to link in */ 1.4350 + TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue, 1.4351 + chk, 1.4352 + sctp_next); 1.4353 + stcb->asoc.ctrl_queue_cnt++; 1.4354 + return (ret_code); 1.4355 +} 1.4356 + 1.4357 +/* 1.4358 + * Handle a router or endpoints report of a packet loss, there are two ways 1.4359 + * to handle this, either we get the whole packet and must disect it 1.4360 + * ourselves (possibly with truncation and or corruption) or it is a summary 1.4361 + * from a middle box that did the disectting for us. 1.4362 + */ 1.4363 +static void 1.4364 +sctp_handle_packet_dropped(struct sctp_pktdrop_chunk *cp, 1.4365 + struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t limit) 1.4366 +{ 1.4367 + uint32_t bottle_bw, on_queue; 1.4368 + uint16_t trunc_len; 1.4369 + unsigned int chlen; 1.4370 + unsigned int at; 1.4371 + struct sctp_chunk_desc desc; 1.4372 + struct sctp_chunkhdr *ch; 1.4373 + 1.4374 + chlen = ntohs(cp->ch.chunk_length); 1.4375 + chlen -= sizeof(struct sctp_pktdrop_chunk); 1.4376 + /* XXX possible chlen underflow */ 1.4377 + if (chlen == 0) { 1.4378 + ch = NULL; 1.4379 + if (cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) 1.4380 + SCTP_STAT_INCR(sctps_pdrpbwrpt); 1.4381 + } else { 1.4382 + ch = (struct sctp_chunkhdr *)(cp->data + sizeof(struct sctphdr)); 1.4383 + chlen -= sizeof(struct sctphdr); 1.4384 + /* XXX possible chlen underflow */ 1.4385 + memset(&desc, 0, sizeof(desc)); 1.4386 + } 1.4387 + trunc_len = (uint16_t) ntohs(cp->trunc_len); 1.4388 + if (trunc_len > limit) { 1.4389 + trunc_len = limit; 1.4390 + } 1.4391 + 1.4392 + /* now the chunks themselves */ 1.4393 + while ((ch != NULL) && (chlen >= sizeof(struct sctp_chunkhdr))) { 1.4394 + desc.chunk_type = ch->chunk_type; 1.4395 + /* get amount we need to move */ 1.4396 + at = ntohs(ch->chunk_length); 1.4397 + if (at < sizeof(struct sctp_chunkhdr)) { 1.4398 + /* corrupt chunk, maybe at the end? */ 1.4399 + SCTP_STAT_INCR(sctps_pdrpcrupt); 1.4400 + break; 1.4401 + } 1.4402 + if (trunc_len == 0) { 1.4403 + /* we are supposed to have all of it */ 1.4404 + if (at > chlen) { 1.4405 + /* corrupt skip it */ 1.4406 + SCTP_STAT_INCR(sctps_pdrpcrupt); 1.4407 + break; 1.4408 + } 1.4409 + } else { 1.4410 + /* is there enough of it left ? */ 1.4411 + if (desc.chunk_type == SCTP_DATA) { 1.4412 + if (chlen < (sizeof(struct sctp_data_chunk) + 1.4413 + sizeof(desc.data_bytes))) { 1.4414 + break; 1.4415 + } 1.4416 + } else { 1.4417 + if (chlen < sizeof(struct sctp_chunkhdr)) { 1.4418 + break; 1.4419 + } 1.4420 + } 1.4421 + } 1.4422 + if (desc.chunk_type == SCTP_DATA) { 1.4423 + /* can we get out the tsn? */ 1.4424 + if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 1.4425 + SCTP_STAT_INCR(sctps_pdrpmbda); 1.4426 + 1.4427 + if (chlen >= (sizeof(struct sctp_data_chunk) + sizeof(uint32_t))) { 1.4428 + /* yep */ 1.4429 + struct sctp_data_chunk *dcp; 1.4430 + uint8_t *ddp; 1.4431 + unsigned int iii; 1.4432 + 1.4433 + dcp = (struct sctp_data_chunk *)ch; 1.4434 + ddp = (uint8_t *) (dcp + 1); 1.4435 + for (iii = 0; iii < sizeof(desc.data_bytes); iii++) { 1.4436 + desc.data_bytes[iii] = ddp[iii]; 1.4437 + } 1.4438 + desc.tsn_ifany = dcp->dp.tsn; 1.4439 + } else { 1.4440 + /* nope we are done. */ 1.4441 + SCTP_STAT_INCR(sctps_pdrpnedat); 1.4442 + break; 1.4443 + } 1.4444 + } else { 1.4445 + if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)) 1.4446 + SCTP_STAT_INCR(sctps_pdrpmbct); 1.4447 + } 1.4448 + 1.4449 + if (process_chunk_drop(stcb, &desc, net, cp->ch.chunk_flags)) { 1.4450 + SCTP_STAT_INCR(sctps_pdrppdbrk); 1.4451 + break; 1.4452 + } 1.4453 + if (SCTP_SIZE32(at) > chlen) { 1.4454 + break; 1.4455 + } 1.4456 + chlen -= SCTP_SIZE32(at); 1.4457 + if (chlen < sizeof(struct sctp_chunkhdr)) { 1.4458 + /* done, none left */ 1.4459 + break; 1.4460 + } 1.4461 + ch = (struct sctp_chunkhdr *)((caddr_t)ch + SCTP_SIZE32(at)); 1.4462 + } 1.4463 + /* Now update any rwnd --- possibly */ 1.4464 + if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) == 0) { 1.4465 + /* From a peer, we get a rwnd report */ 1.4466 + uint32_t a_rwnd; 1.4467 + 1.4468 + SCTP_STAT_INCR(sctps_pdrpfehos); 1.4469 + 1.4470 + bottle_bw = ntohl(cp->bottle_bw); 1.4471 + on_queue = ntohl(cp->current_onq); 1.4472 + if (bottle_bw && on_queue) { 1.4473 + /* a rwnd report is in here */ 1.4474 + if (bottle_bw > on_queue) 1.4475 + a_rwnd = bottle_bw - on_queue; 1.4476 + else 1.4477 + a_rwnd = 0; 1.4478 + 1.4479 + if (a_rwnd == 0) 1.4480 + stcb->asoc.peers_rwnd = 0; 1.4481 + else { 1.4482 + if (a_rwnd > stcb->asoc.total_flight) { 1.4483 + stcb->asoc.peers_rwnd = 1.4484 + a_rwnd - stcb->asoc.total_flight; 1.4485 + } else { 1.4486 + stcb->asoc.peers_rwnd = 0; 1.4487 + } 1.4488 + if (stcb->asoc.peers_rwnd < 1.4489 + stcb->sctp_ep->sctp_ep.sctp_sws_sender) { 1.4490 + /* SWS sender side engages */ 1.4491 + stcb->asoc.peers_rwnd = 0; 1.4492 + } 1.4493 + } 1.4494 + } 1.4495 + } else { 1.4496 + SCTP_STAT_INCR(sctps_pdrpfmbox); 1.4497 + } 1.4498 + 1.4499 + /* now middle boxes in sat networks get a cwnd bump */ 1.4500 + if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) && 1.4501 + (stcb->asoc.sat_t3_loss_recovery == 0) && 1.4502 + (stcb->asoc.sat_network)) { 1.4503 + /* 1.4504 + * This is debateable but for sat networks it makes sense 1.4505 + * Note if a T3 timer has went off, we will prohibit any 1.4506 + * changes to cwnd until we exit the t3 loss recovery. 1.4507 + */ 1.4508 + stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped(stcb, 1.4509 + net, cp, &bottle_bw, &on_queue); 1.4510 + } 1.4511 +} 1.4512 + 1.4513 +/* 1.4514 + * handles all control chunks in a packet inputs: - m: mbuf chain, assumed to 1.4515 + * still contain IP/SCTP header - stcb: is the tcb found for this packet - 1.4516 + * offset: offset into the mbuf chain to first chunkhdr - length: is the 1.4517 + * length of the complete packet outputs: - length: modified to remaining 1.4518 + * length after control processing - netp: modified to new sctp_nets after 1.4519 + * cookie-echo processing - return NULL to discard the packet (ie. no asoc, 1.4520 + * bad packet,...) otherwise return the tcb for this packet 1.4521 + */ 1.4522 +#if !defined(__Panda__) 1.4523 +#ifdef __GNUC__ 1.4524 +__attribute__ ((noinline)) 1.4525 +#endif 1.4526 +#endif 1.4527 +static struct sctp_tcb * 1.4528 +sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length, 1.4529 + struct sockaddr *src, struct sockaddr *dst, 1.4530 + struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp, 1.4531 + struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen, 1.4532 +#if defined(__FreeBSD__) 1.4533 + uint8_t use_mflowid, uint32_t mflowid, 1.4534 +#endif 1.4535 + uint32_t vrf_id, uint16_t port) 1.4536 +{ 1.4537 + struct sctp_association *asoc; 1.4538 + uint32_t vtag_in; 1.4539 + int num_chunks = 0; /* number of control chunks processed */ 1.4540 + uint32_t chk_length; 1.4541 + int ret; 1.4542 + int abort_no_unlock = 0; 1.4543 + int ecne_seen = 0; 1.4544 + /* 1.4545 + * How big should this be, and should it be alloc'd? Lets try the 1.4546 + * d-mtu-ceiling for now (2k) and that should hopefully work ... 1.4547 + * until we get into jumbo grams and such.. 1.4548 + */ 1.4549 + uint8_t chunk_buf[SCTP_CHUNK_BUFFER_SIZE]; 1.4550 + struct sctp_tcb *locked_tcb = stcb; 1.4551 + int got_auth = 0; 1.4552 + uint32_t auth_offset = 0, auth_len = 0; 1.4553 + int auth_skipped = 0; 1.4554 + int asconf_cnt = 0; 1.4555 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4556 + struct socket *so; 1.4557 +#endif 1.4558 + 1.4559 + SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n", 1.4560 + iphlen, *offset, length, (void *)stcb); 1.4561 + 1.4562 + /* validate chunk header length... */ 1.4563 + if (ntohs(ch->chunk_length) < sizeof(*ch)) { 1.4564 + SCTPDBG(SCTP_DEBUG_INPUT1, "Invalid header length %d\n", 1.4565 + ntohs(ch->chunk_length)); 1.4566 + if (locked_tcb) { 1.4567 + SCTP_TCB_UNLOCK(locked_tcb); 1.4568 + } 1.4569 + return (NULL); 1.4570 + } 1.4571 + /* 1.4572 + * validate the verification tag 1.4573 + */ 1.4574 + vtag_in = ntohl(sh->v_tag); 1.4575 + 1.4576 + if (locked_tcb) { 1.4577 + SCTP_TCB_LOCK_ASSERT(locked_tcb); 1.4578 + } 1.4579 + if (ch->chunk_type == SCTP_INITIATION) { 1.4580 + SCTPDBG(SCTP_DEBUG_INPUT1, "Its an INIT of len:%d vtag:%x\n", 1.4581 + ntohs(ch->chunk_length), vtag_in); 1.4582 + if (vtag_in != 0) { 1.4583 + /* protocol error- silently discard... */ 1.4584 + SCTP_STAT_INCR(sctps_badvtag); 1.4585 + if (locked_tcb) { 1.4586 + SCTP_TCB_UNLOCK(locked_tcb); 1.4587 + } 1.4588 + return (NULL); 1.4589 + } 1.4590 + } else if (ch->chunk_type != SCTP_COOKIE_ECHO) { 1.4591 + /* 1.4592 + * If there is no stcb, skip the AUTH chunk and process 1.4593 + * later after a stcb is found (to validate the lookup was 1.4594 + * valid. 1.4595 + */ 1.4596 + if ((ch->chunk_type == SCTP_AUTHENTICATION) && 1.4597 + (stcb == NULL) && 1.4598 + !SCTP_BASE_SYSCTL(sctp_auth_disable)) { 1.4599 + /* save this chunk for later processing */ 1.4600 + auth_skipped = 1; 1.4601 + auth_offset = *offset; 1.4602 + auth_len = ntohs(ch->chunk_length); 1.4603 + 1.4604 + /* (temporarily) move past this chunk */ 1.4605 + *offset += SCTP_SIZE32(auth_len); 1.4606 + if (*offset >= length) { 1.4607 + /* no more data left in the mbuf chain */ 1.4608 + *offset = length; 1.4609 + if (locked_tcb) { 1.4610 + SCTP_TCB_UNLOCK(locked_tcb); 1.4611 + } 1.4612 + return (NULL); 1.4613 + } 1.4614 + ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 1.4615 + sizeof(struct sctp_chunkhdr), chunk_buf); 1.4616 + } 1.4617 + if (ch == NULL) { 1.4618 + /* Help */ 1.4619 + *offset = length; 1.4620 + if (locked_tcb) { 1.4621 + SCTP_TCB_UNLOCK(locked_tcb); 1.4622 + } 1.4623 + return (NULL); 1.4624 + } 1.4625 + if (ch->chunk_type == SCTP_COOKIE_ECHO) { 1.4626 + goto process_control_chunks; 1.4627 + } 1.4628 + /* 1.4629 + * first check if it's an ASCONF with an unknown src addr we 1.4630 + * need to look inside to find the association 1.4631 + */ 1.4632 + if (ch->chunk_type == SCTP_ASCONF && stcb == NULL) { 1.4633 + struct sctp_chunkhdr *asconf_ch = ch; 1.4634 + uint32_t asconf_offset = 0, asconf_len = 0; 1.4635 + 1.4636 + /* inp's refcount may be reduced */ 1.4637 + SCTP_INP_INCR_REF(inp); 1.4638 + 1.4639 + asconf_offset = *offset; 1.4640 + do { 1.4641 + asconf_len = ntohs(asconf_ch->chunk_length); 1.4642 + if (asconf_len < sizeof(struct sctp_asconf_paramhdr)) 1.4643 + break; 1.4644 + stcb = sctp_findassociation_ep_asconf(m, 1.4645 + *offset, 1.4646 + dst, 1.4647 + sh, &inp, netp, vrf_id); 1.4648 + if (stcb != NULL) 1.4649 + break; 1.4650 + asconf_offset += SCTP_SIZE32(asconf_len); 1.4651 + asconf_ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, asconf_offset, 1.4652 + sizeof(struct sctp_chunkhdr), chunk_buf); 1.4653 + } while (asconf_ch != NULL && asconf_ch->chunk_type == SCTP_ASCONF); 1.4654 + if (stcb == NULL) { 1.4655 + /* 1.4656 + * reduce inp's refcount if not reduced in 1.4657 + * sctp_findassociation_ep_asconf(). 1.4658 + */ 1.4659 + SCTP_INP_DECR_REF(inp); 1.4660 + } else { 1.4661 + locked_tcb = stcb; 1.4662 + } 1.4663 + 1.4664 + /* now go back and verify any auth chunk to be sure */ 1.4665 + if (auth_skipped && (stcb != NULL)) { 1.4666 + struct sctp_auth_chunk *auth; 1.4667 + 1.4668 + auth = (struct sctp_auth_chunk *) 1.4669 + sctp_m_getptr(m, auth_offset, 1.4670 + auth_len, chunk_buf); 1.4671 + got_auth = 1; 1.4672 + auth_skipped = 0; 1.4673 + if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, 1.4674 + auth_offset)) { 1.4675 + /* auth HMAC failed so dump it */ 1.4676 + *offset = length; 1.4677 + if (locked_tcb) { 1.4678 + SCTP_TCB_UNLOCK(locked_tcb); 1.4679 + } 1.4680 + return (NULL); 1.4681 + } else { 1.4682 + /* remaining chunks are HMAC checked */ 1.4683 + stcb->asoc.authenticated = 1; 1.4684 + } 1.4685 + } 1.4686 + } 1.4687 + if (stcb == NULL) { 1.4688 + /* no association, so it's out of the blue... */ 1.4689 + sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, 1.4690 +#if defined(__FreeBSD__) 1.4691 + use_mflowid, mflowid, 1.4692 +#endif 1.4693 + vrf_id, port); 1.4694 + *offset = length; 1.4695 + if (locked_tcb) { 1.4696 + SCTP_TCB_UNLOCK(locked_tcb); 1.4697 + } 1.4698 + return (NULL); 1.4699 + } 1.4700 + asoc = &stcb->asoc; 1.4701 + /* ABORT and SHUTDOWN can use either v_tag... */ 1.4702 + if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) || 1.4703 + (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) || 1.4704 + (ch->chunk_type == SCTP_PACKET_DROPPED)) { 1.4705 + /* Take the T-bit always into account. */ 1.4706 + if ((((ch->chunk_flags & SCTP_HAD_NO_TCB) == 0) && 1.4707 + (vtag_in == asoc->my_vtag)) || 1.4708 + (((ch->chunk_flags & SCTP_HAD_NO_TCB) == SCTP_HAD_NO_TCB) && 1.4709 + (vtag_in == asoc->peer_vtag))) { 1.4710 + /* this is valid */ 1.4711 + } else { 1.4712 + /* drop this packet... */ 1.4713 + SCTP_STAT_INCR(sctps_badvtag); 1.4714 + if (locked_tcb) { 1.4715 + SCTP_TCB_UNLOCK(locked_tcb); 1.4716 + } 1.4717 + return (NULL); 1.4718 + } 1.4719 + } else if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 1.4720 + if (vtag_in != asoc->my_vtag) { 1.4721 + /* 1.4722 + * this could be a stale SHUTDOWN-ACK or the 1.4723 + * peer never got the SHUTDOWN-COMPLETE and 1.4724 + * is still hung; we have started a new asoc 1.4725 + * but it won't complete until the shutdown 1.4726 + * is completed 1.4727 + */ 1.4728 + if (locked_tcb) { 1.4729 + SCTP_TCB_UNLOCK(locked_tcb); 1.4730 + } 1.4731 + sctp_handle_ootb(m, iphlen, *offset, src, dst, 1.4732 + sh, inp, 1.4733 +#if defined(__FreeBSD__) 1.4734 + use_mflowid, mflowid, 1.4735 +#endif 1.4736 + vrf_id, port); 1.4737 + return (NULL); 1.4738 + } 1.4739 + } else { 1.4740 + /* for all other chunks, vtag must match */ 1.4741 + if (vtag_in != asoc->my_vtag) { 1.4742 + /* invalid vtag... */ 1.4743 + SCTPDBG(SCTP_DEBUG_INPUT3, 1.4744 + "invalid vtag: %xh, expect %xh\n", 1.4745 + vtag_in, asoc->my_vtag); 1.4746 + SCTP_STAT_INCR(sctps_badvtag); 1.4747 + if (locked_tcb) { 1.4748 + SCTP_TCB_UNLOCK(locked_tcb); 1.4749 + } 1.4750 + *offset = length; 1.4751 + return (NULL); 1.4752 + } 1.4753 + } 1.4754 + } /* end if !SCTP_COOKIE_ECHO */ 1.4755 + /* 1.4756 + * process all control chunks... 1.4757 + */ 1.4758 + if (((ch->chunk_type == SCTP_SELECTIVE_ACK) || 1.4759 + (ch->chunk_type == SCTP_NR_SELECTIVE_ACK) || 1.4760 + (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) && 1.4761 + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { 1.4762 + /* implied cookie-ack.. we must have lost the ack */ 1.4763 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.4764 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.4765 + stcb->asoc.overall_error_count, 1.4766 + 0, 1.4767 + SCTP_FROM_SCTP_INPUT, 1.4768 + __LINE__); 1.4769 + } 1.4770 + stcb->asoc.overall_error_count = 0; 1.4771 + sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, 1.4772 + *netp); 1.4773 + } 1.4774 + 1.4775 + process_control_chunks: 1.4776 + while (IS_SCTP_CONTROL(ch)) { 1.4777 + /* validate chunk length */ 1.4778 + chk_length = ntohs(ch->chunk_length); 1.4779 + SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_process_control: processing a chunk type=%u, len=%u\n", 1.4780 + ch->chunk_type, chk_length); 1.4781 + SCTP_LTRACE_CHK(inp, stcb, ch->chunk_type, chk_length); 1.4782 + if (chk_length < sizeof(*ch) || 1.4783 + (*offset + (int)chk_length) > length) { 1.4784 + *offset = length; 1.4785 + if (locked_tcb) { 1.4786 + SCTP_TCB_UNLOCK(locked_tcb); 1.4787 + } 1.4788 + return (NULL); 1.4789 + } 1.4790 + SCTP_STAT_INCR_COUNTER64(sctps_incontrolchunks); 1.4791 + /* 1.4792 + * INIT-ACK only gets the init ack "header" portion only 1.4793 + * because we don't have to process the peer's COOKIE. All 1.4794 + * others get a complete chunk. 1.4795 + */ 1.4796 + if ((ch->chunk_type == SCTP_INITIATION_ACK) || 1.4797 + (ch->chunk_type == SCTP_INITIATION)) { 1.4798 + /* get an init-ack chunk */ 1.4799 + ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 1.4800 + sizeof(struct sctp_init_ack_chunk), chunk_buf); 1.4801 + if (ch == NULL) { 1.4802 + *offset = length; 1.4803 + if (locked_tcb) { 1.4804 + SCTP_TCB_UNLOCK(locked_tcb); 1.4805 + } 1.4806 + return (NULL); 1.4807 + } 1.4808 + } else { 1.4809 + /* For cookies and all other chunks. */ 1.4810 + if (chk_length > sizeof(chunk_buf)) { 1.4811 + /* 1.4812 + * use just the size of the chunk buffer 1.4813 + * so the front part of our chunks fit in 1.4814 + * contiguous space up to the chunk buffer 1.4815 + * size (508 bytes). 1.4816 + * For chunks that need to get more than that 1.4817 + * they must use the sctp_m_getptr() function 1.4818 + * or other means (e.g. know how to parse mbuf 1.4819 + * chains). Cookies do this already. 1.4820 + */ 1.4821 + ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 1.4822 + (sizeof(chunk_buf) - 4), 1.4823 + chunk_buf); 1.4824 + if (ch == NULL) { 1.4825 + *offset = length; 1.4826 + if (locked_tcb) { 1.4827 + SCTP_TCB_UNLOCK(locked_tcb); 1.4828 + } 1.4829 + return (NULL); 1.4830 + } 1.4831 + } else { 1.4832 + /* We can fit it all */ 1.4833 + ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 1.4834 + chk_length, chunk_buf); 1.4835 + if (ch == NULL) { 1.4836 + SCTP_PRINTF("sctp_process_control: Can't get the all data....\n"); 1.4837 + *offset = length; 1.4838 + if (locked_tcb) { 1.4839 + SCTP_TCB_UNLOCK(locked_tcb); 1.4840 + } 1.4841 + return (NULL); 1.4842 + } 1.4843 + } 1.4844 + } 1.4845 + num_chunks++; 1.4846 + /* Save off the last place we got a control from */ 1.4847 + if (stcb != NULL) { 1.4848 + if (((netp != NULL) && (*netp != NULL)) || (ch->chunk_type == SCTP_ASCONF)) { 1.4849 + /* 1.4850 + * allow last_control to be NULL if 1.4851 + * ASCONF... ASCONF processing will find the 1.4852 + * right net later 1.4853 + */ 1.4854 + if ((netp != NULL) && (*netp != NULL)) 1.4855 + stcb->asoc.last_control_chunk_from = *netp; 1.4856 + } 1.4857 + } 1.4858 +#ifdef SCTP_AUDITING_ENABLED 1.4859 + sctp_audit_log(0xB0, ch->chunk_type); 1.4860 +#endif 1.4861 + 1.4862 + /* check to see if this chunk required auth, but isn't */ 1.4863 + if ((stcb != NULL) && 1.4864 + !SCTP_BASE_SYSCTL(sctp_auth_disable) && 1.4865 + sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) && 1.4866 + !stcb->asoc.authenticated) { 1.4867 + /* "silently" ignore */ 1.4868 + SCTP_STAT_INCR(sctps_recvauthmissing); 1.4869 + goto next_chunk; 1.4870 + } 1.4871 + switch (ch->chunk_type) { 1.4872 + case SCTP_INITIATION: 1.4873 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT\n"); 1.4874 + /* The INIT chunk must be the only chunk. */ 1.4875 + if ((num_chunks > 1) || 1.4876 + (length - *offset > (int)SCTP_SIZE32(chk_length))) { 1.4877 + sctp_abort_association(inp, stcb, m, iphlen, 1.4878 + src, dst, sh, NULL, 1.4879 +#if defined(__FreeBSD__) 1.4880 + use_mflowid, mflowid, 1.4881 +#endif 1.4882 + vrf_id, port); 1.4883 + *offset = length; 1.4884 + return (NULL); 1.4885 + } 1.4886 + /* Honor our resource limit. */ 1.4887 + if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) { 1.4888 + struct mbuf *op_err; 1.4889 + 1.4890 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); 1.4891 + sctp_abort_association(inp, stcb, m, iphlen, 1.4892 + src, dst, sh, op_err, 1.4893 +#if defined(__FreeBSD__) 1.4894 + use_mflowid, mflowid, 1.4895 +#endif 1.4896 + vrf_id, port); 1.4897 + *offset = length; 1.4898 + return (NULL); 1.4899 + } 1.4900 + sctp_handle_init(m, iphlen, *offset, src, dst, sh, 1.4901 + (struct sctp_init_chunk *)ch, inp, 1.4902 + stcb, &abort_no_unlock, 1.4903 +#if defined(__FreeBSD__) 1.4904 + use_mflowid, mflowid, 1.4905 +#endif 1.4906 + vrf_id, port); 1.4907 + *offset = length; 1.4908 + if ((!abort_no_unlock) && (locked_tcb)) { 1.4909 + SCTP_TCB_UNLOCK(locked_tcb); 1.4910 + } 1.4911 + return (NULL); 1.4912 + break; 1.4913 + case SCTP_PAD_CHUNK: 1.4914 + break; 1.4915 + case SCTP_INITIATION_ACK: 1.4916 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n"); 1.4917 + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 1.4918 + /* We are not interested anymore */ 1.4919 + if ((stcb) && (stcb->asoc.total_output_queue_size)) { 1.4920 + ; 1.4921 + } else { 1.4922 + if (locked_tcb != stcb) { 1.4923 + /* Very unlikely */ 1.4924 + SCTP_TCB_UNLOCK(locked_tcb); 1.4925 + } 1.4926 + *offset = length; 1.4927 + if (stcb) { 1.4928 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4929 + so = SCTP_INP_SO(inp); 1.4930 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.4931 + SCTP_TCB_UNLOCK(stcb); 1.4932 + SCTP_SOCKET_LOCK(so, 1); 1.4933 + SCTP_TCB_LOCK(stcb); 1.4934 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.4935 +#endif 1.4936 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_27); 1.4937 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4938 + SCTP_SOCKET_UNLOCK(so, 1); 1.4939 +#endif 1.4940 + } 1.4941 + return (NULL); 1.4942 + } 1.4943 + } 1.4944 + /* The INIT-ACK chunk must be the only chunk. */ 1.4945 + if ((num_chunks > 1) || 1.4946 + (length - *offset > (int)SCTP_SIZE32(chk_length))) { 1.4947 + *offset = length; 1.4948 + if (locked_tcb) { 1.4949 + SCTP_TCB_UNLOCK(locked_tcb); 1.4950 + } 1.4951 + return (NULL); 1.4952 + } 1.4953 + if ((netp) && (*netp)) { 1.4954 + ret = sctp_handle_init_ack(m, iphlen, *offset, 1.4955 + src, dst, sh, 1.4956 + (struct sctp_init_ack_chunk *)ch, 1.4957 + stcb, *netp, 1.4958 + &abort_no_unlock, 1.4959 +#if defined(__FreeBSD__) 1.4960 + use_mflowid, mflowid, 1.4961 +#endif 1.4962 + vrf_id); 1.4963 + } else { 1.4964 + ret = -1; 1.4965 + } 1.4966 + *offset = length; 1.4967 + if (abort_no_unlock) { 1.4968 + return (NULL); 1.4969 + } 1.4970 + /* 1.4971 + * Special case, I must call the output routine to 1.4972 + * get the cookie echoed 1.4973 + */ 1.4974 + if ((stcb != NULL) && (ret == 0)) { 1.4975 + sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 1.4976 + } 1.4977 + if (locked_tcb) { 1.4978 + SCTP_TCB_UNLOCK(locked_tcb); 1.4979 + } 1.4980 + return (NULL); 1.4981 + break; 1.4982 + case SCTP_SELECTIVE_ACK: 1.4983 + { 1.4984 + struct sctp_sack_chunk *sack; 1.4985 + int abort_now = 0; 1.4986 + uint32_t a_rwnd, cum_ack; 1.4987 + uint16_t num_seg, num_dup; 1.4988 + uint8_t flags; 1.4989 + int offset_seg, offset_dup; 1.4990 + 1.4991 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n"); 1.4992 + SCTP_STAT_INCR(sctps_recvsacks); 1.4993 + if (stcb == NULL) { 1.4994 + SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing SACK chunk\n"); 1.4995 + break; 1.4996 + } 1.4997 + if (chk_length < sizeof(struct sctp_sack_chunk)) { 1.4998 + SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on SACK chunk, too small\n"); 1.4999 + break; 1.5000 + } 1.5001 + if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 1.5002 + /*- 1.5003 + * If we have sent a shutdown-ack, we will pay no 1.5004 + * attention to a sack sent in to us since 1.5005 + * we don't care anymore. 1.5006 + */ 1.5007 + break; 1.5008 + } 1.5009 + sack = (struct sctp_sack_chunk *)ch; 1.5010 + flags = ch->chunk_flags; 1.5011 + cum_ack = ntohl(sack->sack.cum_tsn_ack); 1.5012 + num_seg = ntohs(sack->sack.num_gap_ack_blks); 1.5013 + num_dup = ntohs(sack->sack.num_dup_tsns); 1.5014 + a_rwnd = (uint32_t) ntohl(sack->sack.a_rwnd); 1.5015 + if (sizeof(struct sctp_sack_chunk) + 1.5016 + num_seg * sizeof(struct sctp_gap_ack_block) + 1.5017 + num_dup * sizeof(uint32_t) != chk_length) { 1.5018 + SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of SACK chunk\n"); 1.5019 + break; 1.5020 + } 1.5021 + offset_seg = *offset + sizeof(struct sctp_sack_chunk); 1.5022 + offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 1.5023 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 1.5024 + cum_ack, num_seg, a_rwnd); 1.5025 + stcb->asoc.seen_a_sack_this_pkt = 1; 1.5026 + if ((stcb->asoc.pr_sctp_cnt == 0) && 1.5027 + (num_seg == 0) && 1.5028 + SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 1.5029 + (stcb->asoc.saw_sack_with_frags == 0) && 1.5030 + (stcb->asoc.saw_sack_with_nr_frags == 0) && 1.5031 + (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) 1.5032 + ) { 1.5033 + /* We have a SIMPLE sack having no prior segments and 1.5034 + * data on sent queue to be acked.. Use the faster 1.5035 + * path sack processing. We also allow window update 1.5036 + * sacks with no missing segments to go this way too. 1.5037 + */ 1.5038 + sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now, ecne_seen); 1.5039 + } else { 1.5040 + if (netp && *netp) 1.5041 + sctp_handle_sack(m, offset_seg, offset_dup, stcb, 1.5042 + num_seg, 0, num_dup, &abort_now, flags, 1.5043 + cum_ack, a_rwnd, ecne_seen); 1.5044 + } 1.5045 + if (abort_now) { 1.5046 + /* ABORT signal from sack processing */ 1.5047 + *offset = length; 1.5048 + return (NULL); 1.5049 + } 1.5050 + if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 1.5051 + TAILQ_EMPTY(&stcb->asoc.sent_queue) && 1.5052 + (stcb->asoc.stream_queue_cnt == 0)) { 1.5053 + sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1.5054 + } 1.5055 + } 1.5056 + break; 1.5057 + /* EY - nr_sack: If the received chunk is an nr_sack chunk */ 1.5058 + case SCTP_NR_SELECTIVE_ACK: 1.5059 + { 1.5060 + struct sctp_nr_sack_chunk *nr_sack; 1.5061 + int abort_now = 0; 1.5062 + uint32_t a_rwnd, cum_ack; 1.5063 + uint16_t num_seg, num_nr_seg, num_dup; 1.5064 + uint8_t flags; 1.5065 + int offset_seg, offset_dup; 1.5066 + 1.5067 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n"); 1.5068 + SCTP_STAT_INCR(sctps_recvsacks); 1.5069 + if (stcb == NULL) { 1.5070 + SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing NR-SACK chunk\n"); 1.5071 + break; 1.5072 + } 1.5073 + if ((stcb->asoc.sctp_nr_sack_on_off == 0) || 1.5074 + (stcb->asoc.peer_supports_nr_sack == 0)) { 1.5075 + goto unknown_chunk; 1.5076 + } 1.5077 + if (chk_length < sizeof(struct sctp_nr_sack_chunk)) { 1.5078 + SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on NR-SACK chunk, too small\n"); 1.5079 + break; 1.5080 + } 1.5081 + if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { 1.5082 + /*- 1.5083 + * If we have sent a shutdown-ack, we will pay no 1.5084 + * attention to a sack sent in to us since 1.5085 + * we don't care anymore. 1.5086 + */ 1.5087 + break; 1.5088 + } 1.5089 + nr_sack = (struct sctp_nr_sack_chunk *)ch; 1.5090 + flags = ch->chunk_flags; 1.5091 + cum_ack = ntohl(nr_sack->nr_sack.cum_tsn_ack); 1.5092 + num_seg = ntohs(nr_sack->nr_sack.num_gap_ack_blks); 1.5093 + num_nr_seg = ntohs(nr_sack->nr_sack.num_nr_gap_ack_blks); 1.5094 + num_dup = ntohs(nr_sack->nr_sack.num_dup_tsns); 1.5095 + a_rwnd = (uint32_t) ntohl(nr_sack->nr_sack.a_rwnd); 1.5096 + if (sizeof(struct sctp_nr_sack_chunk) + 1.5097 + (num_seg + num_nr_seg) * sizeof(struct sctp_gap_ack_block) + 1.5098 + num_dup * sizeof(uint32_t) != chk_length) { 1.5099 + SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of NR_SACK chunk\n"); 1.5100 + break; 1.5101 + } 1.5102 + offset_seg = *offset + sizeof(struct sctp_nr_sack_chunk); 1.5103 + offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block); 1.5104 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n", 1.5105 + cum_ack, num_seg, a_rwnd); 1.5106 + stcb->asoc.seen_a_sack_this_pkt = 1; 1.5107 + if ((stcb->asoc.pr_sctp_cnt == 0) && 1.5108 + (num_seg == 0) && (num_nr_seg == 0) && 1.5109 + SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) && 1.5110 + (stcb->asoc.saw_sack_with_frags == 0) && 1.5111 + (stcb->asoc.saw_sack_with_nr_frags == 0) && 1.5112 + (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) { 1.5113 + /* 1.5114 + * We have a SIMPLE sack having no 1.5115 + * prior segments and data on sent 1.5116 + * queue to be acked. Use the 1.5117 + * faster path sack processing. We 1.5118 + * also allow window update sacks 1.5119 + * with no missing segments to go 1.5120 + * this way too. 1.5121 + */ 1.5122 + sctp_express_handle_sack(stcb, cum_ack, a_rwnd, 1.5123 + &abort_now, ecne_seen); 1.5124 + } else { 1.5125 + if (netp && *netp) 1.5126 + sctp_handle_sack(m, offset_seg, offset_dup, stcb, 1.5127 + num_seg, num_nr_seg, num_dup, &abort_now, flags, 1.5128 + cum_ack, a_rwnd, ecne_seen); 1.5129 + } 1.5130 + if (abort_now) { 1.5131 + /* ABORT signal from sack processing */ 1.5132 + *offset = length; 1.5133 + return (NULL); 1.5134 + } 1.5135 + if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 1.5136 + TAILQ_EMPTY(&stcb->asoc.sent_queue) && 1.5137 + (stcb->asoc.stream_queue_cnt == 0)) { 1.5138 + sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED); 1.5139 + } 1.5140 + } 1.5141 + break; 1.5142 + 1.5143 + case SCTP_HEARTBEAT_REQUEST: 1.5144 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT\n"); 1.5145 + if ((stcb) && netp && *netp) { 1.5146 + SCTP_STAT_INCR(sctps_recvheartbeat); 1.5147 + sctp_send_heartbeat_ack(stcb, m, *offset, 1.5148 + chk_length, *netp); 1.5149 + 1.5150 + /* He's alive so give him credit */ 1.5151 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.5152 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.5153 + stcb->asoc.overall_error_count, 1.5154 + 0, 1.5155 + SCTP_FROM_SCTP_INPUT, 1.5156 + __LINE__); 1.5157 + } 1.5158 + stcb->asoc.overall_error_count = 0; 1.5159 + } 1.5160 + break; 1.5161 + case SCTP_HEARTBEAT_ACK: 1.5162 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT-ACK\n"); 1.5163 + if ((stcb == NULL) || (chk_length != sizeof(struct sctp_heartbeat_chunk))) { 1.5164 + /* Its not ours */ 1.5165 + *offset = length; 1.5166 + if (locked_tcb) { 1.5167 + SCTP_TCB_UNLOCK(locked_tcb); 1.5168 + } 1.5169 + return (NULL); 1.5170 + } 1.5171 + /* He's alive so give him credit */ 1.5172 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.5173 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.5174 + stcb->asoc.overall_error_count, 1.5175 + 0, 1.5176 + SCTP_FROM_SCTP_INPUT, 1.5177 + __LINE__); 1.5178 + } 1.5179 + stcb->asoc.overall_error_count = 0; 1.5180 + SCTP_STAT_INCR(sctps_recvheartbeatack); 1.5181 + if (netp && *netp) 1.5182 + sctp_handle_heartbeat_ack((struct sctp_heartbeat_chunk *)ch, 1.5183 + stcb, *netp); 1.5184 + break; 1.5185 + case SCTP_ABORT_ASSOCIATION: 1.5186 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT, stcb %p\n", 1.5187 + (void *)stcb); 1.5188 + if ((stcb) && netp && *netp) 1.5189 + sctp_handle_abort((struct sctp_abort_chunk *)ch, 1.5190 + stcb, *netp); 1.5191 + *offset = length; 1.5192 + return (NULL); 1.5193 + break; 1.5194 + case SCTP_SHUTDOWN: 1.5195 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN, stcb %p\n", 1.5196 + (void *)stcb); 1.5197 + if ((stcb == NULL) || (chk_length != sizeof(struct sctp_shutdown_chunk))) { 1.5198 + *offset = length; 1.5199 + if (locked_tcb) { 1.5200 + SCTP_TCB_UNLOCK(locked_tcb); 1.5201 + } 1.5202 + return (NULL); 1.5203 + } 1.5204 + if (netp && *netp) { 1.5205 + int abort_flag = 0; 1.5206 + 1.5207 + sctp_handle_shutdown((struct sctp_shutdown_chunk *)ch, 1.5208 + stcb, *netp, &abort_flag); 1.5209 + if (abort_flag) { 1.5210 + *offset = length; 1.5211 + return (NULL); 1.5212 + } 1.5213 + } 1.5214 + break; 1.5215 + case SCTP_SHUTDOWN_ACK: 1.5216 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", (void *)stcb); 1.5217 + if ((stcb) && (netp) && (*netp)) 1.5218 + sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp); 1.5219 + *offset = length; 1.5220 + return (NULL); 1.5221 + break; 1.5222 + 1.5223 + case SCTP_OPERATION_ERROR: 1.5224 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_OP-ERR\n"); 1.5225 + if ((stcb) && netp && *netp && sctp_handle_error(ch, stcb, *netp) < 0) { 1.5226 + *offset = length; 1.5227 + return (NULL); 1.5228 + } 1.5229 + break; 1.5230 + case SCTP_COOKIE_ECHO: 1.5231 + SCTPDBG(SCTP_DEBUG_INPUT3, 1.5232 + "SCTP_COOKIE-ECHO, stcb %p\n", (void *)stcb); 1.5233 + if ((stcb) && (stcb->asoc.total_output_queue_size)) { 1.5234 + ; 1.5235 + } else { 1.5236 + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 1.5237 + /* We are not interested anymore */ 1.5238 + abend: 1.5239 + if (stcb) { 1.5240 + SCTP_TCB_UNLOCK(stcb); 1.5241 + } 1.5242 + *offset = length; 1.5243 + return (NULL); 1.5244 + } 1.5245 + } 1.5246 + /* 1.5247 + * First are we accepting? We do this again here 1.5248 + * since it is possible that a previous endpoint WAS 1.5249 + * listening responded to a INIT-ACK and then 1.5250 + * closed. We opened and bound.. and are now no 1.5251 + * longer listening. 1.5252 + */ 1.5253 + 1.5254 + if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) { 1.5255 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 1.5256 + (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) { 1.5257 + struct mbuf *op_err; 1.5258 + 1.5259 + op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); 1.5260 + sctp_abort_association(inp, stcb, m, iphlen, 1.5261 + src, dst, sh, op_err, 1.5262 +#if defined(__FreeBSD__) 1.5263 + use_mflowid, mflowid, 1.5264 +#endif 1.5265 + vrf_id, port); 1.5266 + } 1.5267 + *offset = length; 1.5268 + return (NULL); 1.5269 + } else { 1.5270 + struct mbuf *ret_buf; 1.5271 + struct sctp_inpcb *linp; 1.5272 + if (stcb) { 1.5273 + linp = NULL; 1.5274 + } else { 1.5275 + linp = inp; 1.5276 + } 1.5277 + 1.5278 + if (linp) { 1.5279 + SCTP_ASOC_CREATE_LOCK(linp); 1.5280 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 1.5281 + (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 1.5282 + SCTP_ASOC_CREATE_UNLOCK(linp); 1.5283 + goto abend; 1.5284 + } 1.5285 + } 1.5286 + 1.5287 + if (netp) { 1.5288 + ret_buf = 1.5289 + sctp_handle_cookie_echo(m, iphlen, 1.5290 + *offset, 1.5291 + src, dst, 1.5292 + sh, 1.5293 + (struct sctp_cookie_echo_chunk *)ch, 1.5294 + &inp, &stcb, netp, 1.5295 + auth_skipped, 1.5296 + auth_offset, 1.5297 + auth_len, 1.5298 + &locked_tcb, 1.5299 +#if defined(__FreeBSD__) 1.5300 + use_mflowid, 1.5301 + mflowid, 1.5302 +#endif 1.5303 + vrf_id, 1.5304 + port); 1.5305 + } else { 1.5306 + ret_buf = NULL; 1.5307 + } 1.5308 + if (linp) { 1.5309 + SCTP_ASOC_CREATE_UNLOCK(linp); 1.5310 + } 1.5311 + if (ret_buf == NULL) { 1.5312 + if (locked_tcb) { 1.5313 + SCTP_TCB_UNLOCK(locked_tcb); 1.5314 + } 1.5315 + SCTPDBG(SCTP_DEBUG_INPUT3, 1.5316 + "GAK, null buffer\n"); 1.5317 + *offset = length; 1.5318 + return (NULL); 1.5319 + } 1.5320 + /* if AUTH skipped, see if it verified... */ 1.5321 + if (auth_skipped) { 1.5322 + got_auth = 1; 1.5323 + auth_skipped = 0; 1.5324 + } 1.5325 + if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) { 1.5326 + /* 1.5327 + * Restart the timer if we have 1.5328 + * pending data 1.5329 + */ 1.5330 + struct sctp_tmit_chunk *chk; 1.5331 + 1.5332 + chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 1.5333 + sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo); 1.5334 + } 1.5335 + } 1.5336 + break; 1.5337 + case SCTP_COOKIE_ACK: 1.5338 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", (void *)stcb); 1.5339 + if ((stcb == NULL) || chk_length != sizeof(struct sctp_cookie_ack_chunk)) { 1.5340 + if (locked_tcb) { 1.5341 + SCTP_TCB_UNLOCK(locked_tcb); 1.5342 + } 1.5343 + return (NULL); 1.5344 + } 1.5345 + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 1.5346 + /* We are not interested anymore */ 1.5347 + if ((stcb) && (stcb->asoc.total_output_queue_size)) { 1.5348 + ; 1.5349 + } else if (stcb) { 1.5350 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.5351 + so = SCTP_INP_SO(inp); 1.5352 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.5353 + SCTP_TCB_UNLOCK(stcb); 1.5354 + SCTP_SOCKET_LOCK(so, 1); 1.5355 + SCTP_TCB_LOCK(stcb); 1.5356 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.5357 +#endif 1.5358 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_27); 1.5359 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.5360 + SCTP_SOCKET_UNLOCK(so, 1); 1.5361 +#endif 1.5362 + *offset = length; 1.5363 + return (NULL); 1.5364 + } 1.5365 + } 1.5366 + /* He's alive so give him credit */ 1.5367 + if ((stcb) && netp && *netp) { 1.5368 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.5369 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.5370 + stcb->asoc.overall_error_count, 1.5371 + 0, 1.5372 + SCTP_FROM_SCTP_INPUT, 1.5373 + __LINE__); 1.5374 + } 1.5375 + stcb->asoc.overall_error_count = 0; 1.5376 + sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch,stcb, *netp); 1.5377 + } 1.5378 + break; 1.5379 + case SCTP_ECN_ECHO: 1.5380 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-ECHO\n"); 1.5381 + /* He's alive so give him credit */ 1.5382 + if ((stcb == NULL) || (chk_length != sizeof(struct sctp_ecne_chunk))) { 1.5383 + /* Its not ours */ 1.5384 + if (locked_tcb) { 1.5385 + SCTP_TCB_UNLOCK(locked_tcb); 1.5386 + } 1.5387 + *offset = length; 1.5388 + return (NULL); 1.5389 + } 1.5390 + if (stcb) { 1.5391 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.5392 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.5393 + stcb->asoc.overall_error_count, 1.5394 + 0, 1.5395 + SCTP_FROM_SCTP_INPUT, 1.5396 + __LINE__); 1.5397 + } 1.5398 + stcb->asoc.overall_error_count = 0; 1.5399 + sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch, 1.5400 + stcb); 1.5401 + ecne_seen = 1; 1.5402 + } 1.5403 + break; 1.5404 + case SCTP_ECN_CWR: 1.5405 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-CWR\n"); 1.5406 + /* He's alive so give him credit */ 1.5407 + if ((stcb == NULL) || (chk_length != sizeof(struct sctp_cwr_chunk))) { 1.5408 + /* Its not ours */ 1.5409 + if (locked_tcb) { 1.5410 + SCTP_TCB_UNLOCK(locked_tcb); 1.5411 + } 1.5412 + *offset = length; 1.5413 + return (NULL); 1.5414 + } 1.5415 + if (stcb) { 1.5416 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.5417 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.5418 + stcb->asoc.overall_error_count, 1.5419 + 0, 1.5420 + SCTP_FROM_SCTP_INPUT, 1.5421 + __LINE__); 1.5422 + } 1.5423 + stcb->asoc.overall_error_count = 0; 1.5424 + sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb, *netp); 1.5425 + } 1.5426 + break; 1.5427 + case SCTP_SHUTDOWN_COMPLETE: 1.5428 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", (void *)stcb); 1.5429 + /* must be first and only chunk */ 1.5430 + if ((num_chunks > 1) || 1.5431 + (length - *offset > (int)SCTP_SIZE32(chk_length))) { 1.5432 + *offset = length; 1.5433 + if (locked_tcb) { 1.5434 + SCTP_TCB_UNLOCK(locked_tcb); 1.5435 + } 1.5436 + return (NULL); 1.5437 + } 1.5438 + if ((stcb) && netp && *netp) { 1.5439 + sctp_handle_shutdown_complete((struct sctp_shutdown_complete_chunk *)ch, 1.5440 + stcb, *netp); 1.5441 + } 1.5442 + *offset = length; 1.5443 + return (NULL); 1.5444 + break; 1.5445 + case SCTP_ASCONF: 1.5446 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n"); 1.5447 + /* He's alive so give him credit */ 1.5448 + if (stcb) { 1.5449 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.5450 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.5451 + stcb->asoc.overall_error_count, 1.5452 + 0, 1.5453 + SCTP_FROM_SCTP_INPUT, 1.5454 + __LINE__); 1.5455 + } 1.5456 + stcb->asoc.overall_error_count = 0; 1.5457 + sctp_handle_asconf(m, *offset, src, 1.5458 + (struct sctp_asconf_chunk *)ch, stcb, asconf_cnt == 0); 1.5459 + asconf_cnt++; 1.5460 + } 1.5461 + break; 1.5462 + case SCTP_ASCONF_ACK: 1.5463 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF-ACK\n"); 1.5464 + if (chk_length < sizeof(struct sctp_asconf_ack_chunk)) { 1.5465 + /* Its not ours */ 1.5466 + if (locked_tcb) { 1.5467 + SCTP_TCB_UNLOCK(locked_tcb); 1.5468 + } 1.5469 + *offset = length; 1.5470 + return (NULL); 1.5471 + } 1.5472 + if ((stcb) && netp && *netp) { 1.5473 + /* He's alive so give him credit */ 1.5474 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.5475 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.5476 + stcb->asoc.overall_error_count, 1.5477 + 0, 1.5478 + SCTP_FROM_SCTP_INPUT, 1.5479 + __LINE__); 1.5480 + } 1.5481 + stcb->asoc.overall_error_count = 0; 1.5482 + sctp_handle_asconf_ack(m, *offset, 1.5483 + (struct sctp_asconf_ack_chunk *)ch, stcb, *netp, &abort_no_unlock); 1.5484 + if (abort_no_unlock) 1.5485 + return (NULL); 1.5486 + } 1.5487 + break; 1.5488 + case SCTP_FORWARD_CUM_TSN: 1.5489 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_FWD-TSN\n"); 1.5490 + if (chk_length < sizeof(struct sctp_forward_tsn_chunk)) { 1.5491 + /* Its not ours */ 1.5492 + if (locked_tcb) { 1.5493 + SCTP_TCB_UNLOCK(locked_tcb); 1.5494 + } 1.5495 + *offset = length; 1.5496 + return (NULL); 1.5497 + } 1.5498 + 1.5499 + /* He's alive so give him credit */ 1.5500 + if (stcb) { 1.5501 + int abort_flag = 0; 1.5502 + stcb->asoc.overall_error_count = 0; 1.5503 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.5504 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.5505 + stcb->asoc.overall_error_count, 1.5506 + 0, 1.5507 + SCTP_FROM_SCTP_INPUT, 1.5508 + __LINE__); 1.5509 + } 1.5510 + *fwd_tsn_seen = 1; 1.5511 + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 1.5512 + /* We are not interested anymore */ 1.5513 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.5514 + so = SCTP_INP_SO(inp); 1.5515 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.5516 + SCTP_TCB_UNLOCK(stcb); 1.5517 + SCTP_SOCKET_LOCK(so, 1); 1.5518 + SCTP_TCB_LOCK(stcb); 1.5519 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.5520 +#endif 1.5521 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT+SCTP_LOC_29); 1.5522 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.5523 + SCTP_SOCKET_UNLOCK(so, 1); 1.5524 +#endif 1.5525 + *offset = length; 1.5526 + return (NULL); 1.5527 + } 1.5528 + sctp_handle_forward_tsn(stcb, 1.5529 + (struct sctp_forward_tsn_chunk *)ch, &abort_flag, m, *offset); 1.5530 + if (abort_flag) { 1.5531 + *offset = length; 1.5532 + return (NULL); 1.5533 + } else { 1.5534 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.5535 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.5536 + stcb->asoc.overall_error_count, 1.5537 + 0, 1.5538 + SCTP_FROM_SCTP_INPUT, 1.5539 + __LINE__); 1.5540 + } 1.5541 + stcb->asoc.overall_error_count = 0; 1.5542 + } 1.5543 + 1.5544 + } 1.5545 + break; 1.5546 + case SCTP_STREAM_RESET: 1.5547 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_STREAM_RESET\n"); 1.5548 + if (((stcb == NULL) || (ch == NULL) || (chk_length < sizeof(struct sctp_stream_reset_tsn_req)))) { 1.5549 + /* Its not ours */ 1.5550 + if (locked_tcb) { 1.5551 + SCTP_TCB_UNLOCK(locked_tcb); 1.5552 + } 1.5553 + *offset = length; 1.5554 + return (NULL); 1.5555 + } 1.5556 + if (stcb->asoc.peer_supports_strreset == 0) { 1.5557 + /* 1.5558 + * hmm, peer should have announced this, but 1.5559 + * we will turn it on since he is sending us 1.5560 + * a stream reset. 1.5561 + */ 1.5562 + stcb->asoc.peer_supports_strreset = 1; 1.5563 + } 1.5564 + if (sctp_handle_stream_reset(stcb, m, *offset, ch)) { 1.5565 + /* stop processing */ 1.5566 + *offset = length; 1.5567 + return (NULL); 1.5568 + } 1.5569 + break; 1.5570 + case SCTP_PACKET_DROPPED: 1.5571 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_PACKET_DROPPED\n"); 1.5572 + /* re-get it all please */ 1.5573 + if (chk_length < sizeof(struct sctp_pktdrop_chunk)) { 1.5574 + /* Its not ours */ 1.5575 + if (locked_tcb) { 1.5576 + SCTP_TCB_UNLOCK(locked_tcb); 1.5577 + } 1.5578 + *offset = length; 1.5579 + return (NULL); 1.5580 + } 1.5581 + 1.5582 + 1.5583 + if (ch && (stcb) && netp && (*netp)) { 1.5584 + sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch, 1.5585 + stcb, *netp, 1.5586 + min(chk_length, (sizeof(chunk_buf) - 4))); 1.5587 + 1.5588 + } 1.5589 + 1.5590 + break; 1.5591 + 1.5592 + case SCTP_AUTHENTICATION: 1.5593 + SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n"); 1.5594 + if (SCTP_BASE_SYSCTL(sctp_auth_disable)) 1.5595 + goto unknown_chunk; 1.5596 + 1.5597 + if (stcb == NULL) { 1.5598 + /* save the first AUTH for later processing */ 1.5599 + if (auth_skipped == 0) { 1.5600 + auth_offset = *offset; 1.5601 + auth_len = chk_length; 1.5602 + auth_skipped = 1; 1.5603 + } 1.5604 + /* skip this chunk (temporarily) */ 1.5605 + goto next_chunk; 1.5606 + } 1.5607 + if ((chk_length < (sizeof(struct sctp_auth_chunk))) || 1.5608 + (chk_length > (sizeof(struct sctp_auth_chunk) + 1.5609 + SCTP_AUTH_DIGEST_LEN_MAX))) { 1.5610 + /* Its not ours */ 1.5611 + if (locked_tcb) { 1.5612 + SCTP_TCB_UNLOCK(locked_tcb); 1.5613 + } 1.5614 + *offset = length; 1.5615 + return (NULL); 1.5616 + } 1.5617 + if (got_auth == 1) { 1.5618 + /* skip this chunk... it's already auth'd */ 1.5619 + goto next_chunk; 1.5620 + } 1.5621 + got_auth = 1; 1.5622 + if ((ch == NULL) || sctp_handle_auth(stcb, (struct sctp_auth_chunk *)ch, 1.5623 + m, *offset)) { 1.5624 + /* auth HMAC failed so dump the packet */ 1.5625 + *offset = length; 1.5626 + return (stcb); 1.5627 + } else { 1.5628 + /* remaining chunks are HMAC checked */ 1.5629 + stcb->asoc.authenticated = 1; 1.5630 + } 1.5631 + break; 1.5632 + 1.5633 + default: 1.5634 + unknown_chunk: 1.5635 + /* it's an unknown chunk! */ 1.5636 + if ((ch->chunk_type & 0x40) && (stcb != NULL)) { 1.5637 + struct mbuf *mm; 1.5638 + struct sctp_paramhdr *phd; 1.5639 + 1.5640 + mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 1.5641 + 0, M_NOWAIT, 1, MT_DATA); 1.5642 + if (mm) { 1.5643 + phd = mtod(mm, struct sctp_paramhdr *); 1.5644 + /* 1.5645 + * We cheat and use param type since 1.5646 + * we did not bother to define a 1.5647 + * error cause struct. They are the 1.5648 + * same basic format with different 1.5649 + * names. 1.5650 + */ 1.5651 + phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK); 1.5652 + phd->param_length = htons(chk_length + sizeof(*phd)); 1.5653 + SCTP_BUF_LEN(mm) = sizeof(*phd); 1.5654 + SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); 1.5655 + if (SCTP_BUF_NEXT(mm)) { 1.5656 + if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL)) { 1.5657 + sctp_m_freem(mm); 1.5658 + } else { 1.5659 +#ifdef SCTP_MBUF_LOGGING 1.5660 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 1.5661 + struct mbuf *mat; 1.5662 + 1.5663 + for (mat = SCTP_BUF_NEXT(mm); mat; mat = SCTP_BUF_NEXT(mat)) { 1.5664 + if (SCTP_BUF_IS_EXTENDED(mat)) { 1.5665 + sctp_log_mb(mat, SCTP_MBUF_ICOPY); 1.5666 + } 1.5667 + } 1.5668 + } 1.5669 +#endif 1.5670 + sctp_queue_op_err(stcb, mm); 1.5671 + } 1.5672 + } else { 1.5673 + sctp_m_freem(mm); 1.5674 + } 1.5675 + } 1.5676 + } 1.5677 + if ((ch->chunk_type & 0x80) == 0) { 1.5678 + /* discard this packet */ 1.5679 + *offset = length; 1.5680 + return (stcb); 1.5681 + } /* else skip this bad chunk and continue... */ 1.5682 + break; 1.5683 + } /* switch (ch->chunk_type) */ 1.5684 + 1.5685 + 1.5686 + next_chunk: 1.5687 + /* get the next chunk */ 1.5688 + *offset += SCTP_SIZE32(chk_length); 1.5689 + if (*offset >= length) { 1.5690 + /* no more data left in the mbuf chain */ 1.5691 + break; 1.5692 + } 1.5693 + ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset, 1.5694 + sizeof(struct sctp_chunkhdr), chunk_buf); 1.5695 + if (ch == NULL) { 1.5696 + if (locked_tcb) { 1.5697 + SCTP_TCB_UNLOCK(locked_tcb); 1.5698 + } 1.5699 + *offset = length; 1.5700 + return (NULL); 1.5701 + } 1.5702 + } /* while */ 1.5703 + 1.5704 + if (asconf_cnt > 0 && stcb != NULL) { 1.5705 + sctp_send_asconf_ack(stcb); 1.5706 + } 1.5707 + return (stcb); 1.5708 +} 1.5709 + 1.5710 + 1.5711 +#ifdef INVARIANTS 1.5712 +#ifdef __GNUC__ 1.5713 +__attribute__((noinline)) 1.5714 +#endif 1.5715 +void 1.5716 +sctp_validate_no_locks(struct sctp_inpcb *inp) 1.5717 +{ 1.5718 +#ifndef __APPLE__ 1.5719 + struct sctp_tcb *lstcb; 1.5720 + 1.5721 + LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) { 1.5722 + if (mtx_owned(&lstcb->tcb_mtx)) { 1.5723 + panic("Own lock on stcb at return from input"); 1.5724 + } 1.5725 + } 1.5726 + if (mtx_owned(&inp->inp_create_mtx)) { 1.5727 + panic("Own create lock on inp"); 1.5728 + } 1.5729 + if (mtx_owned(&inp->inp_mtx)) { 1.5730 + panic("Own inp lock on inp"); 1.5731 + } 1.5732 +#endif 1.5733 +} 1.5734 +#endif 1.5735 + 1.5736 +/* 1.5737 + * common input chunk processing (v4 and v6) 1.5738 + */ 1.5739 +void 1.5740 +sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int length, 1.5741 + struct sockaddr *src, struct sockaddr *dst, 1.5742 + struct sctphdr *sh, struct sctp_chunkhdr *ch, 1.5743 +#if !defined(SCTP_WITH_NO_CSUM) 1.5744 + uint8_t compute_crc, 1.5745 +#endif 1.5746 + uint8_t ecn_bits, 1.5747 +#if defined(__FreeBSD__) 1.5748 + uint8_t use_mflowid, uint32_t mflowid, 1.5749 +#endif 1.5750 + uint32_t vrf_id, uint16_t port) 1.5751 +{ 1.5752 + uint32_t high_tsn; 1.5753 + int fwd_tsn_seen = 0, data_processed = 0; 1.5754 + struct mbuf *m = *mm; 1.5755 + int un_sent; 1.5756 + int cnt_ctrl_ready = 0; 1.5757 + struct sctp_inpcb *inp = NULL, *inp_decr = NULL; 1.5758 + struct sctp_tcb *stcb = NULL; 1.5759 + struct sctp_nets *net = NULL; 1.5760 + 1.5761 + SCTP_STAT_INCR(sctps_recvdatagrams); 1.5762 +#ifdef SCTP_AUDITING_ENABLED 1.5763 + sctp_audit_log(0xE0, 1); 1.5764 + sctp_auditing(0, inp, stcb, net); 1.5765 +#endif 1.5766 +#if !defined(SCTP_WITH_NO_CSUM) 1.5767 + if (compute_crc != 0) { 1.5768 + uint32_t check, calc_check; 1.5769 + 1.5770 + check = sh->checksum; 1.5771 + sh->checksum = 0; 1.5772 + calc_check = sctp_calculate_cksum(m, iphlen); 1.5773 + sh->checksum = check; 1.5774 + if (calc_check != check) { 1.5775 + SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n", 1.5776 + calc_check, check, (void *)m, length, iphlen); 1.5777 + stcb = sctp_findassociation_addr(m, offset, src, dst, 1.5778 + sh, ch, &inp, &net, vrf_id); 1.5779 + if ((net != NULL) && (port != 0)) { 1.5780 + if (net->port == 0) { 1.5781 + sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 1.5782 + } 1.5783 + net->port = port; 1.5784 + } 1.5785 +#if defined(__FreeBSD__) 1.5786 + if ((net != NULL) && (use_mflowid != 0)) { 1.5787 + net->flowid = mflowid; 1.5788 +#ifdef INVARIANTS 1.5789 + net->flowidset = 1; 1.5790 +#endif 1.5791 + } 1.5792 +#endif 1.5793 + if ((inp != NULL) && (stcb != NULL)) { 1.5794 + sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1); 1.5795 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED); 1.5796 + } else if ((inp != NULL) && (stcb == NULL)) { 1.5797 + inp_decr = inp; 1.5798 + } 1.5799 + SCTP_STAT_INCR(sctps_badsum); 1.5800 + SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors); 1.5801 + goto out; 1.5802 + } 1.5803 + } 1.5804 +#endif 1.5805 + /* Destination port of 0 is illegal, based on RFC4960. */ 1.5806 + if (sh->dest_port == 0) { 1.5807 + SCTP_STAT_INCR(sctps_hdrops); 1.5808 + goto out; 1.5809 + } 1.5810 + stcb = sctp_findassociation_addr(m, offset, src, dst, 1.5811 + sh, ch, &inp, &net, vrf_id); 1.5812 + if ((net != NULL) && (port != 0)) { 1.5813 + if (net->port == 0) { 1.5814 + sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 1.5815 + } 1.5816 + net->port = port; 1.5817 + } 1.5818 +#if defined(__FreeBSD__) 1.5819 + if ((net != NULL) && (use_mflowid != 0)) { 1.5820 + net->flowid = mflowid; 1.5821 +#ifdef INVARIANTS 1.5822 + net->flowidset = 1; 1.5823 +#endif 1.5824 + } 1.5825 +#endif 1.5826 + if (inp == NULL) { 1.5827 + SCTP_STAT_INCR(sctps_noport); 1.5828 +#if defined(__FreeBSD__) && (((__FreeBSD_version < 900000) && (__FreeBSD_version >= 804000)) || (__FreeBSD_version > 900000)) 1.5829 + if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) { 1.5830 + goto out; 1.5831 + } 1.5832 +#endif 1.5833 + if (ch->chunk_type == SCTP_SHUTDOWN_ACK) { 1.5834 + sctp_send_shutdown_complete2(src, dst, sh, 1.5835 +#if defined(__FreeBSD__) 1.5836 + use_mflowid, mflowid, 1.5837 +#endif 1.5838 + vrf_id, port); 1.5839 + goto out; 1.5840 + } 1.5841 + if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) { 1.5842 + goto out; 1.5843 + } 1.5844 + if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) { 1.5845 + if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || 1.5846 + ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && 1.5847 + (ch->chunk_type != SCTP_INIT))) { 1.5848 + sctp_send_abort(m, iphlen, src, dst, 1.5849 + sh, 0, NULL, 1.5850 +#if defined(__FreeBSD__) 1.5851 + use_mflowid, mflowid, 1.5852 +#endif 1.5853 + vrf_id, port); 1.5854 + } 1.5855 + } 1.5856 + goto out; 1.5857 + } else if (stcb == NULL) { 1.5858 + inp_decr = inp; 1.5859 + } 1.5860 +#ifdef IPSEC 1.5861 + /*- 1.5862 + * I very much doubt any of the IPSEC stuff will work but I have no 1.5863 + * idea, so I will leave it in place. 1.5864 + */ 1.5865 + if (inp != NULL) { 1.5866 + switch (dst->sa_family) { 1.5867 +#ifdef INET 1.5868 + case AF_INET: 1.5869 + if (ipsec4_in_reject(m, &inp->ip_inp.inp)) { 1.5870 +#if defined(__FreeBSD__) && (__FreeBSD_version > 1000036) 1.5871 + IPSECSTAT_INC(ips_in_polvio); 1.5872 +#else 1.5873 + MODULE_GLOBAL(ipsec4stat).in_polvio++; 1.5874 +#endif 1.5875 + SCTP_STAT_INCR(sctps_hdrops); 1.5876 + goto out; 1.5877 + } 1.5878 + break; 1.5879 +#endif 1.5880 +#ifdef INET6 1.5881 + case AF_INET6: 1.5882 + if (ipsec6_in_reject(m, &inp->ip_inp.inp)) { 1.5883 +#if defined(__FreeBSD__) && (__FreeBSD_version > 1000036) 1.5884 + IPSEC6STAT_INC(ips_in_polvio); 1.5885 +#else 1.5886 + MODULE_GLOBAL(ipsec6stat).in_polvio++; 1.5887 +#endif 1.5888 + SCTP_STAT_INCR(sctps_hdrops); 1.5889 + goto out; 1.5890 + } 1.5891 + break; 1.5892 +#endif 1.5893 + default: 1.5894 + break; 1.5895 + } 1.5896 + } 1.5897 +#endif 1.5898 + SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n", 1.5899 + (void *)m, iphlen, offset, length, (void *)stcb); 1.5900 + if (stcb) { 1.5901 + /* always clear this before beginning a packet */ 1.5902 + stcb->asoc.authenticated = 0; 1.5903 + stcb->asoc.seen_a_sack_this_pkt = 0; 1.5904 + SCTPDBG(SCTP_DEBUG_INPUT1, "stcb:%p state:%x\n", 1.5905 + (void *)stcb, stcb->asoc.state); 1.5906 + 1.5907 + if ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) || 1.5908 + (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) { 1.5909 + /*- 1.5910 + * If we hit here, we had a ref count 1.5911 + * up when the assoc was aborted and the 1.5912 + * timer is clearing out the assoc, we should 1.5913 + * NOT respond to any packet.. its OOTB. 1.5914 + */ 1.5915 + SCTP_TCB_UNLOCK(stcb); 1.5916 + stcb = NULL; 1.5917 + sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, 1.5918 +#if defined(__FreeBSD__) 1.5919 + use_mflowid, mflowid, 1.5920 +#endif 1.5921 + vrf_id, port); 1.5922 + goto out; 1.5923 + } 1.5924 + 1.5925 + } 1.5926 + if (IS_SCTP_CONTROL(ch)) { 1.5927 + /* process the control portion of the SCTP packet */ 1.5928 + /* sa_ignore NO_NULL_CHK */ 1.5929 + stcb = sctp_process_control(m, iphlen, &offset, length, 1.5930 + src, dst, sh, ch, 1.5931 + inp, stcb, &net, &fwd_tsn_seen, 1.5932 +#if defined(__FreeBSD__) 1.5933 + use_mflowid, mflowid, 1.5934 +#endif 1.5935 + vrf_id, port); 1.5936 + if (stcb) { 1.5937 + /* This covers us if the cookie-echo was there 1.5938 + * and it changes our INP. 1.5939 + */ 1.5940 + inp = stcb->sctp_ep; 1.5941 + if ((net) && (port)) { 1.5942 + if (net->port == 0) { 1.5943 + sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr)); 1.5944 + } 1.5945 + net->port = port; 1.5946 + } 1.5947 + } 1.5948 + } else { 1.5949 + /* 1.5950 + * no control chunks, so pre-process DATA chunks (these 1.5951 + * checks are taken care of by control processing) 1.5952 + */ 1.5953 + 1.5954 + /* 1.5955 + * if DATA only packet, and auth is required, then punt... 1.5956 + * can't have authenticated without any AUTH (control) 1.5957 + * chunks 1.5958 + */ 1.5959 + if ((stcb != NULL) && 1.5960 + !SCTP_BASE_SYSCTL(sctp_auth_disable) && 1.5961 + sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) { 1.5962 + /* "silently" ignore */ 1.5963 + SCTP_STAT_INCR(sctps_recvauthmissing); 1.5964 + goto out; 1.5965 + } 1.5966 + if (stcb == NULL) { 1.5967 + /* out of the blue DATA chunk */ 1.5968 + sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, 1.5969 +#if defined(__FreeBSD__) 1.5970 + use_mflowid, mflowid, 1.5971 +#endif 1.5972 + vrf_id, port); 1.5973 + goto out; 1.5974 + } 1.5975 + if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) { 1.5976 + /* v_tag mismatch! */ 1.5977 + SCTP_STAT_INCR(sctps_badvtag); 1.5978 + goto out; 1.5979 + } 1.5980 + } 1.5981 + 1.5982 + if (stcb == NULL) { 1.5983 + /* 1.5984 + * no valid TCB for this packet, or we found it's a bad 1.5985 + * packet while processing control, or we're done with this 1.5986 + * packet (done or skip rest of data), so we drop it... 1.5987 + */ 1.5988 + goto out; 1.5989 + } 1.5990 + 1.5991 + /* 1.5992 + * DATA chunk processing 1.5993 + */ 1.5994 + /* plow through the data chunks while length > offset */ 1.5995 + 1.5996 + /* 1.5997 + * Rest should be DATA only. Check authentication state if AUTH for 1.5998 + * DATA is required. 1.5999 + */ 1.6000 + if ((length > offset) && 1.6001 + (stcb != NULL) && 1.6002 + !SCTP_BASE_SYSCTL(sctp_auth_disable) && 1.6003 + sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) && 1.6004 + !stcb->asoc.authenticated) { 1.6005 + /* "silently" ignore */ 1.6006 + SCTP_STAT_INCR(sctps_recvauthmissing); 1.6007 + SCTPDBG(SCTP_DEBUG_AUTH1, 1.6008 + "Data chunk requires AUTH, skipped\n"); 1.6009 + goto trigger_send; 1.6010 + } 1.6011 + if (length > offset) { 1.6012 + int retval; 1.6013 + 1.6014 + /* 1.6015 + * First check to make sure our state is correct. We would 1.6016 + * not get here unless we really did have a tag, so we don't 1.6017 + * abort if this happens, just dump the chunk silently. 1.6018 + */ 1.6019 + switch (SCTP_GET_STATE(&stcb->asoc)) { 1.6020 + case SCTP_STATE_COOKIE_ECHOED: 1.6021 + /* 1.6022 + * we consider data with valid tags in this state 1.6023 + * shows us the cookie-ack was lost. Imply it was 1.6024 + * there. 1.6025 + */ 1.6026 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) { 1.6027 + sctp_misc_ints(SCTP_THRESHOLD_CLEAR, 1.6028 + stcb->asoc.overall_error_count, 1.6029 + 0, 1.6030 + SCTP_FROM_SCTP_INPUT, 1.6031 + __LINE__); 1.6032 + } 1.6033 + stcb->asoc.overall_error_count = 0; 1.6034 + sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, net); 1.6035 + break; 1.6036 + case SCTP_STATE_COOKIE_WAIT: 1.6037 + /* 1.6038 + * We consider OOTB any data sent during asoc setup. 1.6039 + */ 1.6040 + sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, 1.6041 +#if defined(__FreeBSD__) 1.6042 + use_mflowid, mflowid, 1.6043 +#endif 1.6044 + vrf_id, port); 1.6045 + goto out; 1.6046 + /*sa_ignore NOTREACHED*/ 1.6047 + break; 1.6048 + case SCTP_STATE_EMPTY: /* should not happen */ 1.6049 + case SCTP_STATE_INUSE: /* should not happen */ 1.6050 + case SCTP_STATE_SHUTDOWN_RECEIVED: /* This is a peer error */ 1.6051 + case SCTP_STATE_SHUTDOWN_ACK_SENT: 1.6052 + default: 1.6053 + goto out; 1.6054 + /*sa_ignore NOTREACHED*/ 1.6055 + break; 1.6056 + case SCTP_STATE_OPEN: 1.6057 + case SCTP_STATE_SHUTDOWN_SENT: 1.6058 + break; 1.6059 + } 1.6060 + /* plow through the data chunks while length > offset */ 1.6061 + retval = sctp_process_data(mm, iphlen, &offset, length, 1.6062 + src, dst, sh, 1.6063 + inp, stcb, net, &high_tsn, 1.6064 +#if defined(__FreeBSD__) 1.6065 + use_mflowid, mflowid, 1.6066 +#endif 1.6067 + vrf_id, port); 1.6068 + if (retval == 2) { 1.6069 + /* 1.6070 + * The association aborted, NO UNLOCK needed since 1.6071 + * the association is destroyed. 1.6072 + */ 1.6073 + stcb = NULL; 1.6074 + goto out; 1.6075 + } 1.6076 + data_processed = 1; 1.6077 + /* 1.6078 + * Anything important needs to have been m_copy'ed in 1.6079 + * process_data 1.6080 + */ 1.6081 + } 1.6082 + 1.6083 + /* take care of ecn */ 1.6084 + if ((data_processed == 1) && 1.6085 + (stcb->asoc.ecn_allowed == 1) && 1.6086 + ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) { 1.6087 + /* Yep, we need to add a ECNE */ 1.6088 + sctp_send_ecn_echo(stcb, net, high_tsn); 1.6089 + } 1.6090 + 1.6091 + if ((data_processed == 0) && (fwd_tsn_seen)) { 1.6092 + int was_a_gap; 1.6093 + uint32_t highest_tsn; 1.6094 + 1.6095 + if (SCTP_TSN_GT(stcb->asoc.highest_tsn_inside_nr_map, stcb->asoc.highest_tsn_inside_map)) { 1.6096 + highest_tsn = stcb->asoc.highest_tsn_inside_nr_map; 1.6097 + } else { 1.6098 + highest_tsn = stcb->asoc.highest_tsn_inside_map; 1.6099 + } 1.6100 + was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn); 1.6101 + stcb->asoc.send_sack = 1; 1.6102 + sctp_sack_check(stcb, was_a_gap); 1.6103 + } else if (fwd_tsn_seen) { 1.6104 + stcb->asoc.send_sack = 1; 1.6105 + } 1.6106 + /* trigger send of any chunks in queue... */ 1.6107 +trigger_send: 1.6108 +#ifdef SCTP_AUDITING_ENABLED 1.6109 + sctp_audit_log(0xE0, 2); 1.6110 + sctp_auditing(1, inp, stcb, net); 1.6111 +#endif 1.6112 + SCTPDBG(SCTP_DEBUG_INPUT1, 1.6113 + "Check for chunk output prw:%d tqe:%d tf=%d\n", 1.6114 + stcb->asoc.peers_rwnd, 1.6115 + TAILQ_EMPTY(&stcb->asoc.control_send_queue), 1.6116 + stcb->asoc.total_flight); 1.6117 + un_sent = (stcb->asoc.total_output_queue_size - stcb->asoc.total_flight); 1.6118 + if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) { 1.6119 + cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq; 1.6120 + } 1.6121 + if (cnt_ctrl_ready || 1.6122 + ((un_sent) && 1.6123 + (stcb->asoc.peers_rwnd > 0 || 1.6124 + (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) { 1.6125 + SCTPDBG(SCTP_DEBUG_INPUT3, "Calling chunk OUTPUT\n"); 1.6126 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED); 1.6127 + SCTPDBG(SCTP_DEBUG_INPUT3, "chunk OUTPUT returns\n"); 1.6128 + } 1.6129 +#ifdef SCTP_AUDITING_ENABLED 1.6130 + sctp_audit_log(0xE0, 3); 1.6131 + sctp_auditing(2, inp, stcb, net); 1.6132 +#endif 1.6133 + out: 1.6134 + if (stcb != NULL) { 1.6135 + SCTP_TCB_UNLOCK(stcb); 1.6136 + } 1.6137 + if (inp_decr != NULL) { 1.6138 + /* reduce ref-count */ 1.6139 + SCTP_INP_WLOCK(inp_decr); 1.6140 + SCTP_INP_DECR_REF(inp_decr); 1.6141 + SCTP_INP_WUNLOCK(inp_decr); 1.6142 + } 1.6143 +#ifdef INVARIANTS 1.6144 + if (inp != NULL) { 1.6145 + sctp_validate_no_locks(inp); 1.6146 + } 1.6147 +#endif 1.6148 + return; 1.6149 +} 1.6150 + 1.6151 +#if 0 1.6152 +static void 1.6153 +sctp_print_mbuf_chain(struct mbuf *m) 1.6154 +{ 1.6155 + for (; m; m = SCTP_BUF_NEXT(m)) { 1.6156 + SCTP_PRINTF("%p: m_len = %ld\n", (void *)m, SCTP_BUF_LEN(m)); 1.6157 + if (SCTP_BUF_IS_EXTENDED(m)) 1.6158 + SCTP_PRINTF("%p: extend_size = %d\n", (void *)m, SCTP_BUF_EXTEND_SIZE(m)); 1.6159 + } 1.6160 +} 1.6161 +#endif 1.6162 + 1.6163 +#ifdef INET 1.6164 +#if !defined(__Userspace__) 1.6165 +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__) 1.6166 +void 1.6167 +sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port) 1.6168 +#elif defined(__Panda__) 1.6169 +void 1.6170 +sctp_input(pakhandle_type i_pak) 1.6171 +#else 1.6172 +void 1.6173 +#if __STDC__ 1.6174 +sctp_input(struct mbuf *i_pak,...) 1.6175 +#else 1.6176 +sctp_input(i_pak, va_alist) 1.6177 + struct mbuf *i_pak; 1.6178 +#endif 1.6179 +#endif 1.6180 +{ 1.6181 + struct mbuf *m; 1.6182 + int iphlen; 1.6183 + uint32_t vrf_id = 0; 1.6184 + uint8_t ecn_bits; 1.6185 + struct sockaddr_in src, dst; 1.6186 + struct ip *ip; 1.6187 + struct sctphdr *sh; 1.6188 + struct sctp_chunkhdr *ch; 1.6189 + int length, offset; 1.6190 +#if !defined(SCTP_WITH_NO_CSUM) 1.6191 + uint8_t compute_crc; 1.6192 +#endif 1.6193 +#if defined(__FreeBSD__) 1.6194 + uint32_t mflowid; 1.6195 + uint8_t use_mflowid; 1.6196 +#endif 1.6197 +#if !(defined(__FreeBSD__) || defined(__APPLE__) || defined(__Windows__)) 1.6198 + uint16_t port = 0; 1.6199 +#endif 1.6200 + 1.6201 +#if defined(__Panda__) 1.6202 + /* This is Evil, but its the only way to make panda work right. */ 1.6203 + iphlen = sizeof(struct ip); 1.6204 +#else 1.6205 + iphlen = off; 1.6206 +#endif 1.6207 + if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) { 1.6208 + SCTP_RELEASE_PKT(i_pak); 1.6209 + return; 1.6210 + } 1.6211 + m = SCTP_HEADER_TO_CHAIN(i_pak); 1.6212 +#ifdef __Panda__ 1.6213 + SCTP_DETACH_HEADER_FROM_CHAIN(i_pak); 1.6214 + (void)SCTP_RELEASE_HEADER(i_pak); 1.6215 +#endif 1.6216 +#ifdef SCTP_MBUF_LOGGING 1.6217 + /* Log in any input mbufs */ 1.6218 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 1.6219 + struct mbuf *mat; 1.6220 + 1.6221 + for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) { 1.6222 + if (SCTP_BUF_IS_EXTENDED(mat)) { 1.6223 + sctp_log_mb(mat, SCTP_MBUF_INPUT); 1.6224 + } 1.6225 + } 1.6226 + } 1.6227 +#endif 1.6228 +#ifdef SCTP_PACKET_LOGGING 1.6229 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) { 1.6230 + sctp_packet_log(m); 1.6231 + } 1.6232 +#endif 1.6233 +#if defined(__FreeBSD__) 1.6234 +#if __FreeBSD_version > 1000049 1.6235 + SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 1.6236 + "sctp_input(): Packet of length %d received on %s with csum_flags 0x%b.\n", 1.6237 + m->m_pkthdr.len, 1.6238 + if_name(m->m_pkthdr.rcvif), 1.6239 + (int)m->m_pkthdr.csum_flags, CSUM_BITS); 1.6240 +#elif __FreeBSD_version >= 800000 1.6241 + SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 1.6242 + "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", 1.6243 + m->m_pkthdr.len, 1.6244 + if_name(m->m_pkthdr.rcvif), 1.6245 + m->m_pkthdr.csum_flags); 1.6246 +#else 1.6247 + SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 1.6248 + "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", 1.6249 + m->m_pkthdr.len, 1.6250 + m->m_pkthdr.rcvif->if_xname, 1.6251 + m->m_pkthdr.csum_flags); 1.6252 +#endif 1.6253 +#endif 1.6254 +#if defined(__APPLE__) 1.6255 + SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 1.6256 + "sctp_input(): Packet of length %d received on %s%d with csum_flags 0x%x.\n", 1.6257 + m->m_pkthdr.len, 1.6258 + m->m_pkthdr.rcvif->if_name, 1.6259 + m->m_pkthdr.rcvif->if_unit, 1.6260 + m->m_pkthdr.csum_flags); 1.6261 +#endif 1.6262 +#if defined(__Windows__) 1.6263 + SCTPDBG(SCTP_DEBUG_CRCOFFLOAD, 1.6264 + "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n", 1.6265 + m->m_pkthdr.len, 1.6266 + m->m_pkthdr.rcvif->if_xname, 1.6267 + m->m_pkthdr.csum_flags); 1.6268 +#endif 1.6269 +#if defined(__FreeBSD__) 1.6270 + if (m->m_flags & M_FLOWID) { 1.6271 + mflowid = m->m_pkthdr.flowid; 1.6272 + use_mflowid = 1; 1.6273 + } else { 1.6274 + mflowid = 0; 1.6275 + use_mflowid = 0; 1.6276 + } 1.6277 +#endif 1.6278 + SCTP_STAT_INCR(sctps_recvpackets); 1.6279 + SCTP_STAT_INCR_COUNTER64(sctps_inpackets); 1.6280 + /* Get IP, SCTP, and first chunk header together in the first mbuf. */ 1.6281 + offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr); 1.6282 + if (SCTP_BUF_LEN(m) < offset) { 1.6283 + if ((m = m_pullup(m, offset)) == NULL) { 1.6284 + SCTP_STAT_INCR(sctps_hdrops); 1.6285 + return; 1.6286 + } 1.6287 + } 1.6288 + ip = mtod(m, struct ip *); 1.6289 + sh = (struct sctphdr *)((caddr_t)ip + iphlen); 1.6290 + ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr)); 1.6291 + offset -= sizeof(struct sctp_chunkhdr); 1.6292 + memset(&src, 0, sizeof(struct sockaddr_in)); 1.6293 + src.sin_family = AF_INET; 1.6294 +#ifdef HAVE_SIN_LEN 1.6295 + src.sin_len = sizeof(struct sockaddr_in); 1.6296 +#endif 1.6297 + src.sin_port = sh->src_port; 1.6298 + src.sin_addr = ip->ip_src; 1.6299 + memset(&dst, 0, sizeof(struct sockaddr_in)); 1.6300 + dst.sin_family = AF_INET; 1.6301 +#ifdef HAVE_SIN_LEN 1.6302 + dst.sin_len = sizeof(struct sockaddr_in); 1.6303 +#endif 1.6304 + dst.sin_port = sh->dest_port; 1.6305 + dst.sin_addr = ip->ip_dst; 1.6306 +#if defined(__Windows__) 1.6307 + NTOHS(ip->ip_len); 1.6308 +#endif 1.6309 +#if defined(__Userspace_os_Linux) || defined(__Userspace_os_Windows) 1.6310 + ip->ip_len = ntohs(ip->ip_len); 1.6311 +#endif 1.6312 +#if defined(__FreeBSD__) 1.6313 +#if __FreeBSD_version >= 1000000 1.6314 + length = ntohs(ip->ip_len); 1.6315 +#else 1.6316 + length = ip->ip_len + iphlen; 1.6317 +#endif 1.6318 +#elif defined(__APPLE__) 1.6319 + length = ip->ip_len + iphlen; 1.6320 +#elif defined(__Userspace__) 1.6321 +#if defined(__Userspace_os_Linux) || defined(__Userspace_os_Windows) 1.6322 + length = ip->ip_len; 1.6323 +#else 1.6324 + length = ip->ip_len + iphlen; 1.6325 +#endif 1.6326 +#else 1.6327 + length = ip->ip_len; 1.6328 +#endif 1.6329 + /* Validate mbuf chain length with IP payload length. */ 1.6330 + if (SCTP_HEADER_LEN(m) != length) { 1.6331 + SCTPDBG(SCTP_DEBUG_INPUT1, 1.6332 + "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m)); 1.6333 + SCTP_STAT_INCR(sctps_hdrops); 1.6334 + goto out; 1.6335 + } 1.6336 + /* SCTP does not allow broadcasts or multicasts */ 1.6337 + if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) { 1.6338 + goto out; 1.6339 + } 1.6340 + if (SCTP_IS_IT_BROADCAST(dst.sin_addr, m)) { 1.6341 + goto out; 1.6342 + } 1.6343 + ecn_bits = ip->ip_tos; 1.6344 +#if defined(SCTP_WITH_NO_CSUM) 1.6345 + SCTP_STAT_INCR(sctps_recvnocrc); 1.6346 +#else 1.6347 +#if defined(__FreeBSD__) && __FreeBSD_version >= 800000 1.6348 + if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) { 1.6349 + SCTP_STAT_INCR(sctps_recvhwcrc); 1.6350 + compute_crc = 0; 1.6351 + } else { 1.6352 +#else 1.6353 + if (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) && 1.6354 + ((src.sin_addr.s_addr == dst.sin_addr.s_addr) || 1.6355 + (SCTP_IS_IT_LOOPBACK(m)))) { 1.6356 + SCTP_STAT_INCR(sctps_recvnocrc); 1.6357 + compute_crc = 0; 1.6358 + } else { 1.6359 +#endif 1.6360 + SCTP_STAT_INCR(sctps_recvswcrc); 1.6361 + compute_crc = 1; 1.6362 + } 1.6363 +#endif 1.6364 + sctp_common_input_processing(&m, iphlen, offset, length, 1.6365 + (struct sockaddr *)&src, 1.6366 + (struct sockaddr *)&dst, 1.6367 + sh, ch, 1.6368 +#if !defined(SCTP_WITH_NO_CSUM) 1.6369 + compute_crc, 1.6370 +#endif 1.6371 + ecn_bits, 1.6372 +#if defined(__FreeBSD__) 1.6373 + use_mflowid, mflowid, 1.6374 +#endif 1.6375 + vrf_id, port); 1.6376 + out: 1.6377 + if (m) { 1.6378 + sctp_m_freem(m); 1.6379 + } 1.6380 + return; 1.6381 +} 1.6382 + 1.6383 +#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 1.6384 +extern int *sctp_cpuarry; 1.6385 +#endif 1.6386 + 1.6387 +void 1.6388 +sctp_input(struct mbuf *m, int off) 1.6389 +{ 1.6390 +#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP) 1.6391 + struct ip *ip; 1.6392 + struct sctphdr *sh; 1.6393 + int offset; 1.6394 + int cpu_to_use; 1.6395 + uint32_t flowid, tag; 1.6396 + 1.6397 + if (mp_ncpus > 1) { 1.6398 + if (m->m_flags & M_FLOWID) { 1.6399 + flowid = m->m_pkthdr.flowid; 1.6400 + } else { 1.6401 + /* No flow id built by lower layers 1.6402 + * fix it so we create one. 1.6403 + */ 1.6404 + offset = off + sizeof(struct sctphdr); 1.6405 + if (SCTP_BUF_LEN(m) < offset) { 1.6406 + if ((m = m_pullup(m, offset)) == NULL) { 1.6407 + SCTP_STAT_INCR(sctps_hdrops); 1.6408 + return; 1.6409 + } 1.6410 + } 1.6411 + ip = mtod(m, struct ip *); 1.6412 + sh = (struct sctphdr *)((caddr_t)ip + off); 1.6413 + tag = htonl(sh->v_tag); 1.6414 + flowid = tag ^ ntohs(sh->dest_port) ^ ntohs(sh->src_port); 1.6415 + m->m_pkthdr.flowid = flowid; 1.6416 + m->m_flags |= M_FLOWID; 1.6417 + } 1.6418 + cpu_to_use = sctp_cpuarry[flowid % mp_ncpus]; 1.6419 + sctp_queue_to_mcore(m, off, cpu_to_use); 1.6420 + return; 1.6421 + } 1.6422 +#endif 1.6423 + sctp_input_with_port(m, off, 0); 1.6424 +} 1.6425 +#endif 1.6426 +#endif