1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/sctp/src/netinet/sctputil.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,7875 @@ 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/sctputil.c 259943 2013-12-27 13:07:00Z tuexen $"); 1.39 +#endif 1.40 + 1.41 +#include <netinet/sctp_os.h> 1.42 +#include <netinet/sctp_pcb.h> 1.43 +#include <netinet/sctputil.h> 1.44 +#include <netinet/sctp_var.h> 1.45 +#include <netinet/sctp_sysctl.h> 1.46 +#ifdef INET6 1.47 +#if defined(__Userspace__) || defined(__FreeBSD__) 1.48 +#include <netinet6/sctp6_var.h> 1.49 +#endif 1.50 +#endif 1.51 +#include <netinet/sctp_header.h> 1.52 +#include <netinet/sctp_output.h> 1.53 +#include <netinet/sctp_uio.h> 1.54 +#include <netinet/sctp_timer.h> 1.55 +#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */ 1.56 +#include <netinet/sctp_auth.h> 1.57 +#include <netinet/sctp_asconf.h> 1.58 +#include <netinet/sctp_bsd_addr.h> 1.59 +#if defined(__Userspace__) 1.60 +#include <netinet/sctp_constants.h> 1.61 +#endif 1.62 +#if defined(__FreeBSD__) 1.63 +#include <netinet/udp.h> 1.64 +#include <netinet/udp_var.h> 1.65 +#include <sys/proc.h> 1.66 +#endif 1.67 + 1.68 +#if defined(__APPLE__) 1.69 +#define APPLE_FILE_NO 8 1.70 +#endif 1.71 + 1.72 +#if defined(__Windows__) 1.73 +#if !defined(SCTP_LOCAL_TRACE_BUF) 1.74 +#include "eventrace_netinet.h" 1.75 +#include "sctputil.tmh" /* this is the file that will be auto generated */ 1.76 +#endif 1.77 +#else 1.78 +#ifndef KTR_SCTP 1.79 +#define KTR_SCTP KTR_SUBSYS 1.80 +#endif 1.81 +#endif 1.82 + 1.83 +extern struct sctp_cc_functions sctp_cc_functions[]; 1.84 +extern struct sctp_ss_functions sctp_ss_functions[]; 1.85 + 1.86 +void 1.87 +sctp_sblog(struct sockbuf *sb, struct sctp_tcb *stcb, int from, int incr) 1.88 +{ 1.89 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.90 + struct sctp_cwnd_log sctp_clog; 1.91 + 1.92 + sctp_clog.x.sb.stcb = stcb; 1.93 + sctp_clog.x.sb.so_sbcc = sb->sb_cc; 1.94 + if (stcb) 1.95 + sctp_clog.x.sb.stcb_sbcc = stcb->asoc.sb_cc; 1.96 + else 1.97 + sctp_clog.x.sb.stcb_sbcc = 0; 1.98 + sctp_clog.x.sb.incr = incr; 1.99 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.100 + SCTP_LOG_EVENT_SB, 1.101 + from, 1.102 + sctp_clog.x.misc.log1, 1.103 + sctp_clog.x.misc.log2, 1.104 + sctp_clog.x.misc.log3, 1.105 + sctp_clog.x.misc.log4); 1.106 +#endif 1.107 +} 1.108 + 1.109 +void 1.110 +sctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc) 1.111 +{ 1.112 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.113 + struct sctp_cwnd_log sctp_clog; 1.114 + 1.115 + sctp_clog.x.close.inp = (void *)inp; 1.116 + sctp_clog.x.close.sctp_flags = inp->sctp_flags; 1.117 + if (stcb) { 1.118 + sctp_clog.x.close.stcb = (void *)stcb; 1.119 + sctp_clog.x.close.state = (uint16_t)stcb->asoc.state; 1.120 + } else { 1.121 + sctp_clog.x.close.stcb = 0; 1.122 + sctp_clog.x.close.state = 0; 1.123 + } 1.124 + sctp_clog.x.close.loc = loc; 1.125 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.126 + SCTP_LOG_EVENT_CLOSE, 1.127 + 0, 1.128 + sctp_clog.x.misc.log1, 1.129 + sctp_clog.x.misc.log2, 1.130 + sctp_clog.x.misc.log3, 1.131 + sctp_clog.x.misc.log4); 1.132 +#endif 1.133 +} 1.134 + 1.135 +void 1.136 +rto_logging(struct sctp_nets *net, int from) 1.137 +{ 1.138 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.139 + struct sctp_cwnd_log sctp_clog; 1.140 + 1.141 + memset(&sctp_clog, 0, sizeof(sctp_clog)); 1.142 + sctp_clog.x.rto.net = (void *) net; 1.143 + sctp_clog.x.rto.rtt = net->rtt / 1000; 1.144 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.145 + SCTP_LOG_EVENT_RTT, 1.146 + from, 1.147 + sctp_clog.x.misc.log1, 1.148 + sctp_clog.x.misc.log2, 1.149 + sctp_clog.x.misc.log3, 1.150 + sctp_clog.x.misc.log4); 1.151 +#endif 1.152 +} 1.153 + 1.154 +void 1.155 +sctp_log_strm_del_alt(struct sctp_tcb *stcb, uint32_t tsn, uint16_t sseq, uint16_t stream, int from) 1.156 +{ 1.157 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.158 + struct sctp_cwnd_log sctp_clog; 1.159 + 1.160 + sctp_clog.x.strlog.stcb = stcb; 1.161 + sctp_clog.x.strlog.n_tsn = tsn; 1.162 + sctp_clog.x.strlog.n_sseq = sseq; 1.163 + sctp_clog.x.strlog.e_tsn = 0; 1.164 + sctp_clog.x.strlog.e_sseq = 0; 1.165 + sctp_clog.x.strlog.strm = stream; 1.166 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.167 + SCTP_LOG_EVENT_STRM, 1.168 + from, 1.169 + sctp_clog.x.misc.log1, 1.170 + sctp_clog.x.misc.log2, 1.171 + sctp_clog.x.misc.log3, 1.172 + sctp_clog.x.misc.log4); 1.173 +#endif 1.174 +} 1.175 + 1.176 +void 1.177 +sctp_log_nagle_event(struct sctp_tcb *stcb, int action) 1.178 +{ 1.179 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.180 + struct sctp_cwnd_log sctp_clog; 1.181 + 1.182 + sctp_clog.x.nagle.stcb = (void *)stcb; 1.183 + sctp_clog.x.nagle.total_flight = stcb->asoc.total_flight; 1.184 + sctp_clog.x.nagle.total_in_queue = stcb->asoc.total_output_queue_size; 1.185 + sctp_clog.x.nagle.count_in_queue = stcb->asoc.chunks_on_out_queue; 1.186 + sctp_clog.x.nagle.count_in_flight = stcb->asoc.total_flight_count; 1.187 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.188 + SCTP_LOG_EVENT_NAGLE, 1.189 + action, 1.190 + sctp_clog.x.misc.log1, 1.191 + sctp_clog.x.misc.log2, 1.192 + sctp_clog.x.misc.log3, 1.193 + sctp_clog.x.misc.log4); 1.194 +#endif 1.195 +} 1.196 + 1.197 +void 1.198 +sctp_log_sack(uint32_t old_cumack, uint32_t cumack, uint32_t tsn, uint16_t gaps, uint16_t dups, int from) 1.199 +{ 1.200 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.201 + struct sctp_cwnd_log sctp_clog; 1.202 + 1.203 + sctp_clog.x.sack.cumack = cumack; 1.204 + sctp_clog.x.sack.oldcumack = old_cumack; 1.205 + sctp_clog.x.sack.tsn = tsn; 1.206 + sctp_clog.x.sack.numGaps = gaps; 1.207 + sctp_clog.x.sack.numDups = dups; 1.208 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.209 + SCTP_LOG_EVENT_SACK, 1.210 + from, 1.211 + sctp_clog.x.misc.log1, 1.212 + sctp_clog.x.misc.log2, 1.213 + sctp_clog.x.misc.log3, 1.214 + sctp_clog.x.misc.log4); 1.215 +#endif 1.216 +} 1.217 + 1.218 +void 1.219 +sctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from) 1.220 +{ 1.221 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.222 + struct sctp_cwnd_log sctp_clog; 1.223 + 1.224 + memset(&sctp_clog, 0, sizeof(sctp_clog)); 1.225 + sctp_clog.x.map.base = map; 1.226 + sctp_clog.x.map.cum = cum; 1.227 + sctp_clog.x.map.high = high; 1.228 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.229 + SCTP_LOG_EVENT_MAP, 1.230 + from, 1.231 + sctp_clog.x.misc.log1, 1.232 + sctp_clog.x.misc.log2, 1.233 + sctp_clog.x.misc.log3, 1.234 + sctp_clog.x.misc.log4); 1.235 +#endif 1.236 +} 1.237 + 1.238 +void 1.239 +sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn, int from) 1.240 +{ 1.241 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.242 + struct sctp_cwnd_log sctp_clog; 1.243 + 1.244 + memset(&sctp_clog, 0, sizeof(sctp_clog)); 1.245 + sctp_clog.x.fr.largest_tsn = biggest_tsn; 1.246 + sctp_clog.x.fr.largest_new_tsn = biggest_new_tsn; 1.247 + sctp_clog.x.fr.tsn = tsn; 1.248 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.249 + SCTP_LOG_EVENT_FR, 1.250 + from, 1.251 + sctp_clog.x.misc.log1, 1.252 + sctp_clog.x.misc.log2, 1.253 + sctp_clog.x.misc.log3, 1.254 + sctp_clog.x.misc.log4); 1.255 +#endif 1.256 +} 1.257 + 1.258 +void 1.259 +sctp_log_mb(struct mbuf *m, int from) 1.260 +{ 1.261 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.262 + struct sctp_cwnd_log sctp_clog; 1.263 + 1.264 + sctp_clog.x.mb.mp = m; 1.265 + sctp_clog.x.mb.mbuf_flags = (uint8_t)(SCTP_BUF_GET_FLAGS(m)); 1.266 + sctp_clog.x.mb.size = (uint16_t)(SCTP_BUF_LEN(m)); 1.267 + sctp_clog.x.mb.data = SCTP_BUF_AT(m, 0); 1.268 + if (SCTP_BUF_IS_EXTENDED(m)) { 1.269 + sctp_clog.x.mb.ext = SCTP_BUF_EXTEND_BASE(m); 1.270 +#if defined(__APPLE__) 1.271 + /* APPLE does not use a ref_cnt, but a forward/backward ref queue */ 1.272 +#else 1.273 + sctp_clog.x.mb.refcnt = (uint8_t)(SCTP_BUF_EXTEND_REFCNT(m)); 1.274 +#endif 1.275 + } else { 1.276 + sctp_clog.x.mb.ext = 0; 1.277 + sctp_clog.x.mb.refcnt = 0; 1.278 + } 1.279 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.280 + SCTP_LOG_EVENT_MBUF, 1.281 + from, 1.282 + sctp_clog.x.misc.log1, 1.283 + sctp_clog.x.misc.log2, 1.284 + sctp_clog.x.misc.log3, 1.285 + sctp_clog.x.misc.log4); 1.286 +#endif 1.287 +} 1.288 + 1.289 +void 1.290 +sctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_read *poschk, int from) 1.291 +{ 1.292 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.293 + struct sctp_cwnd_log sctp_clog; 1.294 + 1.295 + if (control == NULL) { 1.296 + SCTP_PRINTF("Gak log of NULL?\n"); 1.297 + return; 1.298 + } 1.299 + sctp_clog.x.strlog.stcb = control->stcb; 1.300 + sctp_clog.x.strlog.n_tsn = control->sinfo_tsn; 1.301 + sctp_clog.x.strlog.n_sseq = control->sinfo_ssn; 1.302 + sctp_clog.x.strlog.strm = control->sinfo_stream; 1.303 + if (poschk != NULL) { 1.304 + sctp_clog.x.strlog.e_tsn = poschk->sinfo_tsn; 1.305 + sctp_clog.x.strlog.e_sseq = poschk->sinfo_ssn; 1.306 + } else { 1.307 + sctp_clog.x.strlog.e_tsn = 0; 1.308 + sctp_clog.x.strlog.e_sseq = 0; 1.309 + } 1.310 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.311 + SCTP_LOG_EVENT_STRM, 1.312 + from, 1.313 + sctp_clog.x.misc.log1, 1.314 + sctp_clog.x.misc.log2, 1.315 + sctp_clog.x.misc.log3, 1.316 + sctp_clog.x.misc.log4); 1.317 +#endif 1.318 +} 1.319 + 1.320 +void 1.321 +sctp_log_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net, int augment, uint8_t from) 1.322 +{ 1.323 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.324 + struct sctp_cwnd_log sctp_clog; 1.325 + 1.326 + sctp_clog.x.cwnd.net = net; 1.327 + if (stcb->asoc.send_queue_cnt > 255) 1.328 + sctp_clog.x.cwnd.cnt_in_send = 255; 1.329 + else 1.330 + sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt; 1.331 + if (stcb->asoc.stream_queue_cnt > 255) 1.332 + sctp_clog.x.cwnd.cnt_in_str = 255; 1.333 + else 1.334 + sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt; 1.335 + 1.336 + if (net) { 1.337 + sctp_clog.x.cwnd.cwnd_new_value = net->cwnd; 1.338 + sctp_clog.x.cwnd.inflight = net->flight_size; 1.339 + sctp_clog.x.cwnd.pseudo_cumack = net->pseudo_cumack; 1.340 + sctp_clog.x.cwnd.meets_pseudo_cumack = net->new_pseudo_cumack; 1.341 + sctp_clog.x.cwnd.need_new_pseudo_cumack = net->find_pseudo_cumack; 1.342 + } 1.343 + if (SCTP_CWNDLOG_PRESEND == from) { 1.344 + sctp_clog.x.cwnd.meets_pseudo_cumack = stcb->asoc.peers_rwnd; 1.345 + } 1.346 + sctp_clog.x.cwnd.cwnd_augment = augment; 1.347 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.348 + SCTP_LOG_EVENT_CWND, 1.349 + from, 1.350 + sctp_clog.x.misc.log1, 1.351 + sctp_clog.x.misc.log2, 1.352 + sctp_clog.x.misc.log3, 1.353 + sctp_clog.x.misc.log4); 1.354 +#endif 1.355 +} 1.356 + 1.357 +#ifndef __APPLE__ 1.358 +void 1.359 +sctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from) 1.360 +{ 1.361 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.362 + struct sctp_cwnd_log sctp_clog; 1.363 + 1.364 + memset(&sctp_clog, 0, sizeof(sctp_clog)); 1.365 + if (inp) { 1.366 + sctp_clog.x.lock.sock = (void *) inp->sctp_socket; 1.367 + 1.368 + } else { 1.369 + sctp_clog.x.lock.sock = (void *) NULL; 1.370 + } 1.371 + sctp_clog.x.lock.inp = (void *) inp; 1.372 +#if (defined(__FreeBSD__) && __FreeBSD_version >= 503000) || (defined(__APPLE__)) 1.373 + if (stcb) { 1.374 + sctp_clog.x.lock.tcb_lock = mtx_owned(&stcb->tcb_mtx); 1.375 + } else { 1.376 + sctp_clog.x.lock.tcb_lock = SCTP_LOCK_UNKNOWN; 1.377 + } 1.378 + if (inp) { 1.379 + sctp_clog.x.lock.inp_lock = mtx_owned(&inp->inp_mtx); 1.380 + sctp_clog.x.lock.create_lock = mtx_owned(&inp->inp_create_mtx); 1.381 + } else { 1.382 + sctp_clog.x.lock.inp_lock = SCTP_LOCK_UNKNOWN; 1.383 + sctp_clog.x.lock.create_lock = SCTP_LOCK_UNKNOWN; 1.384 + } 1.385 +#if (defined(__FreeBSD__) && __FreeBSD_version <= 602000) 1.386 + sctp_clog.x.lock.info_lock = mtx_owned(&SCTP_BASE_INFO(ipi_ep_mtx)); 1.387 +#else 1.388 + sctp_clog.x.lock.info_lock = rw_wowned(&SCTP_BASE_INFO(ipi_ep_mtx)); 1.389 +#endif 1.390 + if (inp && (inp->sctp_socket)) { 1.391 + sctp_clog.x.lock.sock_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx)); 1.392 + sctp_clog.x.lock.sockrcvbuf_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx)); 1.393 + sctp_clog.x.lock.socksndbuf_lock = mtx_owned(&(inp->sctp_socket->so_snd.sb_mtx)); 1.394 + } else { 1.395 + sctp_clog.x.lock.sock_lock = SCTP_LOCK_UNKNOWN; 1.396 + sctp_clog.x.lock.sockrcvbuf_lock = SCTP_LOCK_UNKNOWN; 1.397 + sctp_clog.x.lock.socksndbuf_lock = SCTP_LOCK_UNKNOWN; 1.398 + } 1.399 +#endif 1.400 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.401 + SCTP_LOG_LOCK_EVENT, 1.402 + from, 1.403 + sctp_clog.x.misc.log1, 1.404 + sctp_clog.x.misc.log2, 1.405 + sctp_clog.x.misc.log3, 1.406 + sctp_clog.x.misc.log4); 1.407 +#endif 1.408 +} 1.409 +#endif 1.410 + 1.411 +void 1.412 +sctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *net, int error, int burst, uint8_t from) 1.413 +{ 1.414 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.415 + struct sctp_cwnd_log sctp_clog; 1.416 + 1.417 + memset(&sctp_clog, 0, sizeof(sctp_clog)); 1.418 + sctp_clog.x.cwnd.net = net; 1.419 + sctp_clog.x.cwnd.cwnd_new_value = error; 1.420 + sctp_clog.x.cwnd.inflight = net->flight_size; 1.421 + sctp_clog.x.cwnd.cwnd_augment = burst; 1.422 + if (stcb->asoc.send_queue_cnt > 255) 1.423 + sctp_clog.x.cwnd.cnt_in_send = 255; 1.424 + else 1.425 + sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt; 1.426 + if (stcb->asoc.stream_queue_cnt > 255) 1.427 + sctp_clog.x.cwnd.cnt_in_str = 255; 1.428 + else 1.429 + sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt; 1.430 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.431 + SCTP_LOG_EVENT_MAXBURST, 1.432 + from, 1.433 + sctp_clog.x.misc.log1, 1.434 + sctp_clog.x.misc.log2, 1.435 + sctp_clog.x.misc.log3, 1.436 + sctp_clog.x.misc.log4); 1.437 +#endif 1.438 +} 1.439 + 1.440 +void 1.441 +sctp_log_rwnd(uint8_t from, uint32_t peers_rwnd, uint32_t snd_size, uint32_t overhead) 1.442 +{ 1.443 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.444 + struct sctp_cwnd_log sctp_clog; 1.445 + 1.446 + sctp_clog.x.rwnd.rwnd = peers_rwnd; 1.447 + sctp_clog.x.rwnd.send_size = snd_size; 1.448 + sctp_clog.x.rwnd.overhead = overhead; 1.449 + sctp_clog.x.rwnd.new_rwnd = 0; 1.450 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.451 + SCTP_LOG_EVENT_RWND, 1.452 + from, 1.453 + sctp_clog.x.misc.log1, 1.454 + sctp_clog.x.misc.log2, 1.455 + sctp_clog.x.misc.log3, 1.456 + sctp_clog.x.misc.log4); 1.457 +#endif 1.458 +} 1.459 + 1.460 +void 1.461 +sctp_log_rwnd_set(uint8_t from, uint32_t peers_rwnd, uint32_t flight_size, uint32_t overhead, uint32_t a_rwndval) 1.462 +{ 1.463 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.464 + struct sctp_cwnd_log sctp_clog; 1.465 + 1.466 + sctp_clog.x.rwnd.rwnd = peers_rwnd; 1.467 + sctp_clog.x.rwnd.send_size = flight_size; 1.468 + sctp_clog.x.rwnd.overhead = overhead; 1.469 + sctp_clog.x.rwnd.new_rwnd = a_rwndval; 1.470 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.471 + SCTP_LOG_EVENT_RWND, 1.472 + from, 1.473 + sctp_clog.x.misc.log1, 1.474 + sctp_clog.x.misc.log2, 1.475 + sctp_clog.x.misc.log3, 1.476 + sctp_clog.x.misc.log4); 1.477 +#endif 1.478 +} 1.479 + 1.480 +void 1.481 +sctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mbcnt_q, uint32_t mbcnt) 1.482 +{ 1.483 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.484 + struct sctp_cwnd_log sctp_clog; 1.485 + 1.486 + sctp_clog.x.mbcnt.total_queue_size = total_oq; 1.487 + sctp_clog.x.mbcnt.size_change = book; 1.488 + sctp_clog.x.mbcnt.total_queue_mb_size = total_mbcnt_q; 1.489 + sctp_clog.x.mbcnt.mbcnt_change = mbcnt; 1.490 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.491 + SCTP_LOG_EVENT_MBCNT, 1.492 + from, 1.493 + sctp_clog.x.misc.log1, 1.494 + sctp_clog.x.misc.log2, 1.495 + sctp_clog.x.misc.log3, 1.496 + sctp_clog.x.misc.log4); 1.497 +#endif 1.498 +} 1.499 + 1.500 +void 1.501 +sctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d) 1.502 +{ 1.503 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.504 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.505 + SCTP_LOG_MISC_EVENT, 1.506 + from, 1.507 + a, b, c, d); 1.508 +#endif 1.509 +} 1.510 + 1.511 +void 1.512 +sctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from) 1.513 +{ 1.514 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.515 + struct sctp_cwnd_log sctp_clog; 1.516 + 1.517 + sctp_clog.x.wake.stcb = (void *)stcb; 1.518 + sctp_clog.x.wake.wake_cnt = wake_cnt; 1.519 + sctp_clog.x.wake.flight = stcb->asoc.total_flight_count; 1.520 + sctp_clog.x.wake.send_q = stcb->asoc.send_queue_cnt; 1.521 + sctp_clog.x.wake.sent_q = stcb->asoc.sent_queue_cnt; 1.522 + 1.523 + if (stcb->asoc.stream_queue_cnt < 0xff) 1.524 + sctp_clog.x.wake.stream_qcnt = (uint8_t) stcb->asoc.stream_queue_cnt; 1.525 + else 1.526 + sctp_clog.x.wake.stream_qcnt = 0xff; 1.527 + 1.528 + if (stcb->asoc.chunks_on_out_queue < 0xff) 1.529 + sctp_clog.x.wake.chunks_on_oque = (uint8_t) stcb->asoc.chunks_on_out_queue; 1.530 + else 1.531 + sctp_clog.x.wake.chunks_on_oque = 0xff; 1.532 + 1.533 + sctp_clog.x.wake.sctpflags = 0; 1.534 + /* set in the defered mode stuff */ 1.535 + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) 1.536 + sctp_clog.x.wake.sctpflags |= 1; 1.537 + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) 1.538 + sctp_clog.x.wake.sctpflags |= 2; 1.539 + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) 1.540 + sctp_clog.x.wake.sctpflags |= 4; 1.541 + /* what about the sb */ 1.542 + if (stcb->sctp_socket) { 1.543 + struct socket *so = stcb->sctp_socket; 1.544 + 1.545 + sctp_clog.x.wake.sbflags = (uint8_t)((so->so_snd.sb_flags & 0x00ff)); 1.546 + } else { 1.547 + sctp_clog.x.wake.sbflags = 0xff; 1.548 + } 1.549 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.550 + SCTP_LOG_EVENT_WAKE, 1.551 + from, 1.552 + sctp_clog.x.misc.log1, 1.553 + sctp_clog.x.misc.log2, 1.554 + sctp_clog.x.misc.log3, 1.555 + sctp_clog.x.misc.log4); 1.556 +#endif 1.557 +} 1.558 + 1.559 +void 1.560 +sctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen) 1.561 +{ 1.562 +#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF) 1.563 + struct sctp_cwnd_log sctp_clog; 1.564 + 1.565 + sctp_clog.x.blk.onsb = asoc->total_output_queue_size; 1.566 + sctp_clog.x.blk.send_sent_qcnt = (uint16_t) (asoc->send_queue_cnt + asoc->sent_queue_cnt); 1.567 + sctp_clog.x.blk.peer_rwnd = asoc->peers_rwnd; 1.568 + sctp_clog.x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt; 1.569 + sctp_clog.x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue; 1.570 + sctp_clog.x.blk.flight_size = (uint16_t) (asoc->total_flight/1024); 1.571 + sctp_clog.x.blk.sndlen = sendlen; 1.572 + SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x", 1.573 + SCTP_LOG_EVENT_BLOCK, 1.574 + from, 1.575 + sctp_clog.x.misc.log1, 1.576 + sctp_clog.x.misc.log2, 1.577 + sctp_clog.x.misc.log3, 1.578 + sctp_clog.x.misc.log4); 1.579 +#endif 1.580 +} 1.581 + 1.582 +int 1.583 +sctp_fill_stat_log(void *optval SCTP_UNUSED, size_t *optsize SCTP_UNUSED) 1.584 +{ 1.585 + /* May need to fix this if ktrdump does not work */ 1.586 + return (0); 1.587 +} 1.588 + 1.589 +#ifdef SCTP_AUDITING_ENABLED 1.590 +uint8_t sctp_audit_data[SCTP_AUDIT_SIZE][2]; 1.591 +static int sctp_audit_indx = 0; 1.592 + 1.593 +static 1.594 +void 1.595 +sctp_print_audit_report(void) 1.596 +{ 1.597 + int i; 1.598 + int cnt; 1.599 + 1.600 + cnt = 0; 1.601 + for (i = sctp_audit_indx; i < SCTP_AUDIT_SIZE; i++) { 1.602 + if ((sctp_audit_data[i][0] == 0xe0) && 1.603 + (sctp_audit_data[i][1] == 0x01)) { 1.604 + cnt = 0; 1.605 + SCTP_PRINTF("\n"); 1.606 + } else if (sctp_audit_data[i][0] == 0xf0) { 1.607 + cnt = 0; 1.608 + SCTP_PRINTF("\n"); 1.609 + } else if ((sctp_audit_data[i][0] == 0xc0) && 1.610 + (sctp_audit_data[i][1] == 0x01)) { 1.611 + SCTP_PRINTF("\n"); 1.612 + cnt = 0; 1.613 + } 1.614 + SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0], 1.615 + (uint32_t) sctp_audit_data[i][1]); 1.616 + cnt++; 1.617 + if ((cnt % 14) == 0) 1.618 + SCTP_PRINTF("\n"); 1.619 + } 1.620 + for (i = 0; i < sctp_audit_indx; i++) { 1.621 + if ((sctp_audit_data[i][0] == 0xe0) && 1.622 + (sctp_audit_data[i][1] == 0x01)) { 1.623 + cnt = 0; 1.624 + SCTP_PRINTF("\n"); 1.625 + } else if (sctp_audit_data[i][0] == 0xf0) { 1.626 + cnt = 0; 1.627 + SCTP_PRINTF("\n"); 1.628 + } else if ((sctp_audit_data[i][0] == 0xc0) && 1.629 + (sctp_audit_data[i][1] == 0x01)) { 1.630 + SCTP_PRINTF("\n"); 1.631 + cnt = 0; 1.632 + } 1.633 + SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0], 1.634 + (uint32_t) sctp_audit_data[i][1]); 1.635 + cnt++; 1.636 + if ((cnt % 14) == 0) 1.637 + SCTP_PRINTF("\n"); 1.638 + } 1.639 + SCTP_PRINTF("\n"); 1.640 +} 1.641 + 1.642 +void 1.643 +sctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1.644 + struct sctp_nets *net) 1.645 +{ 1.646 + int resend_cnt, tot_out, rep, tot_book_cnt; 1.647 + struct sctp_nets *lnet; 1.648 + struct sctp_tmit_chunk *chk; 1.649 + 1.650 + sctp_audit_data[sctp_audit_indx][0] = 0xAA; 1.651 + sctp_audit_data[sctp_audit_indx][1] = 0x000000ff & from; 1.652 + sctp_audit_indx++; 1.653 + if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 1.654 + sctp_audit_indx = 0; 1.655 + } 1.656 + if (inp == NULL) { 1.657 + sctp_audit_data[sctp_audit_indx][0] = 0xAF; 1.658 + sctp_audit_data[sctp_audit_indx][1] = 0x01; 1.659 + sctp_audit_indx++; 1.660 + if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 1.661 + sctp_audit_indx = 0; 1.662 + } 1.663 + return; 1.664 + } 1.665 + if (stcb == NULL) { 1.666 + sctp_audit_data[sctp_audit_indx][0] = 0xAF; 1.667 + sctp_audit_data[sctp_audit_indx][1] = 0x02; 1.668 + sctp_audit_indx++; 1.669 + if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 1.670 + sctp_audit_indx = 0; 1.671 + } 1.672 + return; 1.673 + } 1.674 + sctp_audit_data[sctp_audit_indx][0] = 0xA1; 1.675 + sctp_audit_data[sctp_audit_indx][1] = 1.676 + (0x000000ff & stcb->asoc.sent_queue_retran_cnt); 1.677 + sctp_audit_indx++; 1.678 + if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 1.679 + sctp_audit_indx = 0; 1.680 + } 1.681 + rep = 0; 1.682 + tot_book_cnt = 0; 1.683 + resend_cnt = tot_out = 0; 1.684 + TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 1.685 + if (chk->sent == SCTP_DATAGRAM_RESEND) { 1.686 + resend_cnt++; 1.687 + } else if (chk->sent < SCTP_DATAGRAM_RESEND) { 1.688 + tot_out += chk->book_size; 1.689 + tot_book_cnt++; 1.690 + } 1.691 + } 1.692 + if (resend_cnt != stcb->asoc.sent_queue_retran_cnt) { 1.693 + sctp_audit_data[sctp_audit_indx][0] = 0xAF; 1.694 + sctp_audit_data[sctp_audit_indx][1] = 0xA1; 1.695 + sctp_audit_indx++; 1.696 + if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 1.697 + sctp_audit_indx = 0; 1.698 + } 1.699 + SCTP_PRINTF("resend_cnt:%d asoc-tot:%d\n", 1.700 + resend_cnt, stcb->asoc.sent_queue_retran_cnt); 1.701 + rep = 1; 1.702 + stcb->asoc.sent_queue_retran_cnt = resend_cnt; 1.703 + sctp_audit_data[sctp_audit_indx][0] = 0xA2; 1.704 + sctp_audit_data[sctp_audit_indx][1] = 1.705 + (0x000000ff & stcb->asoc.sent_queue_retran_cnt); 1.706 + sctp_audit_indx++; 1.707 + if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 1.708 + sctp_audit_indx = 0; 1.709 + } 1.710 + } 1.711 + if (tot_out != stcb->asoc.total_flight) { 1.712 + sctp_audit_data[sctp_audit_indx][0] = 0xAF; 1.713 + sctp_audit_data[sctp_audit_indx][1] = 0xA2; 1.714 + sctp_audit_indx++; 1.715 + if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 1.716 + sctp_audit_indx = 0; 1.717 + } 1.718 + rep = 1; 1.719 + SCTP_PRINTF("tot_flt:%d asoc_tot:%d\n", tot_out, 1.720 + (int)stcb->asoc.total_flight); 1.721 + stcb->asoc.total_flight = tot_out; 1.722 + } 1.723 + if (tot_book_cnt != stcb->asoc.total_flight_count) { 1.724 + sctp_audit_data[sctp_audit_indx][0] = 0xAF; 1.725 + sctp_audit_data[sctp_audit_indx][1] = 0xA5; 1.726 + sctp_audit_indx++; 1.727 + if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 1.728 + sctp_audit_indx = 0; 1.729 + } 1.730 + rep = 1; 1.731 + SCTP_PRINTF("tot_flt_book:%d\n", tot_book_cnt); 1.732 + 1.733 + stcb->asoc.total_flight_count = tot_book_cnt; 1.734 + } 1.735 + tot_out = 0; 1.736 + TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) { 1.737 + tot_out += lnet->flight_size; 1.738 + } 1.739 + if (tot_out != stcb->asoc.total_flight) { 1.740 + sctp_audit_data[sctp_audit_indx][0] = 0xAF; 1.741 + sctp_audit_data[sctp_audit_indx][1] = 0xA3; 1.742 + sctp_audit_indx++; 1.743 + if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 1.744 + sctp_audit_indx = 0; 1.745 + } 1.746 + rep = 1; 1.747 + SCTP_PRINTF("real flight:%d net total was %d\n", 1.748 + stcb->asoc.total_flight, tot_out); 1.749 + /* now corrective action */ 1.750 + TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) { 1.751 + 1.752 + tot_out = 0; 1.753 + TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) { 1.754 + if ((chk->whoTo == lnet) && 1.755 + (chk->sent < SCTP_DATAGRAM_RESEND)) { 1.756 + tot_out += chk->book_size; 1.757 + } 1.758 + } 1.759 + if (lnet->flight_size != tot_out) { 1.760 + SCTP_PRINTF("net:%p flight was %d corrected to %d\n", 1.761 + (void *)lnet, lnet->flight_size, 1.762 + tot_out); 1.763 + lnet->flight_size = tot_out; 1.764 + } 1.765 + } 1.766 + } 1.767 + if (rep) { 1.768 + sctp_print_audit_report(); 1.769 + } 1.770 +} 1.771 + 1.772 +void 1.773 +sctp_audit_log(uint8_t ev, uint8_t fd) 1.774 +{ 1.775 + 1.776 + sctp_audit_data[sctp_audit_indx][0] = ev; 1.777 + sctp_audit_data[sctp_audit_indx][1] = fd; 1.778 + sctp_audit_indx++; 1.779 + if (sctp_audit_indx >= SCTP_AUDIT_SIZE) { 1.780 + sctp_audit_indx = 0; 1.781 + } 1.782 +} 1.783 + 1.784 +#endif 1.785 + 1.786 +/* 1.787 + * sctp_stop_timers_for_shutdown() should be called 1.788 + * when entering the SHUTDOWN_SENT or SHUTDOWN_ACK_SENT 1.789 + * state to make sure that all timers are stopped. 1.790 + */ 1.791 +void 1.792 +sctp_stop_timers_for_shutdown(struct sctp_tcb *stcb) 1.793 +{ 1.794 + struct sctp_association *asoc; 1.795 + struct sctp_nets *net; 1.796 + 1.797 + asoc = &stcb->asoc; 1.798 + 1.799 + (void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer); 1.800 + (void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer); 1.801 + (void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer); 1.802 + (void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer); 1.803 + (void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer); 1.804 + TAILQ_FOREACH(net, &asoc->nets, sctp_next) { 1.805 + (void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer); 1.806 + (void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer); 1.807 + } 1.808 +} 1.809 + 1.810 +/* 1.811 + * a list of sizes based on typical mtu's, used only if next hop size not 1.812 + * returned. 1.813 + */ 1.814 +static uint32_t sctp_mtu_sizes[] = { 1.815 + 68, 1.816 + 296, 1.817 + 508, 1.818 + 512, 1.819 + 544, 1.820 + 576, 1.821 + 1006, 1.822 + 1492, 1.823 + 1500, 1.824 + 1536, 1.825 + 2002, 1.826 + 2048, 1.827 + 4352, 1.828 + 4464, 1.829 + 8166, 1.830 + 17914, 1.831 + 32000, 1.832 + 65535 1.833 +}; 1.834 + 1.835 +/* 1.836 + * Return the largest MTU smaller than val. If there is no 1.837 + * entry, just return val. 1.838 + */ 1.839 +uint32_t 1.840 +sctp_get_prev_mtu(uint32_t val) 1.841 +{ 1.842 + uint32_t i; 1.843 + 1.844 + if (val <= sctp_mtu_sizes[0]) { 1.845 + return (val); 1.846 + } 1.847 + for (i = 1; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) { 1.848 + if (val <= sctp_mtu_sizes[i]) { 1.849 + break; 1.850 + } 1.851 + } 1.852 + return (sctp_mtu_sizes[i - 1]); 1.853 +} 1.854 + 1.855 +/* 1.856 + * Return the smallest MTU larger than val. If there is no 1.857 + * entry, just return val. 1.858 + */ 1.859 +uint32_t 1.860 +sctp_get_next_mtu(uint32_t val) 1.861 +{ 1.862 + /* select another MTU that is just bigger than this one */ 1.863 + uint32_t i; 1.864 + 1.865 + for (i = 0; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) { 1.866 + if (val < sctp_mtu_sizes[i]) { 1.867 + return (sctp_mtu_sizes[i]); 1.868 + } 1.869 + } 1.870 + return (val); 1.871 +} 1.872 + 1.873 +void 1.874 +sctp_fill_random_store(struct sctp_pcb *m) 1.875 +{ 1.876 + /* 1.877 + * Here we use the MD5/SHA-1 to hash with our good randomNumbers and 1.878 + * our counter. The result becomes our good random numbers and we 1.879 + * then setup to give these out. Note that we do no locking to 1.880 + * protect this. This is ok, since if competing folks call this we 1.881 + * will get more gobbled gook in the random store which is what we 1.882 + * want. There is a danger that two guys will use the same random 1.883 + * numbers, but thats ok too since that is random as well :-> 1.884 + */ 1.885 + m->store_at = 0; 1.886 + (void)sctp_hmac(SCTP_HMAC, (uint8_t *)m->random_numbers, 1.887 + sizeof(m->random_numbers), (uint8_t *)&m->random_counter, 1.888 + sizeof(m->random_counter), (uint8_t *)m->random_store); 1.889 + m->random_counter++; 1.890 +} 1.891 + 1.892 +uint32_t 1.893 +sctp_select_initial_TSN(struct sctp_pcb *inp) 1.894 +{ 1.895 + /* 1.896 + * A true implementation should use random selection process to get 1.897 + * the initial stream sequence number, using RFC1750 as a good 1.898 + * guideline 1.899 + */ 1.900 + uint32_t x, *xp; 1.901 + uint8_t *p; 1.902 + int store_at, new_store; 1.903 + 1.904 + if (inp->initial_sequence_debug != 0) { 1.905 + uint32_t ret; 1.906 + 1.907 + ret = inp->initial_sequence_debug; 1.908 + inp->initial_sequence_debug++; 1.909 + return (ret); 1.910 + } 1.911 + retry: 1.912 + store_at = inp->store_at; 1.913 + new_store = store_at + sizeof(uint32_t); 1.914 + if (new_store >= (SCTP_SIGNATURE_SIZE-3)) { 1.915 + new_store = 0; 1.916 + } 1.917 + if (!atomic_cmpset_int(&inp->store_at, store_at, new_store)) { 1.918 + goto retry; 1.919 + } 1.920 + if (new_store == 0) { 1.921 + /* Refill the random store */ 1.922 + sctp_fill_random_store(inp); 1.923 + } 1.924 + p = &inp->random_store[store_at]; 1.925 + xp = (uint32_t *)p; 1.926 + x = *xp; 1.927 + return (x); 1.928 +} 1.929 + 1.930 +uint32_t 1.931 +sctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int check) 1.932 +{ 1.933 + uint32_t x; 1.934 + struct timeval now; 1.935 + 1.936 + if (check) { 1.937 + (void)SCTP_GETTIME_TIMEVAL(&now); 1.938 + } 1.939 + for (;;) { 1.940 + x = sctp_select_initial_TSN(&inp->sctp_ep); 1.941 + if (x == 0) { 1.942 + /* we never use 0 */ 1.943 + continue; 1.944 + } 1.945 + if (!check || sctp_is_vtag_good(x, lport, rport, &now)) { 1.946 + break; 1.947 + } 1.948 + } 1.949 + return (x); 1.950 +} 1.951 + 1.952 +int 1.953 +sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1.954 + uint32_t override_tag, uint32_t vrf_id) 1.955 +{ 1.956 + struct sctp_association *asoc; 1.957 + /* 1.958 + * Anything set to zero is taken care of by the allocation routine's 1.959 + * bzero 1.960 + */ 1.961 + 1.962 + /* 1.963 + * Up front select what scoping to apply on addresses I tell my peer 1.964 + * Not sure what to do with these right now, we will need to come up 1.965 + * with a way to set them. We may need to pass them through from the 1.966 + * caller in the sctp_aloc_assoc() function. 1.967 + */ 1.968 + int i; 1.969 + 1.970 + asoc = &stcb->asoc; 1.971 + /* init all variables to a known value. */ 1.972 + SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE); 1.973 + asoc->max_burst = inp->sctp_ep.max_burst; 1.974 + asoc->fr_max_burst = inp->sctp_ep.fr_max_burst; 1.975 + asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]); 1.976 + asoc->cookie_life = inp->sctp_ep.def_cookie_life; 1.977 + asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off; 1.978 + asoc->ecn_allowed = inp->sctp_ecn_enable; 1.979 + asoc->sctp_nr_sack_on_off = (uint8_t)SCTP_BASE_SYSCTL(sctp_nr_sack_on_off); 1.980 + asoc->sctp_cmt_pf = (uint8_t)0; 1.981 + asoc->sctp_frag_point = inp->sctp_frag_point; 1.982 + asoc->sctp_features = inp->sctp_features; 1.983 + asoc->default_dscp = inp->sctp_ep.default_dscp; 1.984 +#ifdef INET6 1.985 + if (inp->sctp_ep.default_flowlabel) { 1.986 + asoc->default_flowlabel = inp->sctp_ep.default_flowlabel; 1.987 + } else { 1.988 + if (inp->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) { 1.989 + asoc->default_flowlabel = sctp_select_initial_TSN(&inp->sctp_ep); 1.990 + asoc->default_flowlabel &= 0x000fffff; 1.991 + asoc->default_flowlabel |= 0x80000000; 1.992 + } else { 1.993 + asoc->default_flowlabel = 0; 1.994 + } 1.995 + } 1.996 +#endif 1.997 + asoc->sb_send_resv = 0; 1.998 + if (override_tag) { 1.999 + asoc->my_vtag = override_tag; 1.1000 + } else { 1.1001 + asoc->my_vtag = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 1); 1.1002 + } 1.1003 + /* Get the nonce tags */ 1.1004 + asoc->my_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0); 1.1005 + asoc->peer_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0); 1.1006 + asoc->vrf_id = vrf_id; 1.1007 + 1.1008 +#ifdef SCTP_ASOCLOG_OF_TSNS 1.1009 + asoc->tsn_in_at = 0; 1.1010 + asoc->tsn_out_at = 0; 1.1011 + asoc->tsn_in_wrapped = 0; 1.1012 + asoc->tsn_out_wrapped = 0; 1.1013 + asoc->cumack_log_at = 0; 1.1014 + asoc->cumack_log_atsnt = 0; 1.1015 +#endif 1.1016 +#ifdef SCTP_FS_SPEC_LOG 1.1017 + asoc->fs_index = 0; 1.1018 +#endif 1.1019 + asoc->refcnt = 0; 1.1020 + asoc->assoc_up_sent = 0; 1.1021 + asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq = 1.1022 + sctp_select_initial_TSN(&inp->sctp_ep); 1.1023 + asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1; 1.1024 + /* we are optimisitic here */ 1.1025 + asoc->peer_supports_pktdrop = 1; 1.1026 + asoc->peer_supports_nat = 0; 1.1027 + asoc->sent_queue_retran_cnt = 0; 1.1028 + 1.1029 + /* for CMT */ 1.1030 + asoc->last_net_cmt_send_started = NULL; 1.1031 + 1.1032 + /* This will need to be adjusted */ 1.1033 + asoc->last_acked_seq = asoc->init_seq_number - 1; 1.1034 + asoc->advanced_peer_ack_point = asoc->last_acked_seq; 1.1035 + asoc->asconf_seq_in = asoc->last_acked_seq; 1.1036 + 1.1037 + /* here we are different, we hold the next one we expect */ 1.1038 + asoc->str_reset_seq_in = asoc->last_acked_seq + 1; 1.1039 + 1.1040 + asoc->initial_init_rto_max = inp->sctp_ep.initial_init_rto_max; 1.1041 + asoc->initial_rto = inp->sctp_ep.initial_rto; 1.1042 + 1.1043 + asoc->max_init_times = inp->sctp_ep.max_init_times; 1.1044 + asoc->max_send_times = inp->sctp_ep.max_send_times; 1.1045 + asoc->def_net_failure = inp->sctp_ep.def_net_failure; 1.1046 + asoc->def_net_pf_threshold = inp->sctp_ep.def_net_pf_threshold; 1.1047 + asoc->free_chunk_cnt = 0; 1.1048 + 1.1049 + asoc->iam_blocking = 0; 1.1050 + asoc->context = inp->sctp_context; 1.1051 + asoc->local_strreset_support = inp->local_strreset_support; 1.1052 + asoc->def_send = inp->def_send; 1.1053 + asoc->delayed_ack = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]); 1.1054 + asoc->sack_freq = inp->sctp_ep.sctp_sack_freq; 1.1055 + asoc->pr_sctp_cnt = 0; 1.1056 + asoc->total_output_queue_size = 0; 1.1057 + 1.1058 + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 1.1059 + asoc->scope.ipv6_addr_legal = 1; 1.1060 + if (SCTP_IPV6_V6ONLY(inp) == 0) { 1.1061 + asoc->scope.ipv4_addr_legal = 1; 1.1062 + } else { 1.1063 + asoc->scope.ipv4_addr_legal = 0; 1.1064 + } 1.1065 +#if defined(__Userspace__) 1.1066 + asoc->scope.conn_addr_legal = 0; 1.1067 +#endif 1.1068 + } else { 1.1069 + asoc->scope.ipv6_addr_legal = 0; 1.1070 +#if defined(__Userspace__) 1.1071 + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) { 1.1072 + asoc->scope.conn_addr_legal = 1; 1.1073 + asoc->scope.ipv4_addr_legal = 0; 1.1074 + } else { 1.1075 + asoc->scope.conn_addr_legal = 0; 1.1076 + asoc->scope.ipv4_addr_legal = 1; 1.1077 + } 1.1078 +#else 1.1079 + asoc->scope.ipv4_addr_legal = 1; 1.1080 +#endif 1.1081 + } 1.1082 + 1.1083 + asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND); 1.1084 + asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(inp->sctp_socket); 1.1085 + 1.1086 + asoc->smallest_mtu = inp->sctp_frag_point; 1.1087 + asoc->minrto = inp->sctp_ep.sctp_minrto; 1.1088 + asoc->maxrto = inp->sctp_ep.sctp_maxrto; 1.1089 + 1.1090 + asoc->locked_on_sending = NULL; 1.1091 + asoc->stream_locked_on = 0; 1.1092 + asoc->ecn_echo_cnt_onq = 0; 1.1093 + asoc->stream_locked = 0; 1.1094 + 1.1095 + asoc->send_sack = 1; 1.1096 + 1.1097 + LIST_INIT(&asoc->sctp_restricted_addrs); 1.1098 + 1.1099 + TAILQ_INIT(&asoc->nets); 1.1100 + TAILQ_INIT(&asoc->pending_reply_queue); 1.1101 + TAILQ_INIT(&asoc->asconf_ack_sent); 1.1102 + /* Setup to fill the hb random cache at first HB */ 1.1103 + asoc->hb_random_idx = 4; 1.1104 + 1.1105 + asoc->sctp_autoclose_ticks = inp->sctp_ep.auto_close_time; 1.1106 + 1.1107 + stcb->asoc.congestion_control_module = inp->sctp_ep.sctp_default_cc_module; 1.1108 + stcb->asoc.cc_functions = sctp_cc_functions[inp->sctp_ep.sctp_default_cc_module]; 1.1109 + 1.1110 + stcb->asoc.stream_scheduling_module = inp->sctp_ep.sctp_default_ss_module; 1.1111 + stcb->asoc.ss_functions = sctp_ss_functions[inp->sctp_ep.sctp_default_ss_module]; 1.1112 + 1.1113 + /* 1.1114 + * Now the stream parameters, here we allocate space for all streams 1.1115 + * that we request by default. 1.1116 + */ 1.1117 + asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams = 1.1118 + inp->sctp_ep.pre_open_stream_count; 1.1119 + SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *, 1.1120 + asoc->streamoutcnt * sizeof(struct sctp_stream_out), 1.1121 + SCTP_M_STRMO); 1.1122 + if (asoc->strmout == NULL) { 1.1123 + /* big trouble no memory */ 1.1124 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 1.1125 + return (ENOMEM); 1.1126 + } 1.1127 + for (i = 0; i < asoc->streamoutcnt; i++) { 1.1128 + /* 1.1129 + * inbound side must be set to 0xffff, also NOTE when we get 1.1130 + * the INIT-ACK back (for INIT sender) we MUST reduce the 1.1131 + * count (streamoutcnt) but first check if we sent to any of 1.1132 + * the upper streams that were dropped (if some were). Those 1.1133 + * that were dropped must be notified to the upper layer as 1.1134 + * failed to send. 1.1135 + */ 1.1136 + asoc->strmout[i].next_sequence_send = 0x0; 1.1137 + TAILQ_INIT(&asoc->strmout[i].outqueue); 1.1138 + asoc->strmout[i].chunks_on_queues = 0; 1.1139 + asoc->strmout[i].stream_no = i; 1.1140 + asoc->strmout[i].last_msg_incomplete = 0; 1.1141 + asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL); 1.1142 + } 1.1143 + asoc->ss_functions.sctp_ss_init(stcb, asoc, 0); 1.1144 + 1.1145 + /* Now the mapping array */ 1.1146 + asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY; 1.1147 + SCTP_MALLOC(asoc->mapping_array, uint8_t *, asoc->mapping_array_size, 1.1148 + SCTP_M_MAP); 1.1149 + if (asoc->mapping_array == NULL) { 1.1150 + SCTP_FREE(asoc->strmout, SCTP_M_STRMO); 1.1151 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 1.1152 + return (ENOMEM); 1.1153 + } 1.1154 + memset(asoc->mapping_array, 0, asoc->mapping_array_size); 1.1155 + SCTP_MALLOC(asoc->nr_mapping_array, uint8_t *, asoc->mapping_array_size, 1.1156 + SCTP_M_MAP); 1.1157 + if (asoc->nr_mapping_array == NULL) { 1.1158 + SCTP_FREE(asoc->strmout, SCTP_M_STRMO); 1.1159 + SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); 1.1160 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 1.1161 + return (ENOMEM); 1.1162 + } 1.1163 + memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size); 1.1164 + 1.1165 + /* Now the init of the other outqueues */ 1.1166 + TAILQ_INIT(&asoc->free_chunks); 1.1167 + TAILQ_INIT(&asoc->control_send_queue); 1.1168 + TAILQ_INIT(&asoc->asconf_send_queue); 1.1169 + TAILQ_INIT(&asoc->send_queue); 1.1170 + TAILQ_INIT(&asoc->sent_queue); 1.1171 + TAILQ_INIT(&asoc->reasmqueue); 1.1172 + TAILQ_INIT(&asoc->resetHead); 1.1173 + asoc->max_inbound_streams = inp->sctp_ep.max_open_streams_intome; 1.1174 + TAILQ_INIT(&asoc->asconf_queue); 1.1175 + /* authentication fields */ 1.1176 + asoc->authinfo.random = NULL; 1.1177 + asoc->authinfo.active_keyid = 0; 1.1178 + asoc->authinfo.assoc_key = NULL; 1.1179 + asoc->authinfo.assoc_keyid = 0; 1.1180 + asoc->authinfo.recv_key = NULL; 1.1181 + asoc->authinfo.recv_keyid = 0; 1.1182 + LIST_INIT(&asoc->shared_keys); 1.1183 + asoc->marked_retrans = 0; 1.1184 + asoc->port = inp->sctp_ep.port; 1.1185 + asoc->timoinit = 0; 1.1186 + asoc->timodata = 0; 1.1187 + asoc->timosack = 0; 1.1188 + asoc->timoshutdown = 0; 1.1189 + asoc->timoheartbeat = 0; 1.1190 + asoc->timocookie = 0; 1.1191 + asoc->timoshutdownack = 0; 1.1192 + (void)SCTP_GETTIME_TIMEVAL(&asoc->start_time); 1.1193 + asoc->discontinuity_time = asoc->start_time; 1.1194 + /* sa_ignore MEMLEAK {memory is put in the assoc mapping array and freed later when 1.1195 + * the association is freed. 1.1196 + */ 1.1197 + return (0); 1.1198 +} 1.1199 + 1.1200 +void 1.1201 +sctp_print_mapping_array(struct sctp_association *asoc) 1.1202 +{ 1.1203 + unsigned int i, limit; 1.1204 + 1.1205 + SCTP_PRINTF("Mapping array size: %d, baseTSN: %8.8x, cumAck: %8.8x, highestTSN: (%8.8x, %8.8x).\n", 1.1206 + asoc->mapping_array_size, 1.1207 + asoc->mapping_array_base_tsn, 1.1208 + asoc->cumulative_tsn, 1.1209 + asoc->highest_tsn_inside_map, 1.1210 + asoc->highest_tsn_inside_nr_map); 1.1211 + for (limit = asoc->mapping_array_size; limit > 1; limit--) { 1.1212 + if (asoc->mapping_array[limit - 1] != 0) { 1.1213 + break; 1.1214 + } 1.1215 + } 1.1216 + SCTP_PRINTF("Renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit); 1.1217 + for (i = 0; i < limit; i++) { 1.1218 + SCTP_PRINTF("%2.2x%c", asoc->mapping_array[i], ((i + 1) % 16) ? ' ' : '\n'); 1.1219 + } 1.1220 + if (limit % 16) 1.1221 + SCTP_PRINTF("\n"); 1.1222 + for (limit = asoc->mapping_array_size; limit > 1; limit--) { 1.1223 + if (asoc->nr_mapping_array[limit - 1]) { 1.1224 + break; 1.1225 + } 1.1226 + } 1.1227 + SCTP_PRINTF("Non renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit); 1.1228 + for (i = 0; i < limit; i++) { 1.1229 + SCTP_PRINTF("%2.2x%c", asoc->nr_mapping_array[i], ((i + 1) % 16) ? ' ': '\n'); 1.1230 + } 1.1231 + if (limit % 16) 1.1232 + SCTP_PRINTF("\n"); 1.1233 +} 1.1234 + 1.1235 +int 1.1236 +sctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed) 1.1237 +{ 1.1238 + /* mapping array needs to grow */ 1.1239 + uint8_t *new_array1, *new_array2; 1.1240 + uint32_t new_size; 1.1241 + 1.1242 + new_size = asoc->mapping_array_size + ((needed+7)/8 + SCTP_MAPPING_ARRAY_INCR); 1.1243 + SCTP_MALLOC(new_array1, uint8_t *, new_size, SCTP_M_MAP); 1.1244 + SCTP_MALLOC(new_array2, uint8_t *, new_size, SCTP_M_MAP); 1.1245 + if ((new_array1 == NULL) || (new_array2 == NULL)) { 1.1246 + /* can't get more, forget it */ 1.1247 + SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n", new_size); 1.1248 + if (new_array1) { 1.1249 + SCTP_FREE(new_array1, SCTP_M_MAP); 1.1250 + } 1.1251 + if (new_array2) { 1.1252 + SCTP_FREE(new_array2, SCTP_M_MAP); 1.1253 + } 1.1254 + return (-1); 1.1255 + } 1.1256 + memset(new_array1, 0, new_size); 1.1257 + memset(new_array2, 0, new_size); 1.1258 + memcpy(new_array1, asoc->mapping_array, asoc->mapping_array_size); 1.1259 + memcpy(new_array2, asoc->nr_mapping_array, asoc->mapping_array_size); 1.1260 + SCTP_FREE(asoc->mapping_array, SCTP_M_MAP); 1.1261 + SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP); 1.1262 + asoc->mapping_array = new_array1; 1.1263 + asoc->nr_mapping_array = new_array2; 1.1264 + asoc->mapping_array_size = new_size; 1.1265 + return (0); 1.1266 +} 1.1267 + 1.1268 + 1.1269 +static void 1.1270 +sctp_iterator_work(struct sctp_iterator *it) 1.1271 +{ 1.1272 + int iteration_count = 0; 1.1273 + int inp_skip = 0; 1.1274 + int first_in = 1; 1.1275 + struct sctp_inpcb *tinp; 1.1276 + 1.1277 + SCTP_INP_INFO_RLOCK(); 1.1278 + SCTP_ITERATOR_LOCK(); 1.1279 + if (it->inp) { 1.1280 + SCTP_INP_RLOCK(it->inp); 1.1281 + SCTP_INP_DECR_REF(it->inp); 1.1282 + } 1.1283 + if (it->inp == NULL) { 1.1284 + /* iterator is complete */ 1.1285 +done_with_iterator: 1.1286 + SCTP_ITERATOR_UNLOCK(); 1.1287 + SCTP_INP_INFO_RUNLOCK(); 1.1288 + if (it->function_atend != NULL) { 1.1289 + (*it->function_atend) (it->pointer, it->val); 1.1290 + } 1.1291 + SCTP_FREE(it, SCTP_M_ITER); 1.1292 + return; 1.1293 + } 1.1294 +select_a_new_ep: 1.1295 + if (first_in) { 1.1296 + first_in = 0; 1.1297 + } else { 1.1298 + SCTP_INP_RLOCK(it->inp); 1.1299 + } 1.1300 + while (((it->pcb_flags) && 1.1301 + ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) || 1.1302 + ((it->pcb_features) && 1.1303 + ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) { 1.1304 + /* endpoint flags or features don't match, so keep looking */ 1.1305 + if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 1.1306 + SCTP_INP_RUNLOCK(it->inp); 1.1307 + goto done_with_iterator; 1.1308 + } 1.1309 + tinp = it->inp; 1.1310 + it->inp = LIST_NEXT(it->inp, sctp_list); 1.1311 + SCTP_INP_RUNLOCK(tinp); 1.1312 + if (it->inp == NULL) { 1.1313 + goto done_with_iterator; 1.1314 + } 1.1315 + SCTP_INP_RLOCK(it->inp); 1.1316 + } 1.1317 + /* now go through each assoc which is in the desired state */ 1.1318 + if (it->done_current_ep == 0) { 1.1319 + if (it->function_inp != NULL) 1.1320 + inp_skip = (*it->function_inp)(it->inp, it->pointer, it->val); 1.1321 + it->done_current_ep = 1; 1.1322 + } 1.1323 + if (it->stcb == NULL) { 1.1324 + /* run the per instance function */ 1.1325 + it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list); 1.1326 + } 1.1327 + if ((inp_skip) || it->stcb == NULL) { 1.1328 + if (it->function_inp_end != NULL) { 1.1329 + inp_skip = (*it->function_inp_end)(it->inp, 1.1330 + it->pointer, 1.1331 + it->val); 1.1332 + } 1.1333 + SCTP_INP_RUNLOCK(it->inp); 1.1334 + goto no_stcb; 1.1335 + } 1.1336 + while (it->stcb) { 1.1337 + SCTP_TCB_LOCK(it->stcb); 1.1338 + if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) { 1.1339 + /* not in the right state... keep looking */ 1.1340 + SCTP_TCB_UNLOCK(it->stcb); 1.1341 + goto next_assoc; 1.1342 + } 1.1343 + /* see if we have limited out the iterator loop */ 1.1344 + iteration_count++; 1.1345 + if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) { 1.1346 + /* Pause to let others grab the lock */ 1.1347 + atomic_add_int(&it->stcb->asoc.refcnt, 1); 1.1348 + SCTP_TCB_UNLOCK(it->stcb); 1.1349 + SCTP_INP_INCR_REF(it->inp); 1.1350 + SCTP_INP_RUNLOCK(it->inp); 1.1351 + SCTP_ITERATOR_UNLOCK(); 1.1352 + SCTP_INP_INFO_RUNLOCK(); 1.1353 + SCTP_INP_INFO_RLOCK(); 1.1354 + SCTP_ITERATOR_LOCK(); 1.1355 + if (sctp_it_ctl.iterator_flags) { 1.1356 + /* We won't be staying here */ 1.1357 + SCTP_INP_DECR_REF(it->inp); 1.1358 + atomic_add_int(&it->stcb->asoc.refcnt, -1); 1.1359 +#if !defined(__FreeBSD__) 1.1360 + if (sctp_it_ctl.iterator_flags & 1.1361 + SCTP_ITERATOR_MUST_EXIT) { 1.1362 + goto done_with_iterator; 1.1363 + } 1.1364 +#endif 1.1365 + if (sctp_it_ctl.iterator_flags & 1.1366 + SCTP_ITERATOR_STOP_CUR_IT) { 1.1367 + sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_IT; 1.1368 + goto done_with_iterator; 1.1369 + } 1.1370 + if (sctp_it_ctl.iterator_flags & 1.1371 + SCTP_ITERATOR_STOP_CUR_INP) { 1.1372 + sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_INP; 1.1373 + goto no_stcb; 1.1374 + } 1.1375 + /* If we reach here huh? */ 1.1376 + SCTP_PRINTF("Unknown it ctl flag %x\n", 1.1377 + sctp_it_ctl.iterator_flags); 1.1378 + sctp_it_ctl.iterator_flags = 0; 1.1379 + } 1.1380 + SCTP_INP_RLOCK(it->inp); 1.1381 + SCTP_INP_DECR_REF(it->inp); 1.1382 + SCTP_TCB_LOCK(it->stcb); 1.1383 + atomic_add_int(&it->stcb->asoc.refcnt, -1); 1.1384 + iteration_count = 0; 1.1385 + } 1.1386 + 1.1387 + /* run function on this one */ 1.1388 + (*it->function_assoc)(it->inp, it->stcb, it->pointer, it->val); 1.1389 + 1.1390 + /* 1.1391 + * we lie here, it really needs to have its own type but 1.1392 + * first I must verify that this won't effect things :-0 1.1393 + */ 1.1394 + if (it->no_chunk_output == 0) 1.1395 + sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1.1396 + 1.1397 + SCTP_TCB_UNLOCK(it->stcb); 1.1398 + next_assoc: 1.1399 + it->stcb = LIST_NEXT(it->stcb, sctp_tcblist); 1.1400 + if (it->stcb == NULL) { 1.1401 + /* Run last function */ 1.1402 + if (it->function_inp_end != NULL) { 1.1403 + inp_skip = (*it->function_inp_end)(it->inp, 1.1404 + it->pointer, 1.1405 + it->val); 1.1406 + } 1.1407 + } 1.1408 + } 1.1409 + SCTP_INP_RUNLOCK(it->inp); 1.1410 + no_stcb: 1.1411 + /* done with all assocs on this endpoint, move on to next endpoint */ 1.1412 + it->done_current_ep = 0; 1.1413 + if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) { 1.1414 + it->inp = NULL; 1.1415 + } else { 1.1416 + it->inp = LIST_NEXT(it->inp, sctp_list); 1.1417 + } 1.1418 + if (it->inp == NULL) { 1.1419 + goto done_with_iterator; 1.1420 + } 1.1421 + goto select_a_new_ep; 1.1422 +} 1.1423 + 1.1424 +void 1.1425 +sctp_iterator_worker(void) 1.1426 +{ 1.1427 + struct sctp_iterator *it, *nit; 1.1428 + 1.1429 + /* This function is called with the WQ lock in place */ 1.1430 + 1.1431 + sctp_it_ctl.iterator_running = 1; 1.1432 + TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) { 1.1433 + sctp_it_ctl.cur_it = it; 1.1434 + /* now lets work on this one */ 1.1435 + TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr); 1.1436 + SCTP_IPI_ITERATOR_WQ_UNLOCK(); 1.1437 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.1438 + CURVNET_SET(it->vn); 1.1439 +#endif 1.1440 + sctp_iterator_work(it); 1.1441 + sctp_it_ctl.cur_it = NULL; 1.1442 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.1443 + CURVNET_RESTORE(); 1.1444 +#endif 1.1445 + SCTP_IPI_ITERATOR_WQ_LOCK(); 1.1446 +#if !defined(__FreeBSD__) 1.1447 + if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) { 1.1448 + break; 1.1449 + } 1.1450 +#endif 1.1451 + /*sa_ignore FREED_MEMORY*/ 1.1452 + } 1.1453 + sctp_it_ctl.iterator_running = 0; 1.1454 + return; 1.1455 +} 1.1456 + 1.1457 + 1.1458 +static void 1.1459 +sctp_handle_addr_wq(void) 1.1460 +{ 1.1461 + /* deal with the ADDR wq from the rtsock calls */ 1.1462 + struct sctp_laddr *wi, *nwi; 1.1463 + struct sctp_asconf_iterator *asc; 1.1464 + 1.1465 + SCTP_MALLOC(asc, struct sctp_asconf_iterator *, 1.1466 + sizeof(struct sctp_asconf_iterator), SCTP_M_ASC_IT); 1.1467 + if (asc == NULL) { 1.1468 + /* Try later, no memory */ 1.1469 + sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 1.1470 + (struct sctp_inpcb *)NULL, 1.1471 + (struct sctp_tcb *)NULL, 1.1472 + (struct sctp_nets *)NULL); 1.1473 + return; 1.1474 + } 1.1475 + LIST_INIT(&asc->list_of_work); 1.1476 + asc->cnt = 0; 1.1477 + 1.1478 + SCTP_WQ_ADDR_LOCK(); 1.1479 + LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) { 1.1480 + LIST_REMOVE(wi, sctp_nxt_addr); 1.1481 + LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr); 1.1482 + asc->cnt++; 1.1483 + } 1.1484 + SCTP_WQ_ADDR_UNLOCK(); 1.1485 + 1.1486 + if (asc->cnt == 0) { 1.1487 + SCTP_FREE(asc, SCTP_M_ASC_IT); 1.1488 + } else { 1.1489 + (void)sctp_initiate_iterator(sctp_asconf_iterator_ep, 1.1490 + sctp_asconf_iterator_stcb, 1.1491 + NULL, /* No ep end for boundall */ 1.1492 + SCTP_PCB_FLAGS_BOUNDALL, 1.1493 + SCTP_PCB_ANY_FEATURES, 1.1494 + SCTP_ASOC_ANY_STATE, 1.1495 + (void *)asc, 0, 1.1496 + sctp_asconf_iterator_end, NULL, 0); 1.1497 + } 1.1498 +} 1.1499 + 1.1500 +void 1.1501 +sctp_timeout_handler(void *t) 1.1502 +{ 1.1503 + struct sctp_inpcb *inp; 1.1504 + struct sctp_tcb *stcb; 1.1505 + struct sctp_nets *net; 1.1506 + struct sctp_timer *tmr; 1.1507 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1508 + struct socket *so; 1.1509 +#endif 1.1510 + int did_output, type; 1.1511 + 1.1512 + tmr = (struct sctp_timer *)t; 1.1513 + inp = (struct sctp_inpcb *)tmr->ep; 1.1514 + stcb = (struct sctp_tcb *)tmr->tcb; 1.1515 + net = (struct sctp_nets *)tmr->net; 1.1516 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.1517 + CURVNET_SET((struct vnet *)tmr->vnet); 1.1518 +#endif 1.1519 + did_output = 1; 1.1520 + 1.1521 +#ifdef SCTP_AUDITING_ENABLED 1.1522 + sctp_audit_log(0xF0, (uint8_t) tmr->type); 1.1523 + sctp_auditing(3, inp, stcb, net); 1.1524 +#endif 1.1525 + 1.1526 + /* sanity checks... */ 1.1527 + if (tmr->self != (void *)tmr) { 1.1528 + /* 1.1529 + * SCTP_PRINTF("Stale SCTP timer fired (%p), ignoring...\n", 1.1530 + * (void *)tmr); 1.1531 + */ 1.1532 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.1533 + CURVNET_RESTORE(); 1.1534 +#endif 1.1535 + return; 1.1536 + } 1.1537 + tmr->stopped_from = 0xa001; 1.1538 + if (!SCTP_IS_TIMER_TYPE_VALID(tmr->type)) { 1.1539 + /* 1.1540 + * SCTP_PRINTF("SCTP timer fired with invalid type: 0x%x\n", 1.1541 + * tmr->type); 1.1542 + */ 1.1543 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.1544 + CURVNET_RESTORE(); 1.1545 +#endif 1.1546 + return; 1.1547 + } 1.1548 + tmr->stopped_from = 0xa002; 1.1549 + if ((tmr->type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) { 1.1550 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.1551 + CURVNET_RESTORE(); 1.1552 +#endif 1.1553 + return; 1.1554 + } 1.1555 + /* if this is an iterator timeout, get the struct and clear inp */ 1.1556 + tmr->stopped_from = 0xa003; 1.1557 + type = tmr->type; 1.1558 + if (inp) { 1.1559 + SCTP_INP_INCR_REF(inp); 1.1560 + if ((inp->sctp_socket == NULL) && 1.1561 + ((tmr->type != SCTP_TIMER_TYPE_INPKILL) && 1.1562 + (tmr->type != SCTP_TIMER_TYPE_INIT) && 1.1563 + (tmr->type != SCTP_TIMER_TYPE_SEND) && 1.1564 + (tmr->type != SCTP_TIMER_TYPE_RECV) && 1.1565 + (tmr->type != SCTP_TIMER_TYPE_HEARTBEAT) && 1.1566 + (tmr->type != SCTP_TIMER_TYPE_SHUTDOWN) && 1.1567 + (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNACK) && 1.1568 + (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNGUARD) && 1.1569 + (tmr->type != SCTP_TIMER_TYPE_ASOCKILL)) 1.1570 + ) { 1.1571 + SCTP_INP_DECR_REF(inp); 1.1572 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.1573 + CURVNET_RESTORE(); 1.1574 +#endif 1.1575 + return; 1.1576 + } 1.1577 + } 1.1578 + tmr->stopped_from = 0xa004; 1.1579 + if (stcb) { 1.1580 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.1581 + if (stcb->asoc.state == 0) { 1.1582 + atomic_add_int(&stcb->asoc.refcnt, -1); 1.1583 + if (inp) { 1.1584 + SCTP_INP_DECR_REF(inp); 1.1585 + } 1.1586 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.1587 + CURVNET_RESTORE(); 1.1588 +#endif 1.1589 + return; 1.1590 + } 1.1591 + } 1.1592 + tmr->stopped_from = 0xa005; 1.1593 + SCTPDBG(SCTP_DEBUG_TIMER1, "Timer type %d goes off\n", tmr->type); 1.1594 + if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) { 1.1595 + if (inp) { 1.1596 + SCTP_INP_DECR_REF(inp); 1.1597 + } 1.1598 + if (stcb) { 1.1599 + atomic_add_int(&stcb->asoc.refcnt, -1); 1.1600 + } 1.1601 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.1602 + CURVNET_RESTORE(); 1.1603 +#endif 1.1604 + return; 1.1605 + } 1.1606 + tmr->stopped_from = 0xa006; 1.1607 + 1.1608 + if (stcb) { 1.1609 + SCTP_TCB_LOCK(stcb); 1.1610 + atomic_add_int(&stcb->asoc.refcnt, -1); 1.1611 + if ((tmr->type != SCTP_TIMER_TYPE_ASOCKILL) && 1.1612 + ((stcb->asoc.state == 0) || 1.1613 + (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED))) { 1.1614 + SCTP_TCB_UNLOCK(stcb); 1.1615 + if (inp) { 1.1616 + SCTP_INP_DECR_REF(inp); 1.1617 + } 1.1618 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.1619 + CURVNET_RESTORE(); 1.1620 +#endif 1.1621 + return; 1.1622 + } 1.1623 + } 1.1624 + /* record in stopped what t-o occured */ 1.1625 + tmr->stopped_from = tmr->type; 1.1626 + 1.1627 + /* mark as being serviced now */ 1.1628 + if (SCTP_OS_TIMER_PENDING(&tmr->timer)) { 1.1629 + /* 1.1630 + * Callout has been rescheduled. 1.1631 + */ 1.1632 + goto get_out; 1.1633 + } 1.1634 + if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) { 1.1635 + /* 1.1636 + * Not active, so no action. 1.1637 + */ 1.1638 + goto get_out; 1.1639 + } 1.1640 + SCTP_OS_TIMER_DEACTIVATE(&tmr->timer); 1.1641 + 1.1642 + /* call the handler for the appropriate timer type */ 1.1643 + switch (tmr->type) { 1.1644 + case SCTP_TIMER_TYPE_ZERO_COPY: 1.1645 + if (inp == NULL) { 1.1646 + break; 1.1647 + } 1.1648 + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 1.1649 + SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); 1.1650 + } 1.1651 + break; 1.1652 + case SCTP_TIMER_TYPE_ZCOPY_SENDQ: 1.1653 + if (inp == NULL) { 1.1654 + break; 1.1655 + } 1.1656 + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 1.1657 + SCTP_ZERO_COPY_SENDQ_EVENT(inp, inp->sctp_socket); 1.1658 + } 1.1659 + break; 1.1660 + case SCTP_TIMER_TYPE_ADDR_WQ: 1.1661 + sctp_handle_addr_wq(); 1.1662 + break; 1.1663 + case SCTP_TIMER_TYPE_SEND: 1.1664 + if ((stcb == NULL) || (inp == NULL)) { 1.1665 + break; 1.1666 + } 1.1667 + SCTP_STAT_INCR(sctps_timodata); 1.1668 + stcb->asoc.timodata++; 1.1669 + stcb->asoc.num_send_timers_up--; 1.1670 + if (stcb->asoc.num_send_timers_up < 0) { 1.1671 + stcb->asoc.num_send_timers_up = 0; 1.1672 + } 1.1673 + SCTP_TCB_LOCK_ASSERT(stcb); 1.1674 + if (sctp_t3rxt_timer(inp, stcb, net)) { 1.1675 + /* no need to unlock on tcb its gone */ 1.1676 + 1.1677 + goto out_decr; 1.1678 + } 1.1679 + SCTP_TCB_LOCK_ASSERT(stcb); 1.1680 +#ifdef SCTP_AUDITING_ENABLED 1.1681 + sctp_auditing(4, inp, stcb, net); 1.1682 +#endif 1.1683 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1.1684 + if ((stcb->asoc.num_send_timers_up == 0) && 1.1685 + (stcb->asoc.sent_queue_cnt > 0)) { 1.1686 + struct sctp_tmit_chunk *chk; 1.1687 + 1.1688 + /* 1.1689 + * safeguard. If there on some on the sent queue 1.1690 + * somewhere but no timers running something is 1.1691 + * wrong... so we start a timer on the first chunk 1.1692 + * on the send queue on whatever net it is sent to. 1.1693 + */ 1.1694 + chk = TAILQ_FIRST(&stcb->asoc.sent_queue); 1.1695 + sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, 1.1696 + chk->whoTo); 1.1697 + } 1.1698 + break; 1.1699 + case SCTP_TIMER_TYPE_INIT: 1.1700 + if ((stcb == NULL) || (inp == NULL)) { 1.1701 + break; 1.1702 + } 1.1703 + SCTP_STAT_INCR(sctps_timoinit); 1.1704 + stcb->asoc.timoinit++; 1.1705 + if (sctp_t1init_timer(inp, stcb, net)) { 1.1706 + /* no need to unlock on tcb its gone */ 1.1707 + goto out_decr; 1.1708 + } 1.1709 + /* We do output but not here */ 1.1710 + did_output = 0; 1.1711 + break; 1.1712 + case SCTP_TIMER_TYPE_RECV: 1.1713 + if ((stcb == NULL) || (inp == NULL)) { 1.1714 + break; 1.1715 + } 1.1716 + SCTP_STAT_INCR(sctps_timosack); 1.1717 + stcb->asoc.timosack++; 1.1718 + sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED); 1.1719 +#ifdef SCTP_AUDITING_ENABLED 1.1720 + sctp_auditing(4, inp, stcb, net); 1.1721 +#endif 1.1722 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SACK_TMR, SCTP_SO_NOT_LOCKED); 1.1723 + break; 1.1724 + case SCTP_TIMER_TYPE_SHUTDOWN: 1.1725 + if ((stcb == NULL) || (inp == NULL)) { 1.1726 + break; 1.1727 + } 1.1728 + if (sctp_shutdown_timer(inp, stcb, net)) { 1.1729 + /* no need to unlock on tcb its gone */ 1.1730 + goto out_decr; 1.1731 + } 1.1732 + SCTP_STAT_INCR(sctps_timoshutdown); 1.1733 + stcb->asoc.timoshutdown++; 1.1734 +#ifdef SCTP_AUDITING_ENABLED 1.1735 + sctp_auditing(4, inp, stcb, net); 1.1736 +#endif 1.1737 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_NOT_LOCKED); 1.1738 + break; 1.1739 + case SCTP_TIMER_TYPE_HEARTBEAT: 1.1740 + if ((stcb == NULL) || (inp == NULL) || (net == NULL)) { 1.1741 + break; 1.1742 + } 1.1743 + SCTP_STAT_INCR(sctps_timoheartbeat); 1.1744 + stcb->asoc.timoheartbeat++; 1.1745 + if (sctp_heartbeat_timer(inp, stcb, net)) { 1.1746 + /* no need to unlock on tcb its gone */ 1.1747 + goto out_decr; 1.1748 + } 1.1749 +#ifdef SCTP_AUDITING_ENABLED 1.1750 + sctp_auditing(4, inp, stcb, net); 1.1751 +#endif 1.1752 + if (!(net->dest_state & SCTP_ADDR_NOHB)) { 1.1753 + sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); 1.1754 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_HB_TMR, SCTP_SO_NOT_LOCKED); 1.1755 + } 1.1756 + break; 1.1757 + case SCTP_TIMER_TYPE_COOKIE: 1.1758 + if ((stcb == NULL) || (inp == NULL)) { 1.1759 + break; 1.1760 + } 1.1761 + 1.1762 + if (sctp_cookie_timer(inp, stcb, net)) { 1.1763 + /* no need to unlock on tcb its gone */ 1.1764 + goto out_decr; 1.1765 + } 1.1766 + SCTP_STAT_INCR(sctps_timocookie); 1.1767 + stcb->asoc.timocookie++; 1.1768 +#ifdef SCTP_AUDITING_ENABLED 1.1769 + sctp_auditing(4, inp, stcb, net); 1.1770 +#endif 1.1771 + /* 1.1772 + * We consider T3 and Cookie timer pretty much the same with 1.1773 + * respect to where from in chunk_output. 1.1774 + */ 1.1775 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED); 1.1776 + break; 1.1777 + case SCTP_TIMER_TYPE_NEWCOOKIE: 1.1778 + { 1.1779 + struct timeval tv; 1.1780 + int i, secret; 1.1781 + if (inp == NULL) { 1.1782 + break; 1.1783 + } 1.1784 + SCTP_STAT_INCR(sctps_timosecret); 1.1785 + (void)SCTP_GETTIME_TIMEVAL(&tv); 1.1786 + SCTP_INP_WLOCK(inp); 1.1787 + inp->sctp_ep.time_of_secret_change = tv.tv_sec; 1.1788 + inp->sctp_ep.last_secret_number = 1.1789 + inp->sctp_ep.current_secret_number; 1.1790 + inp->sctp_ep.current_secret_number++; 1.1791 + if (inp->sctp_ep.current_secret_number >= 1.1792 + SCTP_HOW_MANY_SECRETS) { 1.1793 + inp->sctp_ep.current_secret_number = 0; 1.1794 + } 1.1795 + secret = (int)inp->sctp_ep.current_secret_number; 1.1796 + for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) { 1.1797 + inp->sctp_ep.secret_key[secret][i] = 1.1798 + sctp_select_initial_TSN(&inp->sctp_ep); 1.1799 + } 1.1800 + SCTP_INP_WUNLOCK(inp); 1.1801 + sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net); 1.1802 + } 1.1803 + did_output = 0; 1.1804 + break; 1.1805 + case SCTP_TIMER_TYPE_PATHMTURAISE: 1.1806 + if ((stcb == NULL) || (inp == NULL)) { 1.1807 + break; 1.1808 + } 1.1809 + SCTP_STAT_INCR(sctps_timopathmtu); 1.1810 + sctp_pathmtu_timer(inp, stcb, net); 1.1811 + did_output = 0; 1.1812 + break; 1.1813 + case SCTP_TIMER_TYPE_SHUTDOWNACK: 1.1814 + if ((stcb == NULL) || (inp == NULL)) { 1.1815 + break; 1.1816 + } 1.1817 + if (sctp_shutdownack_timer(inp, stcb, net)) { 1.1818 + /* no need to unlock on tcb its gone */ 1.1819 + goto out_decr; 1.1820 + } 1.1821 + SCTP_STAT_INCR(sctps_timoshutdownack); 1.1822 + stcb->asoc.timoshutdownack++; 1.1823 +#ifdef SCTP_AUDITING_ENABLED 1.1824 + sctp_auditing(4, inp, stcb, net); 1.1825 +#endif 1.1826 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_ACK_TMR, SCTP_SO_NOT_LOCKED); 1.1827 + break; 1.1828 + case SCTP_TIMER_TYPE_SHUTDOWNGUARD: 1.1829 + if ((stcb == NULL) || (inp == NULL)) { 1.1830 + break; 1.1831 + } 1.1832 + SCTP_STAT_INCR(sctps_timoshutdownguard); 1.1833 + sctp_abort_an_association(inp, stcb, NULL, SCTP_SO_NOT_LOCKED); 1.1834 + /* no need to unlock on tcb its gone */ 1.1835 + goto out_decr; 1.1836 + 1.1837 + case SCTP_TIMER_TYPE_STRRESET: 1.1838 + if ((stcb == NULL) || (inp == NULL)) { 1.1839 + break; 1.1840 + } 1.1841 + if (sctp_strreset_timer(inp, stcb, net)) { 1.1842 + /* no need to unlock on tcb its gone */ 1.1843 + goto out_decr; 1.1844 + } 1.1845 + SCTP_STAT_INCR(sctps_timostrmrst); 1.1846 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_TMR, SCTP_SO_NOT_LOCKED); 1.1847 + break; 1.1848 + case SCTP_TIMER_TYPE_ASCONF: 1.1849 + if ((stcb == NULL) || (inp == NULL)) { 1.1850 + break; 1.1851 + } 1.1852 + if (sctp_asconf_timer(inp, stcb, net)) { 1.1853 + /* no need to unlock on tcb its gone */ 1.1854 + goto out_decr; 1.1855 + } 1.1856 + SCTP_STAT_INCR(sctps_timoasconf); 1.1857 +#ifdef SCTP_AUDITING_ENABLED 1.1858 + sctp_auditing(4, inp, stcb, net); 1.1859 +#endif 1.1860 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_ASCONF_TMR, SCTP_SO_NOT_LOCKED); 1.1861 + break; 1.1862 + case SCTP_TIMER_TYPE_PRIM_DELETED: 1.1863 + if ((stcb == NULL) || (inp == NULL)) { 1.1864 + break; 1.1865 + } 1.1866 + sctp_delete_prim_timer(inp, stcb, net); 1.1867 + SCTP_STAT_INCR(sctps_timodelprim); 1.1868 + break; 1.1869 + 1.1870 + case SCTP_TIMER_TYPE_AUTOCLOSE: 1.1871 + if ((stcb == NULL) || (inp == NULL)) { 1.1872 + break; 1.1873 + } 1.1874 + SCTP_STAT_INCR(sctps_timoautoclose); 1.1875 + sctp_autoclose_timer(inp, stcb, net); 1.1876 + sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED); 1.1877 + did_output = 0; 1.1878 + break; 1.1879 + case SCTP_TIMER_TYPE_ASOCKILL: 1.1880 + if ((stcb == NULL) || (inp == NULL)) { 1.1881 + break; 1.1882 + } 1.1883 + SCTP_STAT_INCR(sctps_timoassockill); 1.1884 + /* Can we free it yet? */ 1.1885 + SCTP_INP_DECR_REF(inp); 1.1886 + sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_1); 1.1887 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1888 + so = SCTP_INP_SO(inp); 1.1889 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.1890 + SCTP_TCB_UNLOCK(stcb); 1.1891 + SCTP_SOCKET_LOCK(so, 1); 1.1892 + SCTP_TCB_LOCK(stcb); 1.1893 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.1894 +#endif 1.1895 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_2); 1.1896 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.1897 + SCTP_SOCKET_UNLOCK(so, 1); 1.1898 +#endif 1.1899 + /* 1.1900 + * free asoc, always unlocks (or destroy's) so prevent 1.1901 + * duplicate unlock or unlock of a free mtx :-0 1.1902 + */ 1.1903 + stcb = NULL; 1.1904 + goto out_no_decr; 1.1905 + case SCTP_TIMER_TYPE_INPKILL: 1.1906 + SCTP_STAT_INCR(sctps_timoinpkill); 1.1907 + if (inp == NULL) { 1.1908 + break; 1.1909 + } 1.1910 + /* 1.1911 + * special case, take away our increment since WE are the 1.1912 + * killer 1.1913 + */ 1.1914 + SCTP_INP_DECR_REF(inp); 1.1915 + sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_3); 1.1916 +#if defined(__APPLE__) 1.1917 + SCTP_SOCKET_LOCK(SCTP_INP_SO(inp), 1); 1.1918 +#endif 1.1919 + sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, 1.1920 + SCTP_CALLED_FROM_INPKILL_TIMER); 1.1921 +#if defined(__APPLE__) 1.1922 + SCTP_SOCKET_UNLOCK(SCTP_INP_SO(inp), 1); 1.1923 +#endif 1.1924 + inp = NULL; 1.1925 + goto out_no_decr; 1.1926 + default: 1.1927 + SCTPDBG(SCTP_DEBUG_TIMER1, "sctp_timeout_handler:unknown timer %d\n", 1.1928 + tmr->type); 1.1929 + break; 1.1930 + } 1.1931 +#ifdef SCTP_AUDITING_ENABLED 1.1932 + sctp_audit_log(0xF1, (uint8_t) tmr->type); 1.1933 + if (inp) 1.1934 + sctp_auditing(5, inp, stcb, net); 1.1935 +#endif 1.1936 + if ((did_output) && stcb) { 1.1937 + /* 1.1938 + * Now we need to clean up the control chunk chain if an 1.1939 + * ECNE is on it. It must be marked as UNSENT again so next 1.1940 + * call will continue to send it until such time that we get 1.1941 + * a CWR, to remove it. It is, however, less likely that we 1.1942 + * will find a ecn echo on the chain though. 1.1943 + */ 1.1944 + sctp_fix_ecn_echo(&stcb->asoc); 1.1945 + } 1.1946 +get_out: 1.1947 + if (stcb) { 1.1948 + SCTP_TCB_UNLOCK(stcb); 1.1949 + } 1.1950 + 1.1951 +out_decr: 1.1952 + if (inp) { 1.1953 + SCTP_INP_DECR_REF(inp); 1.1954 + } 1.1955 + 1.1956 +out_no_decr: 1.1957 + SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type %d)\n", 1.1958 + type); 1.1959 +#if defined(__FreeBSD__) && __FreeBSD_version >= 801000 1.1960 + CURVNET_RESTORE(); 1.1961 +#endif 1.1962 +} 1.1963 + 1.1964 +void 1.1965 +sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1.1966 + struct sctp_nets *net) 1.1967 +{ 1.1968 + uint32_t to_ticks; 1.1969 + struct sctp_timer *tmr; 1.1970 + 1.1971 + if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) 1.1972 + return; 1.1973 + 1.1974 + tmr = NULL; 1.1975 + if (stcb) { 1.1976 + SCTP_TCB_LOCK_ASSERT(stcb); 1.1977 + } 1.1978 + switch (t_type) { 1.1979 + case SCTP_TIMER_TYPE_ZERO_COPY: 1.1980 + tmr = &inp->sctp_ep.zero_copy_timer; 1.1981 + to_ticks = SCTP_ZERO_COPY_TICK_DELAY; 1.1982 + break; 1.1983 + case SCTP_TIMER_TYPE_ZCOPY_SENDQ: 1.1984 + tmr = &inp->sctp_ep.zero_copy_sendq_timer; 1.1985 + to_ticks = SCTP_ZERO_COPY_SENDQ_TICK_DELAY; 1.1986 + break; 1.1987 + case SCTP_TIMER_TYPE_ADDR_WQ: 1.1988 + /* Only 1 tick away :-) */ 1.1989 + tmr = &SCTP_BASE_INFO(addr_wq_timer); 1.1990 + to_ticks = SCTP_ADDRESS_TICK_DELAY; 1.1991 + break; 1.1992 + case SCTP_TIMER_TYPE_SEND: 1.1993 + /* Here we use the RTO timer */ 1.1994 + { 1.1995 + int rto_val; 1.1996 + 1.1997 + if ((stcb == NULL) || (net == NULL)) { 1.1998 + return; 1.1999 + } 1.2000 + tmr = &net->rxt_timer; 1.2001 + if (net->RTO == 0) { 1.2002 + rto_val = stcb->asoc.initial_rto; 1.2003 + } else { 1.2004 + rto_val = net->RTO; 1.2005 + } 1.2006 + to_ticks = MSEC_TO_TICKS(rto_val); 1.2007 + } 1.2008 + break; 1.2009 + case SCTP_TIMER_TYPE_INIT: 1.2010 + /* 1.2011 + * Here we use the INIT timer default usually about 1 1.2012 + * minute. 1.2013 + */ 1.2014 + if ((stcb == NULL) || (net == NULL)) { 1.2015 + return; 1.2016 + } 1.2017 + tmr = &net->rxt_timer; 1.2018 + if (net->RTO == 0) { 1.2019 + to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 1.2020 + } else { 1.2021 + to_ticks = MSEC_TO_TICKS(net->RTO); 1.2022 + } 1.2023 + break; 1.2024 + case SCTP_TIMER_TYPE_RECV: 1.2025 + /* 1.2026 + * Here we use the Delayed-Ack timer value from the inp 1.2027 + * ususually about 200ms. 1.2028 + */ 1.2029 + if (stcb == NULL) { 1.2030 + return; 1.2031 + } 1.2032 + tmr = &stcb->asoc.dack_timer; 1.2033 + to_ticks = MSEC_TO_TICKS(stcb->asoc.delayed_ack); 1.2034 + break; 1.2035 + case SCTP_TIMER_TYPE_SHUTDOWN: 1.2036 + /* Here we use the RTO of the destination. */ 1.2037 + if ((stcb == NULL) || (net == NULL)) { 1.2038 + return; 1.2039 + } 1.2040 + if (net->RTO == 0) { 1.2041 + to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 1.2042 + } else { 1.2043 + to_ticks = MSEC_TO_TICKS(net->RTO); 1.2044 + } 1.2045 + tmr = &net->rxt_timer; 1.2046 + break; 1.2047 + case SCTP_TIMER_TYPE_HEARTBEAT: 1.2048 + /* 1.2049 + * the net is used here so that we can add in the RTO. Even 1.2050 + * though we use a different timer. We also add the HB timer 1.2051 + * PLUS a random jitter. 1.2052 + */ 1.2053 + if ((inp == NULL) || (stcb == NULL) || (net == NULL)) { 1.2054 + return; 1.2055 + } else { 1.2056 + uint32_t rndval; 1.2057 + uint32_t jitter; 1.2058 + 1.2059 + if ((net->dest_state & SCTP_ADDR_NOHB) && 1.2060 + !(net->dest_state & SCTP_ADDR_UNCONFIRMED)) { 1.2061 + return; 1.2062 + } 1.2063 + if (net->RTO == 0) { 1.2064 + to_ticks = stcb->asoc.initial_rto; 1.2065 + } else { 1.2066 + to_ticks = net->RTO; 1.2067 + } 1.2068 + rndval = sctp_select_initial_TSN(&inp->sctp_ep); 1.2069 + jitter = rndval % to_ticks; 1.2070 + if (jitter >= (to_ticks >> 1)) { 1.2071 + to_ticks = to_ticks + (jitter - (to_ticks >> 1)); 1.2072 + } else { 1.2073 + to_ticks = to_ticks - jitter; 1.2074 + } 1.2075 + if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) && 1.2076 + !(net->dest_state & SCTP_ADDR_PF)) { 1.2077 + to_ticks += net->heart_beat_delay; 1.2078 + } 1.2079 + /* 1.2080 + * Now we must convert the to_ticks that are now in 1.2081 + * ms to ticks. 1.2082 + */ 1.2083 + to_ticks = MSEC_TO_TICKS(to_ticks); 1.2084 + tmr = &net->hb_timer; 1.2085 + } 1.2086 + break; 1.2087 + case SCTP_TIMER_TYPE_COOKIE: 1.2088 + /* 1.2089 + * Here we can use the RTO timer from the network since one 1.2090 + * RTT was compelete. If a retran happened then we will be 1.2091 + * using the RTO initial value. 1.2092 + */ 1.2093 + if ((stcb == NULL) || (net == NULL)) { 1.2094 + return; 1.2095 + } 1.2096 + if (net->RTO == 0) { 1.2097 + to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 1.2098 + } else { 1.2099 + to_ticks = MSEC_TO_TICKS(net->RTO); 1.2100 + } 1.2101 + tmr = &net->rxt_timer; 1.2102 + break; 1.2103 + case SCTP_TIMER_TYPE_NEWCOOKIE: 1.2104 + /* 1.2105 + * nothing needed but the endpoint here ususually about 60 1.2106 + * minutes. 1.2107 + */ 1.2108 + if (inp == NULL) { 1.2109 + return; 1.2110 + } 1.2111 + tmr = &inp->sctp_ep.signature_change; 1.2112 + to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE]; 1.2113 + break; 1.2114 + case SCTP_TIMER_TYPE_ASOCKILL: 1.2115 + if (stcb == NULL) { 1.2116 + return; 1.2117 + } 1.2118 + tmr = &stcb->asoc.strreset_timer; 1.2119 + to_ticks = MSEC_TO_TICKS(SCTP_ASOC_KILL_TIMEOUT); 1.2120 + break; 1.2121 + case SCTP_TIMER_TYPE_INPKILL: 1.2122 + /* 1.2123 + * The inp is setup to die. We re-use the signature_chage 1.2124 + * timer since that has stopped and we are in the GONE 1.2125 + * state. 1.2126 + */ 1.2127 + if (inp == NULL) { 1.2128 + return; 1.2129 + } 1.2130 + tmr = &inp->sctp_ep.signature_change; 1.2131 + to_ticks = MSEC_TO_TICKS(SCTP_INP_KILL_TIMEOUT); 1.2132 + break; 1.2133 + case SCTP_TIMER_TYPE_PATHMTURAISE: 1.2134 + /* 1.2135 + * Here we use the value found in the EP for PMTU ususually 1.2136 + * about 10 minutes. 1.2137 + */ 1.2138 + if ((stcb == NULL) || (inp == NULL)) { 1.2139 + return; 1.2140 + } 1.2141 + if (net == NULL) { 1.2142 + return; 1.2143 + } 1.2144 + if (net->dest_state & SCTP_ADDR_NO_PMTUD) { 1.2145 + return; 1.2146 + } 1.2147 + to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU]; 1.2148 + tmr = &net->pmtu_timer; 1.2149 + break; 1.2150 + case SCTP_TIMER_TYPE_SHUTDOWNACK: 1.2151 + /* Here we use the RTO of the destination */ 1.2152 + if ((stcb == NULL) || (net == NULL)) { 1.2153 + return; 1.2154 + } 1.2155 + if (net->RTO == 0) { 1.2156 + to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 1.2157 + } else { 1.2158 + to_ticks = MSEC_TO_TICKS(net->RTO); 1.2159 + } 1.2160 + tmr = &net->rxt_timer; 1.2161 + break; 1.2162 + case SCTP_TIMER_TYPE_SHUTDOWNGUARD: 1.2163 + /* 1.2164 + * Here we use the endpoints shutdown guard timer usually 1.2165 + * about 3 minutes. 1.2166 + */ 1.2167 + if ((inp == NULL) || (stcb == NULL)) { 1.2168 + return; 1.2169 + } 1.2170 + to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN]; 1.2171 + tmr = &stcb->asoc.shut_guard_timer; 1.2172 + break; 1.2173 + case SCTP_TIMER_TYPE_STRRESET: 1.2174 + /* 1.2175 + * Here the timer comes from the stcb but its value is from 1.2176 + * the net's RTO. 1.2177 + */ 1.2178 + if ((stcb == NULL) || (net == NULL)) { 1.2179 + return; 1.2180 + } 1.2181 + if (net->RTO == 0) { 1.2182 + to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 1.2183 + } else { 1.2184 + to_ticks = MSEC_TO_TICKS(net->RTO); 1.2185 + } 1.2186 + tmr = &stcb->asoc.strreset_timer; 1.2187 + break; 1.2188 + case SCTP_TIMER_TYPE_ASCONF: 1.2189 + /* 1.2190 + * Here the timer comes from the stcb but its value is from 1.2191 + * the net's RTO. 1.2192 + */ 1.2193 + if ((stcb == NULL) || (net == NULL)) { 1.2194 + return; 1.2195 + } 1.2196 + if (net->RTO == 0) { 1.2197 + to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 1.2198 + } else { 1.2199 + to_ticks = MSEC_TO_TICKS(net->RTO); 1.2200 + } 1.2201 + tmr = &stcb->asoc.asconf_timer; 1.2202 + break; 1.2203 + case SCTP_TIMER_TYPE_PRIM_DELETED: 1.2204 + if ((stcb == NULL) || (net != NULL)) { 1.2205 + return; 1.2206 + } 1.2207 + to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto); 1.2208 + tmr = &stcb->asoc.delete_prim_timer; 1.2209 + break; 1.2210 + case SCTP_TIMER_TYPE_AUTOCLOSE: 1.2211 + if (stcb == NULL) { 1.2212 + return; 1.2213 + } 1.2214 + if (stcb->asoc.sctp_autoclose_ticks == 0) { 1.2215 + /* 1.2216 + * Really an error since stcb is NOT set to 1.2217 + * autoclose 1.2218 + */ 1.2219 + return; 1.2220 + } 1.2221 + to_ticks = stcb->asoc.sctp_autoclose_ticks; 1.2222 + tmr = &stcb->asoc.autoclose_timer; 1.2223 + break; 1.2224 + default: 1.2225 + SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n", 1.2226 + __FUNCTION__, t_type); 1.2227 + return; 1.2228 + break; 1.2229 + } 1.2230 + if ((to_ticks <= 0) || (tmr == NULL)) { 1.2231 + SCTPDBG(SCTP_DEBUG_TIMER1, "%s: %d:software error to_ticks:%d tmr:%p not set ??\n", 1.2232 + __FUNCTION__, t_type, to_ticks, (void *)tmr); 1.2233 + return; 1.2234 + } 1.2235 + if (SCTP_OS_TIMER_PENDING(&tmr->timer)) { 1.2236 + /* 1.2237 + * we do NOT allow you to have it already running. if it is 1.2238 + * we leave the current one up unchanged 1.2239 + */ 1.2240 + return; 1.2241 + } 1.2242 + /* At this point we can proceed */ 1.2243 + if (t_type == SCTP_TIMER_TYPE_SEND) { 1.2244 + stcb->asoc.num_send_timers_up++; 1.2245 + } 1.2246 + tmr->stopped_from = 0; 1.2247 + tmr->type = t_type; 1.2248 + tmr->ep = (void *)inp; 1.2249 + tmr->tcb = (void *)stcb; 1.2250 + tmr->net = (void *)net; 1.2251 + tmr->self = (void *)tmr; 1.2252 +#if defined(__FreeBSD__) && __FreeBSD_version >= 800000 1.2253 + tmr->vnet = (void *)curvnet; 1.2254 +#endif 1.2255 +#ifndef __Panda__ 1.2256 + tmr->ticks = sctp_get_tick_count(); 1.2257 +#endif 1.2258 + (void)SCTP_OS_TIMER_START(&tmr->timer, to_ticks, sctp_timeout_handler, tmr); 1.2259 + return; 1.2260 +} 1.2261 + 1.2262 +void 1.2263 +sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1.2264 + struct sctp_nets *net, uint32_t from) 1.2265 +{ 1.2266 + struct sctp_timer *tmr; 1.2267 + 1.2268 + if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && 1.2269 + (inp == NULL)) 1.2270 + return; 1.2271 + 1.2272 + tmr = NULL; 1.2273 + if (stcb) { 1.2274 + SCTP_TCB_LOCK_ASSERT(stcb); 1.2275 + } 1.2276 + switch (t_type) { 1.2277 + case SCTP_TIMER_TYPE_ZERO_COPY: 1.2278 + tmr = &inp->sctp_ep.zero_copy_timer; 1.2279 + break; 1.2280 + case SCTP_TIMER_TYPE_ZCOPY_SENDQ: 1.2281 + tmr = &inp->sctp_ep.zero_copy_sendq_timer; 1.2282 + break; 1.2283 + case SCTP_TIMER_TYPE_ADDR_WQ: 1.2284 + tmr = &SCTP_BASE_INFO(addr_wq_timer); 1.2285 + break; 1.2286 + case SCTP_TIMER_TYPE_SEND: 1.2287 + if ((stcb == NULL) || (net == NULL)) { 1.2288 + return; 1.2289 + } 1.2290 + tmr = &net->rxt_timer; 1.2291 + break; 1.2292 + case SCTP_TIMER_TYPE_INIT: 1.2293 + if ((stcb == NULL) || (net == NULL)) { 1.2294 + return; 1.2295 + } 1.2296 + tmr = &net->rxt_timer; 1.2297 + break; 1.2298 + case SCTP_TIMER_TYPE_RECV: 1.2299 + if (stcb == NULL) { 1.2300 + return; 1.2301 + } 1.2302 + tmr = &stcb->asoc.dack_timer; 1.2303 + break; 1.2304 + case SCTP_TIMER_TYPE_SHUTDOWN: 1.2305 + if ((stcb == NULL) || (net == NULL)) { 1.2306 + return; 1.2307 + } 1.2308 + tmr = &net->rxt_timer; 1.2309 + break; 1.2310 + case SCTP_TIMER_TYPE_HEARTBEAT: 1.2311 + if ((stcb == NULL) || (net == NULL)) { 1.2312 + return; 1.2313 + } 1.2314 + tmr = &net->hb_timer; 1.2315 + break; 1.2316 + case SCTP_TIMER_TYPE_COOKIE: 1.2317 + if ((stcb == NULL) || (net == NULL)) { 1.2318 + return; 1.2319 + } 1.2320 + tmr = &net->rxt_timer; 1.2321 + break; 1.2322 + case SCTP_TIMER_TYPE_NEWCOOKIE: 1.2323 + /* nothing needed but the endpoint here */ 1.2324 + tmr = &inp->sctp_ep.signature_change; 1.2325 + /* 1.2326 + * We re-use the newcookie timer for the INP kill timer. We 1.2327 + * must assure that we do not kill it by accident. 1.2328 + */ 1.2329 + break; 1.2330 + case SCTP_TIMER_TYPE_ASOCKILL: 1.2331 + /* 1.2332 + * Stop the asoc kill timer. 1.2333 + */ 1.2334 + if (stcb == NULL) { 1.2335 + return; 1.2336 + } 1.2337 + tmr = &stcb->asoc.strreset_timer; 1.2338 + break; 1.2339 + 1.2340 + case SCTP_TIMER_TYPE_INPKILL: 1.2341 + /* 1.2342 + * The inp is setup to die. We re-use the signature_chage 1.2343 + * timer since that has stopped and we are in the GONE 1.2344 + * state. 1.2345 + */ 1.2346 + tmr = &inp->sctp_ep.signature_change; 1.2347 + break; 1.2348 + case SCTP_TIMER_TYPE_PATHMTURAISE: 1.2349 + if ((stcb == NULL) || (net == NULL)) { 1.2350 + return; 1.2351 + } 1.2352 + tmr = &net->pmtu_timer; 1.2353 + break; 1.2354 + case SCTP_TIMER_TYPE_SHUTDOWNACK: 1.2355 + if ((stcb == NULL) || (net == NULL)) { 1.2356 + return; 1.2357 + } 1.2358 + tmr = &net->rxt_timer; 1.2359 + break; 1.2360 + case SCTP_TIMER_TYPE_SHUTDOWNGUARD: 1.2361 + if (stcb == NULL) { 1.2362 + return; 1.2363 + } 1.2364 + tmr = &stcb->asoc.shut_guard_timer; 1.2365 + break; 1.2366 + case SCTP_TIMER_TYPE_STRRESET: 1.2367 + if (stcb == NULL) { 1.2368 + return; 1.2369 + } 1.2370 + tmr = &stcb->asoc.strreset_timer; 1.2371 + break; 1.2372 + case SCTP_TIMER_TYPE_ASCONF: 1.2373 + if (stcb == NULL) { 1.2374 + return; 1.2375 + } 1.2376 + tmr = &stcb->asoc.asconf_timer; 1.2377 + break; 1.2378 + case SCTP_TIMER_TYPE_PRIM_DELETED: 1.2379 + if (stcb == NULL) { 1.2380 + return; 1.2381 + } 1.2382 + tmr = &stcb->asoc.delete_prim_timer; 1.2383 + break; 1.2384 + case SCTP_TIMER_TYPE_AUTOCLOSE: 1.2385 + if (stcb == NULL) { 1.2386 + return; 1.2387 + } 1.2388 + tmr = &stcb->asoc.autoclose_timer; 1.2389 + break; 1.2390 + default: 1.2391 + SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n", 1.2392 + __FUNCTION__, t_type); 1.2393 + break; 1.2394 + } 1.2395 + if (tmr == NULL) { 1.2396 + return; 1.2397 + } 1.2398 + if ((tmr->type != t_type) && tmr->type) { 1.2399 + /* 1.2400 + * Ok we have a timer that is under joint use. Cookie timer 1.2401 + * per chance with the SEND timer. We therefore are NOT 1.2402 + * running the timer that the caller wants stopped. So just 1.2403 + * return. 1.2404 + */ 1.2405 + return; 1.2406 + } 1.2407 + if ((t_type == SCTP_TIMER_TYPE_SEND) && (stcb != NULL)) { 1.2408 + stcb->asoc.num_send_timers_up--; 1.2409 + if (stcb->asoc.num_send_timers_up < 0) { 1.2410 + stcb->asoc.num_send_timers_up = 0; 1.2411 + } 1.2412 + } 1.2413 + tmr->self = NULL; 1.2414 + tmr->stopped_from = from; 1.2415 + (void)SCTP_OS_TIMER_STOP(&tmr->timer); 1.2416 + return; 1.2417 +} 1.2418 + 1.2419 +uint32_t 1.2420 +sctp_calculate_len(struct mbuf *m) 1.2421 +{ 1.2422 + uint32_t tlen = 0; 1.2423 + struct mbuf *at; 1.2424 + 1.2425 + at = m; 1.2426 + while (at) { 1.2427 + tlen += SCTP_BUF_LEN(at); 1.2428 + at = SCTP_BUF_NEXT(at); 1.2429 + } 1.2430 + return (tlen); 1.2431 +} 1.2432 + 1.2433 +void 1.2434 +sctp_mtu_size_reset(struct sctp_inpcb *inp, 1.2435 + struct sctp_association *asoc, uint32_t mtu) 1.2436 +{ 1.2437 + /* 1.2438 + * Reset the P-MTU size on this association, this involves changing 1.2439 + * the asoc MTU, going through ANY chunk+overhead larger than mtu to 1.2440 + * allow the DF flag to be cleared. 1.2441 + */ 1.2442 + struct sctp_tmit_chunk *chk; 1.2443 + unsigned int eff_mtu, ovh; 1.2444 + 1.2445 + asoc->smallest_mtu = mtu; 1.2446 + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 1.2447 + ovh = SCTP_MIN_OVERHEAD; 1.2448 + } else { 1.2449 + ovh = SCTP_MIN_V4_OVERHEAD; 1.2450 + } 1.2451 + eff_mtu = mtu - ovh; 1.2452 + TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) { 1.2453 + if (chk->send_size > eff_mtu) { 1.2454 + chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; 1.2455 + } 1.2456 + } 1.2457 + TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) { 1.2458 + if (chk->send_size > eff_mtu) { 1.2459 + chk->flags |= CHUNK_FLAGS_FRAGMENT_OK; 1.2460 + } 1.2461 + } 1.2462 +} 1.2463 + 1.2464 + 1.2465 +/* 1.2466 + * given an association and starting time of the current RTT period return 1.2467 + * RTO in number of msecs net should point to the current network 1.2468 + */ 1.2469 + 1.2470 +uint32_t 1.2471 +sctp_calculate_rto(struct sctp_tcb *stcb, 1.2472 + struct sctp_association *asoc, 1.2473 + struct sctp_nets *net, 1.2474 + struct timeval *told, 1.2475 + int safe, int rtt_from_sack) 1.2476 +{ 1.2477 + /*- 1.2478 + * given an association and the starting time of the current RTT 1.2479 + * period (in value1/value2) return RTO in number of msecs. 1.2480 + */ 1.2481 + int32_t rtt; /* RTT in ms */ 1.2482 + uint32_t new_rto; 1.2483 + int first_measure = 0; 1.2484 + struct timeval now, then, *old; 1.2485 + 1.2486 + /* Copy it out for sparc64 */ 1.2487 + if (safe == sctp_align_unsafe_makecopy) { 1.2488 + old = &then; 1.2489 + memcpy(&then, told, sizeof(struct timeval)); 1.2490 + } else if (safe == sctp_align_safe_nocopy) { 1.2491 + old = told; 1.2492 + } else { 1.2493 + /* error */ 1.2494 + SCTP_PRINTF("Huh, bad rto calc call\n"); 1.2495 + return (0); 1.2496 + } 1.2497 + /************************/ 1.2498 + /* 1. calculate new RTT */ 1.2499 + /************************/ 1.2500 + /* get the current time */ 1.2501 + if (stcb->asoc.use_precise_time) { 1.2502 + (void)SCTP_GETPTIME_TIMEVAL(&now); 1.2503 + } else { 1.2504 + (void)SCTP_GETTIME_TIMEVAL(&now); 1.2505 + } 1.2506 + timevalsub(&now, old); 1.2507 + /* store the current RTT in us */ 1.2508 + net->rtt = (uint64_t)1000000 * (uint64_t)now.tv_sec + 1.2509 + (uint64_t)now.tv_usec; 1.2510 + /* computer rtt in ms */ 1.2511 + rtt = net->rtt / 1000; 1.2512 + if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) { 1.2513 + /* Tell the CC module that a new update has just occurred from a sack */ 1.2514 + (*asoc->cc_functions.sctp_rtt_calculated)(stcb, net, &now); 1.2515 + } 1.2516 + /* Do we need to determine the lan? We do this only 1.2517 + * on sacks i.e. RTT being determined from data not 1.2518 + * non-data (HB/INIT->INITACK). 1.2519 + */ 1.2520 + if ((rtt_from_sack == SCTP_RTT_FROM_DATA) && 1.2521 + (net->lan_type == SCTP_LAN_UNKNOWN)) { 1.2522 + if (net->rtt > SCTP_LOCAL_LAN_RTT) { 1.2523 + net->lan_type = SCTP_LAN_INTERNET; 1.2524 + } else { 1.2525 + net->lan_type = SCTP_LAN_LOCAL; 1.2526 + } 1.2527 + } 1.2528 + 1.2529 + /***************************/ 1.2530 + /* 2. update RTTVAR & SRTT */ 1.2531 + /***************************/ 1.2532 + /*- 1.2533 + * Compute the scaled average lastsa and the 1.2534 + * scaled variance lastsv as described in van Jacobson 1.2535 + * Paper "Congestion Avoidance and Control", Annex A. 1.2536 + * 1.2537 + * (net->lastsa >> SCTP_RTT_SHIFT) is the srtt 1.2538 + * (net->lastsa >> SCTP_RTT_VAR_SHIFT) is the rttvar 1.2539 + */ 1.2540 + if (net->RTO_measured) { 1.2541 + rtt -= (net->lastsa >> SCTP_RTT_SHIFT); 1.2542 + net->lastsa += rtt; 1.2543 + if (rtt < 0) { 1.2544 + rtt = -rtt; 1.2545 + } 1.2546 + rtt -= (net->lastsv >> SCTP_RTT_VAR_SHIFT); 1.2547 + net->lastsv += rtt; 1.2548 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) { 1.2549 + rto_logging(net, SCTP_LOG_RTTVAR); 1.2550 + } 1.2551 + } else { 1.2552 + /* First RTO measurment */ 1.2553 + net->RTO_measured = 1; 1.2554 + first_measure = 1; 1.2555 + net->lastsa = rtt << SCTP_RTT_SHIFT; 1.2556 + net->lastsv = (rtt / 2) << SCTP_RTT_VAR_SHIFT; 1.2557 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) { 1.2558 + rto_logging(net, SCTP_LOG_INITIAL_RTT); 1.2559 + } 1.2560 + } 1.2561 + if (net->lastsv == 0) { 1.2562 + net->lastsv = SCTP_CLOCK_GRANULARITY; 1.2563 + } 1.2564 + new_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv; 1.2565 + if ((new_rto > SCTP_SAT_NETWORK_MIN) && 1.2566 + (stcb->asoc.sat_network_lockout == 0)) { 1.2567 + stcb->asoc.sat_network = 1; 1.2568 + } else if ((!first_measure) && stcb->asoc.sat_network) { 1.2569 + stcb->asoc.sat_network = 0; 1.2570 + stcb->asoc.sat_network_lockout = 1; 1.2571 + } 1.2572 + /* bound it, per C6/C7 in Section 5.3.1 */ 1.2573 + if (new_rto < stcb->asoc.minrto) { 1.2574 + new_rto = stcb->asoc.minrto; 1.2575 + } 1.2576 + if (new_rto > stcb->asoc.maxrto) { 1.2577 + new_rto = stcb->asoc.maxrto; 1.2578 + } 1.2579 + /* we are now returning the RTO */ 1.2580 + return (new_rto); 1.2581 +} 1.2582 + 1.2583 +/* 1.2584 + * return a pointer to a contiguous piece of data from the given mbuf chain 1.2585 + * starting at 'off' for 'len' bytes. If the desired piece spans more than 1.2586 + * one mbuf, a copy is made at 'ptr'. caller must ensure that the buffer size 1.2587 + * is >= 'len' returns NULL if there there isn't 'len' bytes in the chain. 1.2588 + */ 1.2589 +caddr_t 1.2590 +sctp_m_getptr(struct mbuf *m, int off, int len, uint8_t * in_ptr) 1.2591 +{ 1.2592 + uint32_t count; 1.2593 + uint8_t *ptr; 1.2594 + 1.2595 + ptr = in_ptr; 1.2596 + if ((off < 0) || (len <= 0)) 1.2597 + return (NULL); 1.2598 + 1.2599 + /* find the desired start location */ 1.2600 + while ((m != NULL) && (off > 0)) { 1.2601 + if (off < SCTP_BUF_LEN(m)) 1.2602 + break; 1.2603 + off -= SCTP_BUF_LEN(m); 1.2604 + m = SCTP_BUF_NEXT(m); 1.2605 + } 1.2606 + if (m == NULL) 1.2607 + return (NULL); 1.2608 + 1.2609 + /* is the current mbuf large enough (eg. contiguous)? */ 1.2610 + if ((SCTP_BUF_LEN(m) - off) >= len) { 1.2611 + return (mtod(m, caddr_t) + off); 1.2612 + } else { 1.2613 + /* else, it spans more than one mbuf, so save a temp copy... */ 1.2614 + while ((m != NULL) && (len > 0)) { 1.2615 + count = min(SCTP_BUF_LEN(m) - off, len); 1.2616 + bcopy(mtod(m, caddr_t) + off, ptr, count); 1.2617 + len -= count; 1.2618 + ptr += count; 1.2619 + off = 0; 1.2620 + m = SCTP_BUF_NEXT(m); 1.2621 + } 1.2622 + if ((m == NULL) && (len > 0)) 1.2623 + return (NULL); 1.2624 + else 1.2625 + return ((caddr_t)in_ptr); 1.2626 + } 1.2627 +} 1.2628 + 1.2629 + 1.2630 + 1.2631 +struct sctp_paramhdr * 1.2632 +sctp_get_next_param(struct mbuf *m, 1.2633 + int offset, 1.2634 + struct sctp_paramhdr *pull, 1.2635 + int pull_limit) 1.2636 +{ 1.2637 + /* This just provides a typed signature to Peter's Pull routine */ 1.2638 + return ((struct sctp_paramhdr *)sctp_m_getptr(m, offset, pull_limit, 1.2639 + (uint8_t *) pull)); 1.2640 +} 1.2641 + 1.2642 + 1.2643 +int 1.2644 +sctp_add_pad_tombuf(struct mbuf *m, int padlen) 1.2645 +{ 1.2646 + /* 1.2647 + * add padlen bytes of 0 filled padding to the end of the mbuf. If 1.2648 + * padlen is > 3 this routine will fail. 1.2649 + */ 1.2650 + uint8_t *dp; 1.2651 + int i; 1.2652 + 1.2653 + if (padlen > 3) { 1.2654 + SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); 1.2655 + return (ENOBUFS); 1.2656 + } 1.2657 + if (padlen <= M_TRAILINGSPACE(m)) { 1.2658 + /* 1.2659 + * The easy way. We hope the majority of the time we hit 1.2660 + * here :) 1.2661 + */ 1.2662 + dp = (uint8_t *) (mtod(m, caddr_t) + SCTP_BUF_LEN(m)); 1.2663 + SCTP_BUF_LEN(m) += padlen; 1.2664 + } else { 1.2665 + /* Hard way we must grow the mbuf */ 1.2666 + struct mbuf *tmp; 1.2667 + 1.2668 + tmp = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA); 1.2669 + if (tmp == NULL) { 1.2670 + /* Out of space GAK! we are in big trouble. */ 1.2671 + SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); 1.2672 + return (ENOBUFS); 1.2673 + } 1.2674 + /* setup and insert in middle */ 1.2675 + SCTP_BUF_LEN(tmp) = padlen; 1.2676 + SCTP_BUF_NEXT(tmp) = NULL; 1.2677 + SCTP_BUF_NEXT(m) = tmp; 1.2678 + dp = mtod(tmp, uint8_t *); 1.2679 + } 1.2680 + /* zero out the pad */ 1.2681 + for (i = 0; i < padlen; i++) { 1.2682 + *dp = 0; 1.2683 + dp++; 1.2684 + } 1.2685 + return (0); 1.2686 +} 1.2687 + 1.2688 +int 1.2689 +sctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf) 1.2690 +{ 1.2691 + /* find the last mbuf in chain and pad it */ 1.2692 + struct mbuf *m_at; 1.2693 + 1.2694 + if (last_mbuf) { 1.2695 + return (sctp_add_pad_tombuf(last_mbuf, padval)); 1.2696 + } else { 1.2697 + for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) { 1.2698 + if (SCTP_BUF_NEXT(m_at) == NULL) { 1.2699 + return (sctp_add_pad_tombuf(m_at, padval)); 1.2700 + } 1.2701 + } 1.2702 + } 1.2703 + SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT); 1.2704 + return (EFAULT); 1.2705 +} 1.2706 + 1.2707 +static void 1.2708 +sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb, 1.2709 + uint16_t error, struct sctp_abort_chunk *abort, uint8_t from_peer, int so_locked 1.2710 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.2711 + SCTP_UNUSED 1.2712 +#endif 1.2713 + ) 1.2714 +{ 1.2715 + struct mbuf *m_notify; 1.2716 + struct sctp_assoc_change *sac; 1.2717 + struct sctp_queued_to_read *control; 1.2718 + size_t notif_len, abort_len; 1.2719 + unsigned int i; 1.2720 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2721 + struct socket *so; 1.2722 +#endif 1.2723 + 1.2724 + if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) { 1.2725 + notif_len = sizeof(struct sctp_assoc_change); 1.2726 + if (abort != NULL) { 1.2727 + abort_len = ntohs(abort->ch.chunk_length); 1.2728 + } else { 1.2729 + abort_len = 0; 1.2730 + } 1.2731 + if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) { 1.2732 + notif_len += SCTP_ASSOC_SUPPORTS_MAX; 1.2733 + } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) { 1.2734 + notif_len += abort_len; 1.2735 + } 1.2736 + m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); 1.2737 + if (m_notify == NULL) { 1.2738 + /* Retry with smaller value. */ 1.2739 + notif_len = sizeof(struct sctp_assoc_change); 1.2740 + m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); 1.2741 + if (m_notify == NULL) { 1.2742 + goto set_error; 1.2743 + } 1.2744 + } 1.2745 + SCTP_BUF_NEXT(m_notify) = NULL; 1.2746 + sac = mtod(m_notify, struct sctp_assoc_change *); 1.2747 + sac->sac_type = SCTP_ASSOC_CHANGE; 1.2748 + sac->sac_flags = 0; 1.2749 + sac->sac_length = sizeof(struct sctp_assoc_change); 1.2750 + sac->sac_state = state; 1.2751 + sac->sac_error = error; 1.2752 + /* XXX verify these stream counts */ 1.2753 + sac->sac_outbound_streams = stcb->asoc.streamoutcnt; 1.2754 + sac->sac_inbound_streams = stcb->asoc.streamincnt; 1.2755 + sac->sac_assoc_id = sctp_get_associd(stcb); 1.2756 + if (notif_len > sizeof(struct sctp_assoc_change)) { 1.2757 + if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) { 1.2758 + i = 0; 1.2759 + if (stcb->asoc.peer_supports_prsctp) { 1.2760 + sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR; 1.2761 + } 1.2762 + if (stcb->asoc.peer_supports_auth) { 1.2763 + sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH; 1.2764 + } 1.2765 + if (stcb->asoc.peer_supports_asconf) { 1.2766 + sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF; 1.2767 + } 1.2768 + sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF; 1.2769 + if (stcb->asoc.peer_supports_strreset) { 1.2770 + sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG; 1.2771 + } 1.2772 + sac->sac_length += i; 1.2773 + } else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) { 1.2774 + memcpy(sac->sac_info, abort, abort_len); 1.2775 + sac->sac_length += abort_len; 1.2776 + } 1.2777 + } 1.2778 + SCTP_BUF_LEN(m_notify) = sac->sac_length; 1.2779 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.2780 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.2781 + m_notify); 1.2782 + if (control != NULL) { 1.2783 + control->length = SCTP_BUF_LEN(m_notify); 1.2784 + /* not that we need this */ 1.2785 + control->tail_mbuf = m_notify; 1.2786 + control->spec_flags = M_NOTIFICATION; 1.2787 + sctp_add_to_readq(stcb->sctp_ep, stcb, 1.2788 + control, 1.2789 + &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, 1.2790 + so_locked); 1.2791 + } else { 1.2792 + sctp_m_freem(m_notify); 1.2793 + } 1.2794 + } 1.2795 + /* 1.2796 + * For 1-to-1 style sockets, we send up and error when an ABORT 1.2797 + * comes in. 1.2798 + */ 1.2799 +set_error: 1.2800 + if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1.2801 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1.2802 + ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) { 1.2803 + SOCK_LOCK(stcb->sctp_socket); 1.2804 + if (from_peer) { 1.2805 + if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) { 1.2806 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED); 1.2807 + stcb->sctp_socket->so_error = ECONNREFUSED; 1.2808 + } else { 1.2809 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET); 1.2810 + stcb->sctp_socket->so_error = ECONNRESET; 1.2811 + } 1.2812 + } else { 1.2813 + if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) || 1.2814 + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) { 1.2815 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ETIMEDOUT); 1.2816 + stcb->sctp_socket->so_error = ETIMEDOUT; 1.2817 + } else { 1.2818 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNABORTED); 1.2819 + stcb->sctp_socket->so_error = ECONNABORTED; 1.2820 + } 1.2821 + } 1.2822 + } 1.2823 + /* Wake ANY sleepers */ 1.2824 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2825 + so = SCTP_INP_SO(stcb->sctp_ep); 1.2826 + if (!so_locked) { 1.2827 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.2828 + SCTP_TCB_UNLOCK(stcb); 1.2829 + SCTP_SOCKET_LOCK(so, 1); 1.2830 + SCTP_TCB_LOCK(stcb); 1.2831 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.2832 + if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1.2833 + SCTP_SOCKET_UNLOCK(so, 1); 1.2834 + return; 1.2835 + } 1.2836 + } 1.2837 +#endif 1.2838 + if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1.2839 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) && 1.2840 + ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) { 1.2841 +#if defined(__APPLE__) 1.2842 + socantrcvmore(stcb->sctp_socket); 1.2843 +#else 1.2844 + socantrcvmore_locked(stcb->sctp_socket); 1.2845 +#endif 1.2846 + } 1.2847 + sorwakeup(stcb->sctp_socket); 1.2848 + sowwakeup(stcb->sctp_socket); 1.2849 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.2850 + if (!so_locked) { 1.2851 + SCTP_SOCKET_UNLOCK(so, 1); 1.2852 + } 1.2853 +#endif 1.2854 +} 1.2855 + 1.2856 +static void 1.2857 +sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state, 1.2858 + struct sockaddr *sa, uint32_t error) 1.2859 +{ 1.2860 + struct mbuf *m_notify; 1.2861 + struct sctp_paddr_change *spc; 1.2862 + struct sctp_queued_to_read *control; 1.2863 + 1.2864 + if ((stcb == NULL) || 1.2865 + sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) { 1.2866 + /* event not enabled */ 1.2867 + return; 1.2868 + } 1.2869 + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_paddr_change), 0, M_NOWAIT, 1, MT_DATA); 1.2870 + if (m_notify == NULL) 1.2871 + return; 1.2872 + SCTP_BUF_LEN(m_notify) = 0; 1.2873 + spc = mtod(m_notify, struct sctp_paddr_change *); 1.2874 + spc->spc_type = SCTP_PEER_ADDR_CHANGE; 1.2875 + spc->spc_flags = 0; 1.2876 + spc->spc_length = sizeof(struct sctp_paddr_change); 1.2877 + switch (sa->sa_family) { 1.2878 +#ifdef INET 1.2879 + case AF_INET: 1.2880 + memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in)); 1.2881 + break; 1.2882 +#endif 1.2883 +#ifdef INET6 1.2884 + case AF_INET6: 1.2885 + { 1.2886 +#ifdef SCTP_EMBEDDED_V6_SCOPE 1.2887 + struct sockaddr_in6 *sin6; 1.2888 +#endif /* SCTP_EMBEDDED_V6_SCOPE */ 1.2889 + memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6)); 1.2890 + 1.2891 +#ifdef SCTP_EMBEDDED_V6_SCOPE 1.2892 + sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr; 1.2893 + if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) { 1.2894 + if (sin6->sin6_scope_id == 0) { 1.2895 + /* recover scope_id for user */ 1.2896 +#ifdef SCTP_KAME 1.2897 + (void)sa6_recoverscope(sin6); 1.2898 +#else 1.2899 + (void)in6_recoverscope(sin6, &sin6->sin6_addr, 1.2900 + NULL); 1.2901 +#endif 1.2902 + } else { 1.2903 + /* clear embedded scope_id for user */ 1.2904 + in6_clearscope(&sin6->sin6_addr); 1.2905 + } 1.2906 + } 1.2907 +#endif /* SCTP_EMBEDDED_V6_SCOPE */ 1.2908 + break; 1.2909 + } 1.2910 +#endif 1.2911 +#if defined(__Userspace__) 1.2912 + case AF_CONN: 1.2913 + memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_conn)); 1.2914 + break; 1.2915 +#endif 1.2916 + default: 1.2917 + /* TSNH */ 1.2918 + break; 1.2919 + } 1.2920 + spc->spc_state = state; 1.2921 + spc->spc_error = error; 1.2922 + spc->spc_assoc_id = sctp_get_associd(stcb); 1.2923 + 1.2924 + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_paddr_change); 1.2925 + SCTP_BUF_NEXT(m_notify) = NULL; 1.2926 + 1.2927 + /* append to socket */ 1.2928 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.2929 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.2930 + m_notify); 1.2931 + if (control == NULL) { 1.2932 + /* no memory */ 1.2933 + sctp_m_freem(m_notify); 1.2934 + return; 1.2935 + } 1.2936 + control->length = SCTP_BUF_LEN(m_notify); 1.2937 + control->spec_flags = M_NOTIFICATION; 1.2938 + /* not that we need this */ 1.2939 + control->tail_mbuf = m_notify; 1.2940 + sctp_add_to_readq(stcb->sctp_ep, stcb, 1.2941 + control, 1.2942 + &stcb->sctp_socket->so_rcv, 1, 1.2943 + SCTP_READ_LOCK_NOT_HELD, 1.2944 + SCTP_SO_NOT_LOCKED); 1.2945 +} 1.2946 + 1.2947 + 1.2948 +static void 1.2949 +sctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error, 1.2950 + struct sctp_tmit_chunk *chk, int so_locked 1.2951 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.2952 + SCTP_UNUSED 1.2953 +#endif 1.2954 + ) 1.2955 +{ 1.2956 + struct mbuf *m_notify; 1.2957 + struct sctp_send_failed *ssf; 1.2958 + struct sctp_send_failed_event *ssfe; 1.2959 + struct sctp_queued_to_read *control; 1.2960 + int length; 1.2961 + 1.2962 + if ((stcb == NULL) || 1.2963 + (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) && 1.2964 + sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) { 1.2965 + /* event not enabled */ 1.2966 + return; 1.2967 + } 1.2968 + 1.2969 + if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 1.2970 + length = sizeof(struct sctp_send_failed_event); 1.2971 + } else { 1.2972 + length = sizeof(struct sctp_send_failed); 1.2973 + } 1.2974 + m_notify = sctp_get_mbuf_for_msg(length, 0, M_NOWAIT, 1, MT_DATA); 1.2975 + if (m_notify == NULL) 1.2976 + /* no space left */ 1.2977 + return; 1.2978 + length += chk->send_size; 1.2979 + length -= sizeof(struct sctp_data_chunk); 1.2980 + SCTP_BUF_LEN(m_notify) = 0; 1.2981 + if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 1.2982 + ssfe = mtod(m_notify, struct sctp_send_failed_event *); 1.2983 + ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT; 1.2984 + if (sent) { 1.2985 + ssfe->ssfe_flags = SCTP_DATA_SENT; 1.2986 + } else { 1.2987 + ssfe->ssfe_flags = SCTP_DATA_UNSENT; 1.2988 + } 1.2989 + ssfe->ssfe_length = length; 1.2990 + ssfe->ssfe_error = error; 1.2991 + /* not exactly what the user sent in, but should be close :) */ 1.2992 + bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info)); 1.2993 + ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number; 1.2994 + ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags; 1.2995 + ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype; 1.2996 + ssfe->ssfe_info.snd_context = chk->rec.data.context; 1.2997 + ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb); 1.2998 + ssfe->ssfe_assoc_id = sctp_get_associd(stcb); 1.2999 + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event); 1.3000 + } else { 1.3001 + ssf = mtod(m_notify, struct sctp_send_failed *); 1.3002 + ssf->ssf_type = SCTP_SEND_FAILED; 1.3003 + if (sent) { 1.3004 + ssf->ssf_flags = SCTP_DATA_SENT; 1.3005 + } else { 1.3006 + ssf->ssf_flags = SCTP_DATA_UNSENT; 1.3007 + } 1.3008 + ssf->ssf_length = length; 1.3009 + ssf->ssf_error = error; 1.3010 + /* not exactly what the user sent in, but should be close :) */ 1.3011 + bzero(&ssf->ssf_info, sizeof(ssf->ssf_info)); 1.3012 + ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number; 1.3013 + ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq; 1.3014 + ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags; 1.3015 + ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype; 1.3016 + ssf->ssf_info.sinfo_context = chk->rec.data.context; 1.3017 + ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb); 1.3018 + ssf->ssf_assoc_id = sctp_get_associd(stcb); 1.3019 + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed); 1.3020 + } 1.3021 + if (chk->data) { 1.3022 + /* 1.3023 + * trim off the sctp chunk header(it should 1.3024 + * be there) 1.3025 + */ 1.3026 + if (chk->send_size >= sizeof(struct sctp_data_chunk)) { 1.3027 + m_adj(chk->data, sizeof(struct sctp_data_chunk)); 1.3028 + sctp_mbuf_crush(chk->data); 1.3029 + chk->send_size -= sizeof(struct sctp_data_chunk); 1.3030 + } 1.3031 + } 1.3032 + SCTP_BUF_NEXT(m_notify) = chk->data; 1.3033 + /* Steal off the mbuf */ 1.3034 + chk->data = NULL; 1.3035 + /* 1.3036 + * For this case, we check the actual socket buffer, since the assoc 1.3037 + * is going away we don't want to overfill the socket buffer for a 1.3038 + * non-reader 1.3039 + */ 1.3040 + if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 1.3041 + sctp_m_freem(m_notify); 1.3042 + return; 1.3043 + } 1.3044 + /* append to socket */ 1.3045 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.3046 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.3047 + m_notify); 1.3048 + if (control == NULL) { 1.3049 + /* no memory */ 1.3050 + sctp_m_freem(m_notify); 1.3051 + return; 1.3052 + } 1.3053 + control->spec_flags = M_NOTIFICATION; 1.3054 + sctp_add_to_readq(stcb->sctp_ep, stcb, 1.3055 + control, 1.3056 + &stcb->sctp_socket->so_rcv, 1, 1.3057 + SCTP_READ_LOCK_NOT_HELD, 1.3058 + so_locked); 1.3059 +} 1.3060 + 1.3061 + 1.3062 +static void 1.3063 +sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error, 1.3064 + struct sctp_stream_queue_pending *sp, int so_locked 1.3065 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.3066 + SCTP_UNUSED 1.3067 +#endif 1.3068 + ) 1.3069 +{ 1.3070 + struct mbuf *m_notify; 1.3071 + struct sctp_send_failed *ssf; 1.3072 + struct sctp_send_failed_event *ssfe; 1.3073 + struct sctp_queued_to_read *control; 1.3074 + int length; 1.3075 + 1.3076 + if ((stcb == NULL) || 1.3077 + (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) && 1.3078 + sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) { 1.3079 + /* event not enabled */ 1.3080 + return; 1.3081 + } 1.3082 + if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 1.3083 + length = sizeof(struct sctp_send_failed_event); 1.3084 + } else { 1.3085 + length = sizeof(struct sctp_send_failed); 1.3086 + } 1.3087 + m_notify = sctp_get_mbuf_for_msg(length, 0, M_NOWAIT, 1, MT_DATA); 1.3088 + if (m_notify == NULL) { 1.3089 + /* no space left */ 1.3090 + return; 1.3091 + } 1.3092 + length += sp->length; 1.3093 + SCTP_BUF_LEN(m_notify) = 0; 1.3094 + if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) { 1.3095 + ssfe = mtod(m_notify, struct sctp_send_failed_event *); 1.3096 + ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT; 1.3097 + ssfe->ssfe_flags = SCTP_DATA_UNSENT; 1.3098 + ssfe->ssfe_length = length; 1.3099 + ssfe->ssfe_error = error; 1.3100 + /* not exactly what the user sent in, but should be close :) */ 1.3101 + bzero(&ssfe->ssfe_info, sizeof(ssfe->ssfe_info)); 1.3102 + ssfe->ssfe_info.snd_sid = sp->stream; 1.3103 + if (sp->some_taken) { 1.3104 + ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG; 1.3105 + } else { 1.3106 + ssfe->ssfe_info.snd_flags = SCTP_DATA_NOT_FRAG; 1.3107 + } 1.3108 + ssfe->ssfe_info.snd_ppid = sp->ppid; 1.3109 + ssfe->ssfe_info.snd_context = sp->context; 1.3110 + ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb); 1.3111 + ssfe->ssfe_assoc_id = sctp_get_associd(stcb); 1.3112 + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event); 1.3113 + } else { 1.3114 + ssf = mtod(m_notify, struct sctp_send_failed *); 1.3115 + ssf->ssf_type = SCTP_SEND_FAILED; 1.3116 + ssf->ssf_flags = SCTP_DATA_UNSENT; 1.3117 + ssf->ssf_length = length; 1.3118 + ssf->ssf_error = error; 1.3119 + /* not exactly what the user sent in, but should be close :) */ 1.3120 + bzero(&ssf->ssf_info, sizeof(ssf->ssf_info)); 1.3121 + ssf->ssf_info.sinfo_stream = sp->stream; 1.3122 + ssf->ssf_info.sinfo_ssn = 0; 1.3123 + if (sp->some_taken) { 1.3124 + ssf->ssf_info.sinfo_flags = SCTP_DATA_LAST_FRAG; 1.3125 + } else { 1.3126 + ssf->ssf_info.sinfo_flags = SCTP_DATA_NOT_FRAG; 1.3127 + } 1.3128 + ssf->ssf_info.sinfo_ppid = sp->ppid; 1.3129 + ssf->ssf_info.sinfo_context = sp->context; 1.3130 + ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb); 1.3131 + ssf->ssf_assoc_id = sctp_get_associd(stcb); 1.3132 + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed); 1.3133 + } 1.3134 + SCTP_BUF_NEXT(m_notify) = sp->data; 1.3135 + 1.3136 + /* Steal off the mbuf */ 1.3137 + sp->data = NULL; 1.3138 + /* 1.3139 + * For this case, we check the actual socket buffer, since the assoc 1.3140 + * is going away we don't want to overfill the socket buffer for a 1.3141 + * non-reader 1.3142 + */ 1.3143 + if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 1.3144 + sctp_m_freem(m_notify); 1.3145 + return; 1.3146 + } 1.3147 + /* append to socket */ 1.3148 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.3149 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.3150 + m_notify); 1.3151 + if (control == NULL) { 1.3152 + /* no memory */ 1.3153 + sctp_m_freem(m_notify); 1.3154 + return; 1.3155 + } 1.3156 + control->spec_flags = M_NOTIFICATION; 1.3157 + sctp_add_to_readq(stcb->sctp_ep, stcb, 1.3158 + control, 1.3159 + &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked); 1.3160 +} 1.3161 + 1.3162 + 1.3163 + 1.3164 +static void 1.3165 +sctp_notify_adaptation_layer(struct sctp_tcb *stcb) 1.3166 +{ 1.3167 + struct mbuf *m_notify; 1.3168 + struct sctp_adaptation_event *sai; 1.3169 + struct sctp_queued_to_read *control; 1.3170 + 1.3171 + if ((stcb == NULL) || 1.3172 + sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) { 1.3173 + /* event not enabled */ 1.3174 + return; 1.3175 + } 1.3176 + 1.3177 + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 0, M_NOWAIT, 1, MT_DATA); 1.3178 + if (m_notify == NULL) 1.3179 + /* no space left */ 1.3180 + return; 1.3181 + SCTP_BUF_LEN(m_notify) = 0; 1.3182 + sai = mtod(m_notify, struct sctp_adaptation_event *); 1.3183 + sai->sai_type = SCTP_ADAPTATION_INDICATION; 1.3184 + sai->sai_flags = 0; 1.3185 + sai->sai_length = sizeof(struct sctp_adaptation_event); 1.3186 + sai->sai_adaptation_ind = stcb->asoc.peers_adaptation; 1.3187 + sai->sai_assoc_id = sctp_get_associd(stcb); 1.3188 + 1.3189 + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_adaptation_event); 1.3190 + SCTP_BUF_NEXT(m_notify) = NULL; 1.3191 + 1.3192 + /* append to socket */ 1.3193 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.3194 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.3195 + m_notify); 1.3196 + if (control == NULL) { 1.3197 + /* no memory */ 1.3198 + sctp_m_freem(m_notify); 1.3199 + return; 1.3200 + } 1.3201 + control->length = SCTP_BUF_LEN(m_notify); 1.3202 + control->spec_flags = M_NOTIFICATION; 1.3203 + /* not that we need this */ 1.3204 + control->tail_mbuf = m_notify; 1.3205 + sctp_add_to_readq(stcb->sctp_ep, stcb, 1.3206 + control, 1.3207 + &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 1.3208 +} 1.3209 + 1.3210 +/* This always must be called with the read-queue LOCKED in the INP */ 1.3211 +static void 1.3212 +sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error, 1.3213 + uint32_t val, int so_locked 1.3214 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.3215 + SCTP_UNUSED 1.3216 +#endif 1.3217 + ) 1.3218 +{ 1.3219 + struct mbuf *m_notify; 1.3220 + struct sctp_pdapi_event *pdapi; 1.3221 + struct sctp_queued_to_read *control; 1.3222 + struct sockbuf *sb; 1.3223 + 1.3224 + if ((stcb == NULL) || 1.3225 + sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_PDAPIEVNT)) { 1.3226 + /* event not enabled */ 1.3227 + return; 1.3228 + } 1.3229 + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) { 1.3230 + return; 1.3231 + } 1.3232 + 1.3233 + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 0, M_NOWAIT, 1, MT_DATA); 1.3234 + if (m_notify == NULL) 1.3235 + /* no space left */ 1.3236 + return; 1.3237 + SCTP_BUF_LEN(m_notify) = 0; 1.3238 + pdapi = mtod(m_notify, struct sctp_pdapi_event *); 1.3239 + pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT; 1.3240 + pdapi->pdapi_flags = 0; 1.3241 + pdapi->pdapi_length = sizeof(struct sctp_pdapi_event); 1.3242 + pdapi->pdapi_indication = error; 1.3243 + pdapi->pdapi_stream = (val >> 16); 1.3244 + pdapi->pdapi_seq = (val & 0x0000ffff); 1.3245 + pdapi->pdapi_assoc_id = sctp_get_associd(stcb); 1.3246 + 1.3247 + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_pdapi_event); 1.3248 + SCTP_BUF_NEXT(m_notify) = NULL; 1.3249 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.3250 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.3251 + m_notify); 1.3252 + if (control == NULL) { 1.3253 + /* no memory */ 1.3254 + sctp_m_freem(m_notify); 1.3255 + return; 1.3256 + } 1.3257 + control->spec_flags = M_NOTIFICATION; 1.3258 + control->length = SCTP_BUF_LEN(m_notify); 1.3259 + /* not that we need this */ 1.3260 + control->tail_mbuf = m_notify; 1.3261 + control->held_length = 0; 1.3262 + control->length = 0; 1.3263 + sb = &stcb->sctp_socket->so_rcv; 1.3264 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.3265 + sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify)); 1.3266 + } 1.3267 + sctp_sballoc(stcb, sb, m_notify); 1.3268 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.3269 + sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0); 1.3270 + } 1.3271 + atomic_add_int(&control->length, SCTP_BUF_LEN(m_notify)); 1.3272 + control->end_added = 1; 1.3273 + if (stcb->asoc.control_pdapi) 1.3274 + TAILQ_INSERT_AFTER(&stcb->sctp_ep->read_queue, stcb->asoc.control_pdapi, control, next); 1.3275 + else { 1.3276 + /* we really should not see this case */ 1.3277 + TAILQ_INSERT_TAIL(&stcb->sctp_ep->read_queue, control, next); 1.3278 + } 1.3279 + if (stcb->sctp_ep && stcb->sctp_socket) { 1.3280 + /* This should always be the case */ 1.3281 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3282 + struct socket *so; 1.3283 + 1.3284 + so = SCTP_INP_SO(stcb->sctp_ep); 1.3285 + if (!so_locked) { 1.3286 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.3287 + SCTP_TCB_UNLOCK(stcb); 1.3288 + SCTP_SOCKET_LOCK(so, 1); 1.3289 + SCTP_TCB_LOCK(stcb); 1.3290 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.3291 + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 1.3292 + SCTP_SOCKET_UNLOCK(so, 1); 1.3293 + return; 1.3294 + } 1.3295 + } 1.3296 +#endif 1.3297 + sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket); 1.3298 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3299 + if (!so_locked) { 1.3300 + SCTP_SOCKET_UNLOCK(so, 1); 1.3301 + } 1.3302 +#endif 1.3303 + } 1.3304 +} 1.3305 + 1.3306 +static void 1.3307 +sctp_notify_shutdown_event(struct sctp_tcb *stcb) 1.3308 +{ 1.3309 + struct mbuf *m_notify; 1.3310 + struct sctp_shutdown_event *sse; 1.3311 + struct sctp_queued_to_read *control; 1.3312 + 1.3313 + /* 1.3314 + * For TCP model AND UDP connected sockets we will send an error up 1.3315 + * when an SHUTDOWN completes 1.3316 + */ 1.3317 + if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1.3318 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 1.3319 + /* mark socket closed for read/write and wakeup! */ 1.3320 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3321 + struct socket *so; 1.3322 + 1.3323 + so = SCTP_INP_SO(stcb->sctp_ep); 1.3324 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.3325 + SCTP_TCB_UNLOCK(stcb); 1.3326 + SCTP_SOCKET_LOCK(so, 1); 1.3327 + SCTP_TCB_LOCK(stcb); 1.3328 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.3329 + if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1.3330 + SCTP_SOCKET_UNLOCK(so, 1); 1.3331 + return; 1.3332 + } 1.3333 +#endif 1.3334 + socantsendmore(stcb->sctp_socket); 1.3335 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.3336 + SCTP_SOCKET_UNLOCK(so, 1); 1.3337 +#endif 1.3338 + } 1.3339 + if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)) { 1.3340 + /* event not enabled */ 1.3341 + return; 1.3342 + } 1.3343 + 1.3344 + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_event), 0, M_NOWAIT, 1, MT_DATA); 1.3345 + if (m_notify == NULL) 1.3346 + /* no space left */ 1.3347 + return; 1.3348 + sse = mtod(m_notify, struct sctp_shutdown_event *); 1.3349 + sse->sse_type = SCTP_SHUTDOWN_EVENT; 1.3350 + sse->sse_flags = 0; 1.3351 + sse->sse_length = sizeof(struct sctp_shutdown_event); 1.3352 + sse->sse_assoc_id = sctp_get_associd(stcb); 1.3353 + 1.3354 + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_shutdown_event); 1.3355 + SCTP_BUF_NEXT(m_notify) = NULL; 1.3356 + 1.3357 + /* append to socket */ 1.3358 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.3359 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.3360 + m_notify); 1.3361 + if (control == NULL) { 1.3362 + /* no memory */ 1.3363 + sctp_m_freem(m_notify); 1.3364 + return; 1.3365 + } 1.3366 + control->spec_flags = M_NOTIFICATION; 1.3367 + control->length = SCTP_BUF_LEN(m_notify); 1.3368 + /* not that we need this */ 1.3369 + control->tail_mbuf = m_notify; 1.3370 + sctp_add_to_readq(stcb->sctp_ep, stcb, 1.3371 + control, 1.3372 + &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 1.3373 +} 1.3374 + 1.3375 +static void 1.3376 +sctp_notify_sender_dry_event(struct sctp_tcb *stcb, 1.3377 + int so_locked 1.3378 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.3379 + SCTP_UNUSED 1.3380 +#endif 1.3381 + ) 1.3382 +{ 1.3383 + struct mbuf *m_notify; 1.3384 + struct sctp_sender_dry_event *event; 1.3385 + struct sctp_queued_to_read *control; 1.3386 + 1.3387 + if ((stcb == NULL) || 1.3388 + sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DRYEVNT)) { 1.3389 + /* event not enabled */ 1.3390 + return; 1.3391 + } 1.3392 + 1.3393 + m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_sender_dry_event), 0, M_NOWAIT, 1, MT_DATA); 1.3394 + if (m_notify == NULL) { 1.3395 + /* no space left */ 1.3396 + return; 1.3397 + } 1.3398 + SCTP_BUF_LEN(m_notify) = 0; 1.3399 + event = mtod(m_notify, struct sctp_sender_dry_event *); 1.3400 + event->sender_dry_type = SCTP_SENDER_DRY_EVENT; 1.3401 + event->sender_dry_flags = 0; 1.3402 + event->sender_dry_length = sizeof(struct sctp_sender_dry_event); 1.3403 + event->sender_dry_assoc_id = sctp_get_associd(stcb); 1.3404 + 1.3405 + SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_sender_dry_event); 1.3406 + SCTP_BUF_NEXT(m_notify) = NULL; 1.3407 + 1.3408 + /* append to socket */ 1.3409 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.3410 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.3411 + m_notify); 1.3412 + if (control == NULL) { 1.3413 + /* no memory */ 1.3414 + sctp_m_freem(m_notify); 1.3415 + return; 1.3416 + } 1.3417 + control->length = SCTP_BUF_LEN(m_notify); 1.3418 + control->spec_flags = M_NOTIFICATION; 1.3419 + /* not that we need this */ 1.3420 + control->tail_mbuf = m_notify; 1.3421 + sctp_add_to_readq(stcb->sctp_ep, stcb, control, 1.3422 + &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked); 1.3423 +} 1.3424 + 1.3425 + 1.3426 +void 1.3427 +sctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t numberout, int flag) 1.3428 +{ 1.3429 + struct mbuf *m_notify; 1.3430 + struct sctp_queued_to_read *control; 1.3431 + struct sctp_stream_change_event *stradd; 1.3432 + int len; 1.3433 + 1.3434 + if ((stcb == NULL) || 1.3435 + (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) { 1.3436 + /* event not enabled */ 1.3437 + return; 1.3438 + } 1.3439 + if ((stcb->asoc.peer_req_out) && flag) { 1.3440 + /* Peer made the request, don't tell the local user */ 1.3441 + stcb->asoc.peer_req_out = 0; 1.3442 + return; 1.3443 + } 1.3444 + stcb->asoc.peer_req_out = 0; 1.3445 + m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); 1.3446 + if (m_notify == NULL) 1.3447 + /* no space left */ 1.3448 + return; 1.3449 + SCTP_BUF_LEN(m_notify) = 0; 1.3450 + len = sizeof(struct sctp_stream_change_event); 1.3451 + if (len > M_TRAILINGSPACE(m_notify)) { 1.3452 + /* never enough room */ 1.3453 + sctp_m_freem(m_notify); 1.3454 + return; 1.3455 + } 1.3456 + stradd = mtod(m_notify, struct sctp_stream_change_event *); 1.3457 + stradd->strchange_type = SCTP_STREAM_CHANGE_EVENT; 1.3458 + stradd->strchange_flags = flag; 1.3459 + stradd->strchange_length = len; 1.3460 + stradd->strchange_assoc_id = sctp_get_associd(stcb); 1.3461 + stradd->strchange_instrms = numberin; 1.3462 + stradd->strchange_outstrms = numberout; 1.3463 + SCTP_BUF_LEN(m_notify) = len; 1.3464 + SCTP_BUF_NEXT(m_notify) = NULL; 1.3465 + if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 1.3466 + /* no space */ 1.3467 + sctp_m_freem(m_notify); 1.3468 + return; 1.3469 + } 1.3470 + /* append to socket */ 1.3471 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.3472 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.3473 + m_notify); 1.3474 + if (control == NULL) { 1.3475 + /* no memory */ 1.3476 + sctp_m_freem(m_notify); 1.3477 + return; 1.3478 + } 1.3479 + control->spec_flags = M_NOTIFICATION; 1.3480 + control->length = SCTP_BUF_LEN(m_notify); 1.3481 + /* not that we need this */ 1.3482 + control->tail_mbuf = m_notify; 1.3483 + sctp_add_to_readq(stcb->sctp_ep, stcb, 1.3484 + control, 1.3485 + &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 1.3486 +} 1.3487 + 1.3488 +void 1.3489 +sctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32_t recv_tsn, int flag) 1.3490 +{ 1.3491 + struct mbuf *m_notify; 1.3492 + struct sctp_queued_to_read *control; 1.3493 + struct sctp_assoc_reset_event *strasoc; 1.3494 + int len; 1.3495 + 1.3496 + if ((stcb == NULL) || 1.3497 + (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) { 1.3498 + /* event not enabled */ 1.3499 + return; 1.3500 + } 1.3501 + m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); 1.3502 + if (m_notify == NULL) 1.3503 + /* no space left */ 1.3504 + return; 1.3505 + SCTP_BUF_LEN(m_notify) = 0; 1.3506 + len = sizeof(struct sctp_assoc_reset_event); 1.3507 + if (len > M_TRAILINGSPACE(m_notify)) { 1.3508 + /* never enough room */ 1.3509 + sctp_m_freem(m_notify); 1.3510 + return; 1.3511 + } 1.3512 + strasoc = mtod(m_notify, struct sctp_assoc_reset_event *); 1.3513 + strasoc->assocreset_type = SCTP_ASSOC_RESET_EVENT; 1.3514 + strasoc->assocreset_flags = flag; 1.3515 + strasoc->assocreset_length = len; 1.3516 + strasoc->assocreset_assoc_id= sctp_get_associd(stcb); 1.3517 + strasoc->assocreset_local_tsn = sending_tsn; 1.3518 + strasoc->assocreset_remote_tsn = recv_tsn; 1.3519 + SCTP_BUF_LEN(m_notify) = len; 1.3520 + SCTP_BUF_NEXT(m_notify) = NULL; 1.3521 + if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 1.3522 + /* no space */ 1.3523 + sctp_m_freem(m_notify); 1.3524 + return; 1.3525 + } 1.3526 + /* append to socket */ 1.3527 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.3528 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.3529 + m_notify); 1.3530 + if (control == NULL) { 1.3531 + /* no memory */ 1.3532 + sctp_m_freem(m_notify); 1.3533 + return; 1.3534 + } 1.3535 + control->spec_flags = M_NOTIFICATION; 1.3536 + control->length = SCTP_BUF_LEN(m_notify); 1.3537 + /* not that we need this */ 1.3538 + control->tail_mbuf = m_notify; 1.3539 + sctp_add_to_readq(stcb->sctp_ep, stcb, 1.3540 + control, 1.3541 + &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 1.3542 +} 1.3543 + 1.3544 + 1.3545 + 1.3546 +static void 1.3547 +sctp_notify_stream_reset(struct sctp_tcb *stcb, 1.3548 + int number_entries, uint16_t * list, int flag) 1.3549 +{ 1.3550 + struct mbuf *m_notify; 1.3551 + struct sctp_queued_to_read *control; 1.3552 + struct sctp_stream_reset_event *strreset; 1.3553 + int len; 1.3554 + 1.3555 + if ((stcb == NULL) || 1.3556 + (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT))) { 1.3557 + /* event not enabled */ 1.3558 + return; 1.3559 + } 1.3560 + 1.3561 + m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA); 1.3562 + if (m_notify == NULL) 1.3563 + /* no space left */ 1.3564 + return; 1.3565 + SCTP_BUF_LEN(m_notify) = 0; 1.3566 + len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t)); 1.3567 + if (len > M_TRAILINGSPACE(m_notify)) { 1.3568 + /* never enough room */ 1.3569 + sctp_m_freem(m_notify); 1.3570 + return; 1.3571 + } 1.3572 + strreset = mtod(m_notify, struct sctp_stream_reset_event *); 1.3573 + strreset->strreset_type = SCTP_STREAM_RESET_EVENT; 1.3574 + strreset->strreset_flags = flag; 1.3575 + strreset->strreset_length = len; 1.3576 + strreset->strreset_assoc_id = sctp_get_associd(stcb); 1.3577 + if (number_entries) { 1.3578 + int i; 1.3579 + 1.3580 + for (i = 0; i < number_entries; i++) { 1.3581 + strreset->strreset_stream_list[i] = ntohs(list[i]); 1.3582 + } 1.3583 + } 1.3584 + SCTP_BUF_LEN(m_notify) = len; 1.3585 + SCTP_BUF_NEXT(m_notify) = NULL; 1.3586 + if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) { 1.3587 + /* no space */ 1.3588 + sctp_m_freem(m_notify); 1.3589 + return; 1.3590 + } 1.3591 + /* append to socket */ 1.3592 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.3593 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.3594 + m_notify); 1.3595 + if (control == NULL) { 1.3596 + /* no memory */ 1.3597 + sctp_m_freem(m_notify); 1.3598 + return; 1.3599 + } 1.3600 + control->spec_flags = M_NOTIFICATION; 1.3601 + control->length = SCTP_BUF_LEN(m_notify); 1.3602 + /* not that we need this */ 1.3603 + control->tail_mbuf = m_notify; 1.3604 + sctp_add_to_readq(stcb->sctp_ep, stcb, 1.3605 + control, 1.3606 + &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 1.3607 +} 1.3608 + 1.3609 + 1.3610 +static void 1.3611 +sctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_error_chunk *chunk) 1.3612 +{ 1.3613 + struct mbuf *m_notify; 1.3614 + struct sctp_remote_error *sre; 1.3615 + struct sctp_queued_to_read *control; 1.3616 + size_t notif_len, chunk_len; 1.3617 + 1.3618 + if ((stcb == NULL) || 1.3619 + sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) { 1.3620 + return; 1.3621 + } 1.3622 + if (chunk != NULL) { 1.3623 + chunk_len = ntohs(chunk->ch.chunk_length); 1.3624 + } else { 1.3625 + chunk_len = 0; 1.3626 + } 1.3627 + notif_len = sizeof(struct sctp_remote_error) + chunk_len; 1.3628 + m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); 1.3629 + if (m_notify == NULL) { 1.3630 + /* Retry with smaller value. */ 1.3631 + notif_len = sizeof(struct sctp_remote_error); 1.3632 + m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA); 1.3633 + if (m_notify == NULL) { 1.3634 + return; 1.3635 + } 1.3636 + } 1.3637 + SCTP_BUF_NEXT(m_notify) = NULL; 1.3638 + sre = mtod(m_notify, struct sctp_remote_error *); 1.3639 + sre->sre_type = SCTP_REMOTE_ERROR; 1.3640 + sre->sre_flags = 0; 1.3641 + sre->sre_length = sizeof(struct sctp_remote_error); 1.3642 + sre->sre_error = error; 1.3643 + sre->sre_assoc_id = sctp_get_associd(stcb); 1.3644 + if (notif_len > sizeof(struct sctp_remote_error)) { 1.3645 + memcpy(sre->sre_data, chunk, chunk_len); 1.3646 + sre->sre_length += chunk_len; 1.3647 + } 1.3648 + SCTP_BUF_LEN(m_notify) = sre->sre_length; 1.3649 + control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination, 1.3650 + 0, 0, stcb->asoc.context, 0, 0, 0, 1.3651 + m_notify); 1.3652 + if (control != NULL) { 1.3653 + control->length = SCTP_BUF_LEN(m_notify); 1.3654 + /* not that we need this */ 1.3655 + control->tail_mbuf = m_notify; 1.3656 + control->spec_flags = M_NOTIFICATION; 1.3657 + sctp_add_to_readq(stcb->sctp_ep, stcb, 1.3658 + control, 1.3659 + &stcb->sctp_socket->so_rcv, 1, 1.3660 + SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED); 1.3661 + } else { 1.3662 + sctp_m_freem(m_notify); 1.3663 + } 1.3664 +} 1.3665 + 1.3666 + 1.3667 +void 1.3668 +sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb, 1.3669 + uint32_t error, void *data, int so_locked 1.3670 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.3671 + SCTP_UNUSED 1.3672 +#endif 1.3673 + ) 1.3674 +{ 1.3675 + if ((stcb == NULL) || 1.3676 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 1.3677 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 1.3678 + (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) { 1.3679 + /* If the socket is gone we are out of here */ 1.3680 + return; 1.3681 + } 1.3682 +#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__) 1.3683 + if (stcb->sctp_socket->so_rcv.sb_state & SBS_CANTRCVMORE) { 1.3684 +#else 1.3685 + if (stcb->sctp_socket->so_state & SS_CANTRCVMORE) { 1.3686 +#endif 1.3687 + return; 1.3688 + } 1.3689 +#if defined(__APPLE__) 1.3690 + if (so_locked) { 1.3691 + sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep)); 1.3692 + } else { 1.3693 + sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep)); 1.3694 + } 1.3695 +#endif 1.3696 + if ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) || 1.3697 + (stcb->asoc.state & SCTP_STATE_COOKIE_ECHOED)) { 1.3698 + if ((notification == SCTP_NOTIFY_INTERFACE_DOWN) || 1.3699 + (notification == SCTP_NOTIFY_INTERFACE_UP) || 1.3700 + (notification == SCTP_NOTIFY_INTERFACE_CONFIRMED)) { 1.3701 + /* Don't report these in front states */ 1.3702 + return; 1.3703 + } 1.3704 + } 1.3705 + switch (notification) { 1.3706 + case SCTP_NOTIFY_ASSOC_UP: 1.3707 + if (stcb->asoc.assoc_up_sent == 0) { 1.3708 + sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, NULL, 0, so_locked); 1.3709 + stcb->asoc.assoc_up_sent = 1; 1.3710 + } 1.3711 + if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent == 0)) { 1.3712 + sctp_notify_adaptation_layer(stcb); 1.3713 + } 1.3714 + if (stcb->asoc.peer_supports_auth == 0) { 1.3715 + sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0, 1.3716 + NULL, so_locked); 1.3717 + } 1.3718 + break; 1.3719 + case SCTP_NOTIFY_ASSOC_DOWN: 1.3720 + sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, 0, so_locked); 1.3721 +#if defined(__Userspace__) 1.3722 + if (stcb->sctp_ep->recv_callback) { 1.3723 + if (stcb->sctp_socket) { 1.3724 + union sctp_sockstore addr; 1.3725 + struct sctp_rcvinfo rcv; 1.3726 + 1.3727 + memset(&addr, 0, sizeof(union sctp_sockstore)); 1.3728 + memset(&rcv, 0, sizeof(struct sctp_rcvinfo)); 1.3729 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.3730 + SCTP_TCB_UNLOCK(stcb); 1.3731 + stcb->sctp_ep->recv_callback(stcb->sctp_socket, addr, NULL, 0, rcv, 0, stcb->sctp_ep->ulp_info); 1.3732 + SCTP_TCB_LOCK(stcb); 1.3733 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.3734 + } 1.3735 + } 1.3736 +#endif 1.3737 + break; 1.3738 + case SCTP_NOTIFY_INTERFACE_DOWN: 1.3739 + { 1.3740 + struct sctp_nets *net; 1.3741 + 1.3742 + net = (struct sctp_nets *)data; 1.3743 + sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE, 1.3744 + (struct sockaddr *)&net->ro._l_addr, error); 1.3745 + break; 1.3746 + } 1.3747 + case SCTP_NOTIFY_INTERFACE_UP: 1.3748 + { 1.3749 + struct sctp_nets *net; 1.3750 + 1.3751 + net = (struct sctp_nets *)data; 1.3752 + sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE, 1.3753 + (struct sockaddr *)&net->ro._l_addr, error); 1.3754 + break; 1.3755 + } 1.3756 + case SCTP_NOTIFY_INTERFACE_CONFIRMED: 1.3757 + { 1.3758 + struct sctp_nets *net; 1.3759 + 1.3760 + net = (struct sctp_nets *)data; 1.3761 + sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED, 1.3762 + (struct sockaddr *)&net->ro._l_addr, error); 1.3763 + break; 1.3764 + } 1.3765 + case SCTP_NOTIFY_SPECIAL_SP_FAIL: 1.3766 + sctp_notify_send_failed2(stcb, error, 1.3767 + (struct sctp_stream_queue_pending *)data, so_locked); 1.3768 + break; 1.3769 + case SCTP_NOTIFY_SENT_DG_FAIL: 1.3770 + sctp_notify_send_failed(stcb, 1, error, 1.3771 + (struct sctp_tmit_chunk *)data, so_locked); 1.3772 + break; 1.3773 + case SCTP_NOTIFY_UNSENT_DG_FAIL: 1.3774 + sctp_notify_send_failed(stcb, 0, error, 1.3775 + (struct sctp_tmit_chunk *)data, so_locked); 1.3776 + break; 1.3777 + case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION: 1.3778 + { 1.3779 + uint32_t val; 1.3780 + val = *((uint32_t *)data); 1.3781 + 1.3782 + sctp_notify_partial_delivery_indication(stcb, error, val, so_locked); 1.3783 + break; 1.3784 + } 1.3785 + case SCTP_NOTIFY_ASSOC_LOC_ABORTED: 1.3786 + if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) || 1.3787 + ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) { 1.3788 + sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 0, so_locked); 1.3789 + } else { 1.3790 + sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 0, so_locked); 1.3791 + } 1.3792 + break; 1.3793 + case SCTP_NOTIFY_ASSOC_REM_ABORTED: 1.3794 + if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) || 1.3795 + ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) { 1.3796 + sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 1, so_locked); 1.3797 + } else { 1.3798 + sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 1, so_locked); 1.3799 + } 1.3800 + break; 1.3801 + case SCTP_NOTIFY_ASSOC_RESTART: 1.3802 + sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, so_locked); 1.3803 + if (stcb->asoc.peer_supports_auth == 0) { 1.3804 + sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0, 1.3805 + NULL, so_locked); 1.3806 + } 1.3807 + break; 1.3808 + case SCTP_NOTIFY_STR_RESET_SEND: 1.3809 + sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_OUTGOING_SSN); 1.3810 + break; 1.3811 + case SCTP_NOTIFY_STR_RESET_RECV: 1.3812 + sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_INCOMING); 1.3813 + break; 1.3814 + case SCTP_NOTIFY_STR_RESET_FAILED_OUT: 1.3815 + sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 1.3816 + (SCTP_STREAM_RESET_OUTGOING_SSN|SCTP_STREAM_RESET_FAILED)); 1.3817 + break; 1.3818 + case SCTP_NOTIFY_STR_RESET_DENIED_OUT: 1.3819 + sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 1.3820 + (SCTP_STREAM_RESET_OUTGOING_SSN|SCTP_STREAM_RESET_DENIED)); 1.3821 + break; 1.3822 + case SCTP_NOTIFY_STR_RESET_FAILED_IN: 1.3823 + sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 1.3824 + (SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_FAILED)); 1.3825 + break; 1.3826 + case SCTP_NOTIFY_STR_RESET_DENIED_IN: 1.3827 + sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), 1.3828 + (SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_DENIED)); 1.3829 + break; 1.3830 + case SCTP_NOTIFY_ASCONF_ADD_IP: 1.3831 + sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data, 1.3832 + error); 1.3833 + break; 1.3834 + case SCTP_NOTIFY_ASCONF_DELETE_IP: 1.3835 + sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data, 1.3836 + error); 1.3837 + break; 1.3838 + case SCTP_NOTIFY_ASCONF_SET_PRIMARY: 1.3839 + sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data, 1.3840 + error); 1.3841 + break; 1.3842 + case SCTP_NOTIFY_PEER_SHUTDOWN: 1.3843 + sctp_notify_shutdown_event(stcb); 1.3844 + break; 1.3845 + case SCTP_NOTIFY_AUTH_NEW_KEY: 1.3846 + sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY, error, 1.3847 + (uint16_t)(uintptr_t)data, 1.3848 + so_locked); 1.3849 + break; 1.3850 + case SCTP_NOTIFY_AUTH_FREE_KEY: 1.3851 + sctp_notify_authentication(stcb, SCTP_AUTH_FREE_KEY, error, 1.3852 + (uint16_t)(uintptr_t)data, 1.3853 + so_locked); 1.3854 + break; 1.3855 + case SCTP_NOTIFY_NO_PEER_AUTH: 1.3856 + sctp_notify_authentication(stcb, SCTP_AUTH_NO_AUTH, error, 1.3857 + (uint16_t)(uintptr_t)data, 1.3858 + so_locked); 1.3859 + break; 1.3860 + case SCTP_NOTIFY_SENDER_DRY: 1.3861 + sctp_notify_sender_dry_event(stcb, so_locked); 1.3862 + break; 1.3863 + case SCTP_NOTIFY_REMOTE_ERROR: 1.3864 + sctp_notify_remote_error(stcb, error, data); 1.3865 + break; 1.3866 + default: 1.3867 + SCTPDBG(SCTP_DEBUG_UTIL1, "%s: unknown notification %xh (%u)\n", 1.3868 + __FUNCTION__, notification, notification); 1.3869 + break; 1.3870 + } /* end switch */ 1.3871 +} 1.3872 + 1.3873 +void 1.3874 +sctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked 1.3875 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.3876 + SCTP_UNUSED 1.3877 +#endif 1.3878 + ) 1.3879 +{ 1.3880 + struct sctp_association *asoc; 1.3881 + struct sctp_stream_out *outs; 1.3882 + struct sctp_tmit_chunk *chk, *nchk; 1.3883 + struct sctp_stream_queue_pending *sp, *nsp; 1.3884 + int i; 1.3885 + 1.3886 + if (stcb == NULL) { 1.3887 + return; 1.3888 + } 1.3889 + asoc = &stcb->asoc; 1.3890 + if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) { 1.3891 + /* already being freed */ 1.3892 + return; 1.3893 + } 1.3894 +#if defined(__APPLE__) 1.3895 + if (so_locked) { 1.3896 + sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep)); 1.3897 + } else { 1.3898 + sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep)); 1.3899 + } 1.3900 +#endif 1.3901 + if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 1.3902 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 1.3903 + (asoc->state & SCTP_STATE_CLOSED_SOCKET)) { 1.3904 + return; 1.3905 + } 1.3906 + /* now through all the gunk freeing chunks */ 1.3907 + if (holds_lock == 0) { 1.3908 + SCTP_TCB_SEND_LOCK(stcb); 1.3909 + } 1.3910 + /* sent queue SHOULD be empty */ 1.3911 + TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) { 1.3912 + TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next); 1.3913 + asoc->sent_queue_cnt--; 1.3914 + if (chk->sent != SCTP_DATAGRAM_NR_ACKED) { 1.3915 + if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 1.3916 + asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 1.3917 +#ifdef INVARIANTS 1.3918 + } else { 1.3919 + panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 1.3920 +#endif 1.3921 + } 1.3922 + } 1.3923 + if (chk->data != NULL) { 1.3924 + sctp_free_bufspace(stcb, asoc, chk, 1); 1.3925 + sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 1.3926 + error, chk, so_locked); 1.3927 + if (chk->data) { 1.3928 + sctp_m_freem(chk->data); 1.3929 + chk->data = NULL; 1.3930 + } 1.3931 + } 1.3932 + sctp_free_a_chunk(stcb, chk, so_locked); 1.3933 + /*sa_ignore FREED_MEMORY*/ 1.3934 + } 1.3935 + /* pending send queue SHOULD be empty */ 1.3936 + TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) { 1.3937 + TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next); 1.3938 + asoc->send_queue_cnt--; 1.3939 + if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) { 1.3940 + asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--; 1.3941 +#ifdef INVARIANTS 1.3942 + } else { 1.3943 + panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number); 1.3944 +#endif 1.3945 + } 1.3946 + if (chk->data != NULL) { 1.3947 + sctp_free_bufspace(stcb, asoc, chk, 1); 1.3948 + sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 1.3949 + error, chk, so_locked); 1.3950 + if (chk->data) { 1.3951 + sctp_m_freem(chk->data); 1.3952 + chk->data = NULL; 1.3953 + } 1.3954 + } 1.3955 + sctp_free_a_chunk(stcb, chk, so_locked); 1.3956 + /*sa_ignore FREED_MEMORY*/ 1.3957 + } 1.3958 + for (i = 0; i < asoc->streamoutcnt; i++) { 1.3959 + /* For each stream */ 1.3960 + outs = &asoc->strmout[i]; 1.3961 + /* clean up any sends there */ 1.3962 + asoc->locked_on_sending = NULL; 1.3963 + TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) { 1.3964 + asoc->stream_queue_cnt--; 1.3965 + TAILQ_REMOVE(&outs->outqueue, sp, next); 1.3966 + sctp_free_spbufspace(stcb, asoc, sp); 1.3967 + if (sp->data) { 1.3968 + sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb, 1.3969 + error, (void *)sp, so_locked); 1.3970 + if (sp->data) { 1.3971 + sctp_m_freem(sp->data); 1.3972 + sp->data = NULL; 1.3973 + sp->tail_mbuf = NULL; 1.3974 + sp->length = 0; 1.3975 + } 1.3976 + } 1.3977 + if (sp->net) { 1.3978 + sctp_free_remote_addr(sp->net); 1.3979 + sp->net = NULL; 1.3980 + } 1.3981 + /* Free the chunk */ 1.3982 + sctp_free_a_strmoq(stcb, sp, so_locked); 1.3983 + /*sa_ignore FREED_MEMORY*/ 1.3984 + } 1.3985 + } 1.3986 + 1.3987 + if (holds_lock == 0) { 1.3988 + SCTP_TCB_SEND_UNLOCK(stcb); 1.3989 + } 1.3990 +} 1.3991 + 1.3992 +void 1.3993 +sctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t error, 1.3994 + struct sctp_abort_chunk *abort, int so_locked 1.3995 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.3996 + SCTP_UNUSED 1.3997 +#endif 1.3998 + ) 1.3999 +{ 1.4000 + if (stcb == NULL) { 1.4001 + return; 1.4002 + } 1.4003 +#if defined(__APPLE__) 1.4004 + if (so_locked) { 1.4005 + sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep)); 1.4006 + } else { 1.4007 + sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep)); 1.4008 + } 1.4009 +#endif 1.4010 + if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 1.4011 + ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 1.4012 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) { 1.4013 + stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED; 1.4014 + } 1.4015 + if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 1.4016 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 1.4017 + (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) { 1.4018 + return; 1.4019 + } 1.4020 + /* Tell them we lost the asoc */ 1.4021 + sctp_report_all_outbound(stcb, error, 1, so_locked); 1.4022 + if (from_peer) { 1.4023 + sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked); 1.4024 + } else { 1.4025 + sctp_ulp_notify(SCTP_NOTIFY_ASSOC_LOC_ABORTED, stcb, error, abort, so_locked); 1.4026 + } 1.4027 +} 1.4028 + 1.4029 +void 1.4030 +sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1.4031 + struct mbuf *m, int iphlen, 1.4032 + struct sockaddr *src, struct sockaddr *dst, 1.4033 + struct sctphdr *sh, struct mbuf *op_err, 1.4034 +#if defined(__FreeBSD__) 1.4035 + uint8_t use_mflowid, uint32_t mflowid, 1.4036 +#endif 1.4037 + uint32_t vrf_id, uint16_t port) 1.4038 +{ 1.4039 + uint32_t vtag; 1.4040 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4041 + struct socket *so; 1.4042 +#endif 1.4043 + 1.4044 + vtag = 0; 1.4045 + if (stcb != NULL) { 1.4046 + /* We have a TCB to abort, send notification too */ 1.4047 + vtag = stcb->asoc.peer_vtag; 1.4048 + sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED); 1.4049 + /* get the assoc vrf id and table id */ 1.4050 + vrf_id = stcb->asoc.vrf_id; 1.4051 + stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 1.4052 + } 1.4053 + sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err, 1.4054 +#if defined(__FreeBSD__) 1.4055 + use_mflowid, mflowid, 1.4056 +#endif 1.4057 + vrf_id, port); 1.4058 + if (stcb != NULL) { 1.4059 + /* Ok, now lets free it */ 1.4060 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4061 + so = SCTP_INP_SO(inp); 1.4062 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.4063 + SCTP_TCB_UNLOCK(stcb); 1.4064 + SCTP_SOCKET_LOCK(so, 1); 1.4065 + SCTP_TCB_LOCK(stcb); 1.4066 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.4067 +#endif 1.4068 + SCTP_STAT_INCR_COUNTER32(sctps_aborted); 1.4069 + if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 1.4070 + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 1.4071 + SCTP_STAT_DECR_GAUGE32(sctps_currestab); 1.4072 + } 1.4073 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_4); 1.4074 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4075 + SCTP_SOCKET_UNLOCK(so, 1); 1.4076 +#endif 1.4077 + } 1.4078 +} 1.4079 +#ifdef SCTP_ASOCLOG_OF_TSNS 1.4080 +void 1.4081 +sctp_print_out_track_log(struct sctp_tcb *stcb) 1.4082 +{ 1.4083 +#ifdef NOSIY_PRINTS 1.4084 + int i; 1.4085 + SCTP_PRINTF("Last ep reason:%x\n", stcb->sctp_ep->last_abort_code); 1.4086 + SCTP_PRINTF("IN bound TSN log-aaa\n"); 1.4087 + if ((stcb->asoc.tsn_in_at == 0) && (stcb->asoc.tsn_in_wrapped == 0)) { 1.4088 + SCTP_PRINTF("None rcvd\n"); 1.4089 + goto none_in; 1.4090 + } 1.4091 + if (stcb->asoc.tsn_in_wrapped) { 1.4092 + for (i = stcb->asoc.tsn_in_at; i < SCTP_TSN_LOG_SIZE; i++) { 1.4093 + SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 1.4094 + stcb->asoc.in_tsnlog[i].tsn, 1.4095 + stcb->asoc.in_tsnlog[i].strm, 1.4096 + stcb->asoc.in_tsnlog[i].seq, 1.4097 + stcb->asoc.in_tsnlog[i].flgs, 1.4098 + stcb->asoc.in_tsnlog[i].sz); 1.4099 + } 1.4100 + } 1.4101 + if (stcb->asoc.tsn_in_at) { 1.4102 + for (i = 0; i < stcb->asoc.tsn_in_at; i++) { 1.4103 + SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 1.4104 + stcb->asoc.in_tsnlog[i].tsn, 1.4105 + stcb->asoc.in_tsnlog[i].strm, 1.4106 + stcb->asoc.in_tsnlog[i].seq, 1.4107 + stcb->asoc.in_tsnlog[i].flgs, 1.4108 + stcb->asoc.in_tsnlog[i].sz); 1.4109 + } 1.4110 + } 1.4111 + none_in: 1.4112 + SCTP_PRINTF("OUT bound TSN log-aaa\n"); 1.4113 + if ((stcb->asoc.tsn_out_at == 0) && 1.4114 + (stcb->asoc.tsn_out_wrapped == 0)) { 1.4115 + SCTP_PRINTF("None sent\n"); 1.4116 + } 1.4117 + if (stcb->asoc.tsn_out_wrapped) { 1.4118 + for (i = stcb->asoc.tsn_out_at; i < SCTP_TSN_LOG_SIZE; i++) { 1.4119 + SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 1.4120 + stcb->asoc.out_tsnlog[i].tsn, 1.4121 + stcb->asoc.out_tsnlog[i].strm, 1.4122 + stcb->asoc.out_tsnlog[i].seq, 1.4123 + stcb->asoc.out_tsnlog[i].flgs, 1.4124 + stcb->asoc.out_tsnlog[i].sz); 1.4125 + } 1.4126 + } 1.4127 + if (stcb->asoc.tsn_out_at) { 1.4128 + for (i = 0; i < stcb->asoc.tsn_out_at; i++) { 1.4129 + SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n", 1.4130 + stcb->asoc.out_tsnlog[i].tsn, 1.4131 + stcb->asoc.out_tsnlog[i].strm, 1.4132 + stcb->asoc.out_tsnlog[i].seq, 1.4133 + stcb->asoc.out_tsnlog[i].flgs, 1.4134 + stcb->asoc.out_tsnlog[i].sz); 1.4135 + } 1.4136 + } 1.4137 +#endif 1.4138 +} 1.4139 +#endif 1.4140 + 1.4141 +void 1.4142 +sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb, 1.4143 + struct mbuf *op_err, 1.4144 + int so_locked 1.4145 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.4146 + SCTP_UNUSED 1.4147 +#endif 1.4148 +) 1.4149 +{ 1.4150 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4151 + struct socket *so; 1.4152 +#endif 1.4153 + 1.4154 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4155 + so = SCTP_INP_SO(inp); 1.4156 +#endif 1.4157 +#if defined(__APPLE__) 1.4158 + if (so_locked) { 1.4159 + sctp_lock_assert(SCTP_INP_SO(inp)); 1.4160 + } else { 1.4161 + sctp_unlock_assert(SCTP_INP_SO(inp)); 1.4162 + } 1.4163 +#endif 1.4164 + if (stcb == NULL) { 1.4165 + /* Got to have a TCB */ 1.4166 + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 1.4167 + if (LIST_EMPTY(&inp->sctp_asoc_list)) { 1.4168 +#if defined(__APPLE__) 1.4169 + if (!so_locked) { 1.4170 + SCTP_SOCKET_LOCK(so, 1); 1.4171 + } 1.4172 +#endif 1.4173 + sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, 1.4174 + SCTP_CALLED_DIRECTLY_NOCMPSET); 1.4175 +#if defined(__APPLE__) 1.4176 + if (!so_locked) { 1.4177 + SCTP_SOCKET_UNLOCK(so, 1); 1.4178 + } 1.4179 +#endif 1.4180 + } 1.4181 + } 1.4182 + return; 1.4183 + } else { 1.4184 + stcb->asoc.state |= SCTP_STATE_WAS_ABORTED; 1.4185 + } 1.4186 + /* notify the ulp */ 1.4187 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) { 1.4188 + sctp_abort_notification(stcb, 0, 0, NULL, so_locked); 1.4189 + } 1.4190 + /* notify the peer */ 1.4191 + sctp_send_abort_tcb(stcb, op_err, so_locked); 1.4192 + SCTP_STAT_INCR_COUNTER32(sctps_aborted); 1.4193 + if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) || 1.4194 + (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) { 1.4195 + SCTP_STAT_DECR_GAUGE32(sctps_currestab); 1.4196 + } 1.4197 + /* now free the asoc */ 1.4198 +#ifdef SCTP_ASOCLOG_OF_TSNS 1.4199 + sctp_print_out_track_log(stcb); 1.4200 +#endif 1.4201 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4202 + if (!so_locked) { 1.4203 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.4204 + SCTP_TCB_UNLOCK(stcb); 1.4205 + SCTP_SOCKET_LOCK(so, 1); 1.4206 + SCTP_TCB_LOCK(stcb); 1.4207 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.4208 + } 1.4209 +#endif 1.4210 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_5); 1.4211 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4212 + if (!so_locked) { 1.4213 + SCTP_SOCKET_UNLOCK(so, 1); 1.4214 + } 1.4215 +#endif 1.4216 +} 1.4217 + 1.4218 +void 1.4219 +sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, 1.4220 + struct sockaddr *src, struct sockaddr *dst, 1.4221 + struct sctphdr *sh, struct sctp_inpcb *inp, 1.4222 +#if defined(__FreeBSD__) 1.4223 + uint8_t use_mflowid, uint32_t mflowid, 1.4224 +#endif 1.4225 + uint32_t vrf_id, uint16_t port) 1.4226 +{ 1.4227 + struct sctp_chunkhdr *ch, chunk_buf; 1.4228 + unsigned int chk_length; 1.4229 + int contains_init_chunk; 1.4230 + 1.4231 + SCTP_STAT_INCR_COUNTER32(sctps_outoftheblue); 1.4232 + /* Generate a TO address for future reference */ 1.4233 + if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { 1.4234 + if (LIST_EMPTY(&inp->sctp_asoc_list)) { 1.4235 +#if defined(__APPLE__) 1.4236 + SCTP_SOCKET_LOCK(SCTP_INP_SO(inp), 1); 1.4237 +#endif 1.4238 + sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT, 1.4239 + SCTP_CALLED_DIRECTLY_NOCMPSET); 1.4240 +#if defined(__APPLE__) 1.4241 + SCTP_SOCKET_UNLOCK(SCTP_INP_SO(inp), 1); 1.4242 +#endif 1.4243 + } 1.4244 + } 1.4245 + contains_init_chunk = 0; 1.4246 + ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, 1.4247 + sizeof(*ch), (uint8_t *) & chunk_buf); 1.4248 + while (ch != NULL) { 1.4249 + chk_length = ntohs(ch->chunk_length); 1.4250 + if (chk_length < sizeof(*ch)) { 1.4251 + /* break to abort land */ 1.4252 + break; 1.4253 + } 1.4254 + switch (ch->chunk_type) { 1.4255 + case SCTP_INIT: 1.4256 + contains_init_chunk = 1; 1.4257 + break; 1.4258 + case SCTP_COOKIE_ECHO: 1.4259 + /* We hit here only if the assoc is being freed */ 1.4260 + return; 1.4261 + case SCTP_PACKET_DROPPED: 1.4262 + /* we don't respond to pkt-dropped */ 1.4263 + return; 1.4264 + case SCTP_ABORT_ASSOCIATION: 1.4265 + /* we don't respond with an ABORT to an ABORT */ 1.4266 + return; 1.4267 + case SCTP_SHUTDOWN_COMPLETE: 1.4268 + /* 1.4269 + * we ignore it since we are not waiting for it and 1.4270 + * peer is gone 1.4271 + */ 1.4272 + return; 1.4273 + case SCTP_SHUTDOWN_ACK: 1.4274 + sctp_send_shutdown_complete2(src, dst, sh, 1.4275 +#if defined(__FreeBSD__) 1.4276 + use_mflowid, mflowid, 1.4277 +#endif 1.4278 + vrf_id, port); 1.4279 + return; 1.4280 + default: 1.4281 + break; 1.4282 + } 1.4283 + offset += SCTP_SIZE32(chk_length); 1.4284 + ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, 1.4285 + sizeof(*ch), (uint8_t *) & chunk_buf); 1.4286 + } 1.4287 + if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || 1.4288 + ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && 1.4289 + (contains_init_chunk == 0))) { 1.4290 + sctp_send_abort(m, iphlen, src, dst, sh, 0, NULL, 1.4291 +#if defined(__FreeBSD__) 1.4292 + use_mflowid, mflowid, 1.4293 +#endif 1.4294 + vrf_id, port); 1.4295 + } 1.4296 +} 1.4297 + 1.4298 +/* 1.4299 + * check the inbound datagram to make sure there is not an abort inside it, 1.4300 + * if there is return 1, else return 0. 1.4301 + */ 1.4302 +int 1.4303 +sctp_is_there_an_abort_here(struct mbuf *m, int iphlen, uint32_t * vtagfill) 1.4304 +{ 1.4305 + struct sctp_chunkhdr *ch; 1.4306 + struct sctp_init_chunk *init_chk, chunk_buf; 1.4307 + int offset; 1.4308 + unsigned int chk_length; 1.4309 + 1.4310 + offset = iphlen + sizeof(struct sctphdr); 1.4311 + ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, sizeof(*ch), 1.4312 + (uint8_t *) & chunk_buf); 1.4313 + while (ch != NULL) { 1.4314 + chk_length = ntohs(ch->chunk_length); 1.4315 + if (chk_length < sizeof(*ch)) { 1.4316 + /* packet is probably corrupt */ 1.4317 + break; 1.4318 + } 1.4319 + /* we seem to be ok, is it an abort? */ 1.4320 + if (ch->chunk_type == SCTP_ABORT_ASSOCIATION) { 1.4321 + /* yep, tell them */ 1.4322 + return (1); 1.4323 + } 1.4324 + if (ch->chunk_type == SCTP_INITIATION) { 1.4325 + /* need to update the Vtag */ 1.4326 + init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m, 1.4327 + offset, sizeof(*init_chk), (uint8_t *) & chunk_buf); 1.4328 + if (init_chk != NULL) { 1.4329 + *vtagfill = ntohl(init_chk->init.initiate_tag); 1.4330 + } 1.4331 + } 1.4332 + /* Nope, move to the next chunk */ 1.4333 + offset += SCTP_SIZE32(chk_length); 1.4334 + ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, 1.4335 + sizeof(*ch), (uint8_t *) & chunk_buf); 1.4336 + } 1.4337 + return (0); 1.4338 +} 1.4339 + 1.4340 +/* 1.4341 + * currently (2/02), ifa_addr embeds scope_id's and don't have sin6_scope_id 1.4342 + * set (i.e. it's 0) so, create this function to compare link local scopes 1.4343 + */ 1.4344 +#ifdef INET6 1.4345 +uint32_t 1.4346 +sctp_is_same_scope(struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2) 1.4347 +{ 1.4348 +#if defined(__Userspace__) 1.4349 + /*__Userspace__ Returning 1 here always */ 1.4350 +#endif 1.4351 +#if defined(SCTP_EMBEDDED_V6_SCOPE) 1.4352 + struct sockaddr_in6 a, b; 1.4353 + 1.4354 + /* save copies */ 1.4355 + a = *addr1; 1.4356 + b = *addr2; 1.4357 + 1.4358 + if (a.sin6_scope_id == 0) 1.4359 +#ifdef SCTP_KAME 1.4360 + if (sa6_recoverscope(&a)) { 1.4361 +#else 1.4362 + if (in6_recoverscope(&a, &a.sin6_addr, NULL)) { 1.4363 +#endif /* SCTP_KAME */ 1.4364 + /* can't get scope, so can't match */ 1.4365 + return (0); 1.4366 + } 1.4367 + if (b.sin6_scope_id == 0) 1.4368 +#ifdef SCTP_KAME 1.4369 + if (sa6_recoverscope(&b)) { 1.4370 +#else 1.4371 + if (in6_recoverscope(&b, &b.sin6_addr, NULL)) { 1.4372 +#endif /* SCTP_KAME */ 1.4373 + /* can't get scope, so can't match */ 1.4374 + return (0); 1.4375 + } 1.4376 + if (a.sin6_scope_id != b.sin6_scope_id) 1.4377 + return (0); 1.4378 +#else 1.4379 + if (addr1->sin6_scope_id != addr2->sin6_scope_id) 1.4380 + return (0); 1.4381 +#endif /* SCTP_EMBEDDED_V6_SCOPE */ 1.4382 + 1.4383 + return (1); 1.4384 +} 1.4385 + 1.4386 +#if defined(SCTP_EMBEDDED_V6_SCOPE) 1.4387 +/* 1.4388 + * returns a sockaddr_in6 with embedded scope recovered and removed 1.4389 + */ 1.4390 +struct sockaddr_in6 * 1.4391 +sctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store) 1.4392 +{ 1.4393 + /* check and strip embedded scope junk */ 1.4394 + if (addr->sin6_family == AF_INET6) { 1.4395 + if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) { 1.4396 + if (addr->sin6_scope_id == 0) { 1.4397 + *store = *addr; 1.4398 +#ifdef SCTP_KAME 1.4399 + if (!sa6_recoverscope(store)) { 1.4400 +#else 1.4401 + if (!in6_recoverscope(store, &store->sin6_addr, 1.4402 + NULL)) { 1.4403 +#endif /* SCTP_KAME */ 1.4404 + /* use the recovered scope */ 1.4405 + addr = store; 1.4406 + } 1.4407 + } else { 1.4408 + /* else, return the original "to" addr */ 1.4409 + in6_clearscope(&addr->sin6_addr); 1.4410 + } 1.4411 + } 1.4412 + } 1.4413 + return (addr); 1.4414 +} 1.4415 +#endif /* SCTP_EMBEDDED_V6_SCOPE */ 1.4416 +#endif 1.4417 + 1.4418 +/* 1.4419 + * are the two addresses the same? currently a "scopeless" check returns: 1 1.4420 + * if same, 0 if not 1.4421 + */ 1.4422 +int 1.4423 +sctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2) 1.4424 +{ 1.4425 + 1.4426 + /* must be valid */ 1.4427 + if (sa1 == NULL || sa2 == NULL) 1.4428 + return (0); 1.4429 + 1.4430 + /* must be the same family */ 1.4431 + if (sa1->sa_family != sa2->sa_family) 1.4432 + return (0); 1.4433 + 1.4434 + switch (sa1->sa_family) { 1.4435 +#ifdef INET6 1.4436 + case AF_INET6: 1.4437 + { 1.4438 + /* IPv6 addresses */ 1.4439 + struct sockaddr_in6 *sin6_1, *sin6_2; 1.4440 + 1.4441 + sin6_1 = (struct sockaddr_in6 *)sa1; 1.4442 + sin6_2 = (struct sockaddr_in6 *)sa2; 1.4443 + return (SCTP6_ARE_ADDR_EQUAL(sin6_1, 1.4444 + sin6_2)); 1.4445 + } 1.4446 +#endif 1.4447 +#ifdef INET 1.4448 + case AF_INET: 1.4449 + { 1.4450 + /* IPv4 addresses */ 1.4451 + struct sockaddr_in *sin_1, *sin_2; 1.4452 + 1.4453 + sin_1 = (struct sockaddr_in *)sa1; 1.4454 + sin_2 = (struct sockaddr_in *)sa2; 1.4455 + return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr); 1.4456 + } 1.4457 +#endif 1.4458 +#if defined(__Userspace__) 1.4459 + case AF_CONN: 1.4460 + { 1.4461 + struct sockaddr_conn *sconn_1, *sconn_2; 1.4462 + 1.4463 + sconn_1 = (struct sockaddr_conn *)sa1; 1.4464 + sconn_2 = (struct sockaddr_conn *)sa2; 1.4465 + return (sconn_1->sconn_addr == sconn_2->sconn_addr); 1.4466 + } 1.4467 +#endif 1.4468 + default: 1.4469 + /* we don't do these... */ 1.4470 + return (0); 1.4471 + } 1.4472 +} 1.4473 + 1.4474 +void 1.4475 +sctp_print_address(struct sockaddr *sa) 1.4476 +{ 1.4477 +#ifdef INET6 1.4478 +#if defined(__FreeBSD__) && __FreeBSD_version >= 700000 1.4479 + char ip6buf[INET6_ADDRSTRLEN]; 1.4480 +#endif 1.4481 +#endif 1.4482 + 1.4483 + switch (sa->sa_family) { 1.4484 +#ifdef INET6 1.4485 + case AF_INET6: 1.4486 + { 1.4487 + struct sockaddr_in6 *sin6; 1.4488 + 1.4489 + sin6 = (struct sockaddr_in6 *)sa; 1.4490 +#if defined(__Userspace__) 1.4491 + SCTP_PRINTF("IPv6 address: %x:%x:%x:%x:%x:%x:%x:%x:port:%d scope:%u\n", 1.4492 + ntohs(sin6->sin6_addr.s6_addr16[0]), 1.4493 + ntohs(sin6->sin6_addr.s6_addr16[1]), 1.4494 + ntohs(sin6->sin6_addr.s6_addr16[2]), 1.4495 + ntohs(sin6->sin6_addr.s6_addr16[3]), 1.4496 + ntohs(sin6->sin6_addr.s6_addr16[4]), 1.4497 + ntohs(sin6->sin6_addr.s6_addr16[5]), 1.4498 + ntohs(sin6->sin6_addr.s6_addr16[6]), 1.4499 + ntohs(sin6->sin6_addr.s6_addr16[7]), 1.4500 + ntohs(sin6->sin6_port), 1.4501 + sin6->sin6_scope_id); 1.4502 +#else 1.4503 +#if defined(__FreeBSD__) && __FreeBSD_version >= 700000 1.4504 + SCTP_PRINTF("IPv6 address: %s:port:%d scope:%u\n", 1.4505 + ip6_sprintf(ip6buf, &sin6->sin6_addr), 1.4506 + ntohs(sin6->sin6_port), 1.4507 + sin6->sin6_scope_id); 1.4508 +#else 1.4509 + SCTP_PRINTF("IPv6 address: %s:port:%d scope:%u\n", 1.4510 + ip6_sprintf(&sin6->sin6_addr), 1.4511 + ntohs(sin6->sin6_port), 1.4512 + sin6->sin6_scope_id); 1.4513 +#endif 1.4514 +#endif 1.4515 + break; 1.4516 + } 1.4517 +#endif 1.4518 +#ifdef INET 1.4519 + case AF_INET: 1.4520 + { 1.4521 + struct sockaddr_in *sin; 1.4522 + unsigned char *p; 1.4523 + 1.4524 + sin = (struct sockaddr_in *)sa; 1.4525 + p = (unsigned char *)&sin->sin_addr; 1.4526 + SCTP_PRINTF("IPv4 address: %u.%u.%u.%u:%d\n", 1.4527 + p[0], p[1], p[2], p[3], ntohs(sin->sin_port)); 1.4528 + break; 1.4529 + } 1.4530 +#endif 1.4531 +#if defined(__Userspace__) 1.4532 + case AF_CONN: 1.4533 + { 1.4534 + struct sockaddr_conn *sconn; 1.4535 + 1.4536 + sconn = (struct sockaddr_conn *)sa; 1.4537 + SCTP_PRINTF("AF_CONN address: %p\n", sconn->sconn_addr); 1.4538 + break; 1.4539 + } 1.4540 +#endif 1.4541 + default: 1.4542 + SCTP_PRINTF("?\n"); 1.4543 + break; 1.4544 + } 1.4545 +} 1.4546 + 1.4547 +void 1.4548 +sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp, 1.4549 + struct sctp_inpcb *new_inp, 1.4550 + struct sctp_tcb *stcb, 1.4551 + int waitflags) 1.4552 +{ 1.4553 + /* 1.4554 + * go through our old INP and pull off any control structures that 1.4555 + * belong to stcb and move then to the new inp. 1.4556 + */ 1.4557 + struct socket *old_so, *new_so; 1.4558 + struct sctp_queued_to_read *control, *nctl; 1.4559 + struct sctp_readhead tmp_queue; 1.4560 + struct mbuf *m; 1.4561 + int error = 0; 1.4562 + 1.4563 + old_so = old_inp->sctp_socket; 1.4564 + new_so = new_inp->sctp_socket; 1.4565 + TAILQ_INIT(&tmp_queue); 1.4566 +#if defined(__FreeBSD__) && __FreeBSD_version < 700000 1.4567 + SOCKBUF_LOCK(&(old_so->so_rcv)); 1.4568 +#endif 1.4569 +#if defined(__FreeBSD__) || defined(__APPLE__) 1.4570 + error = sblock(&old_so->so_rcv, waitflags); 1.4571 +#endif 1.4572 +#if defined(__FreeBSD__) && __FreeBSD_version < 700000 1.4573 + SOCKBUF_UNLOCK(&(old_so->so_rcv)); 1.4574 +#endif 1.4575 + if (error) { 1.4576 + /* Gak, can't get sblock, we have a problem. 1.4577 + * data will be left stranded.. and we 1.4578 + * don't dare look at it since the 1.4579 + * other thread may be reading something. 1.4580 + * Oh well, its a screwed up app that does 1.4581 + * a peeloff OR a accept while reading 1.4582 + * from the main socket... actually its 1.4583 + * only the peeloff() case, since I think 1.4584 + * read will fail on a listening socket.. 1.4585 + */ 1.4586 + return; 1.4587 + } 1.4588 + /* lock the socket buffers */ 1.4589 + SCTP_INP_READ_LOCK(old_inp); 1.4590 + TAILQ_FOREACH_SAFE(control, &old_inp->read_queue, next, nctl) { 1.4591 + /* Pull off all for out target stcb */ 1.4592 + if (control->stcb == stcb) { 1.4593 + /* remove it we want it */ 1.4594 + TAILQ_REMOVE(&old_inp->read_queue, control, next); 1.4595 + TAILQ_INSERT_TAIL(&tmp_queue, control, next); 1.4596 + m = control->data; 1.4597 + while (m) { 1.4598 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.4599 + sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE,SCTP_BUF_LEN(m)); 1.4600 + } 1.4601 + sctp_sbfree(control, stcb, &old_so->so_rcv, m); 1.4602 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.4603 + sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0); 1.4604 + } 1.4605 + m = SCTP_BUF_NEXT(m); 1.4606 + } 1.4607 + } 1.4608 + } 1.4609 + SCTP_INP_READ_UNLOCK(old_inp); 1.4610 + /* Remove the sb-lock on the old socket */ 1.4611 +#if defined(__FreeBSD__) && __FreeBSD_version < 700000 1.4612 + SOCKBUF_LOCK(&(old_so->so_rcv)); 1.4613 +#endif 1.4614 +#if defined(__APPLE__) 1.4615 + sbunlock(&old_so->so_rcv, 1); 1.4616 +#endif 1.4617 + 1.4618 +#if defined(__FreeBSD__) 1.4619 + sbunlock(&old_so->so_rcv); 1.4620 +#endif 1.4621 +#if defined(__FreeBSD__) && __FreeBSD_version < 700000 1.4622 + SOCKBUF_UNLOCK(&(old_so->so_rcv)); 1.4623 +#endif 1.4624 + /* Now we move them over to the new socket buffer */ 1.4625 + SCTP_INP_READ_LOCK(new_inp); 1.4626 + TAILQ_FOREACH_SAFE(control, &tmp_queue, next, nctl) { 1.4627 + TAILQ_INSERT_TAIL(&new_inp->read_queue, control, next); 1.4628 + m = control->data; 1.4629 + while (m) { 1.4630 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.4631 + sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m)); 1.4632 + } 1.4633 + sctp_sballoc(stcb, &new_so->so_rcv, m); 1.4634 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.4635 + sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0); 1.4636 + } 1.4637 + m = SCTP_BUF_NEXT(m); 1.4638 + } 1.4639 + } 1.4640 + SCTP_INP_READ_UNLOCK(new_inp); 1.4641 +} 1.4642 + 1.4643 +void 1.4644 +sctp_add_to_readq(struct sctp_inpcb *inp, 1.4645 + struct sctp_tcb *stcb, 1.4646 + struct sctp_queued_to_read *control, 1.4647 + struct sockbuf *sb, 1.4648 + int end, 1.4649 + int inp_read_lock_held, 1.4650 + int so_locked 1.4651 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.4652 + SCTP_UNUSED 1.4653 +#endif 1.4654 + ) 1.4655 +{ 1.4656 + /* 1.4657 + * Here we must place the control on the end of the socket read 1.4658 + * queue AND increment sb_cc so that select will work properly on 1.4659 + * read. 1.4660 + */ 1.4661 + struct mbuf *m, *prev = NULL; 1.4662 + 1.4663 + if (inp == NULL) { 1.4664 + /* Gak, TSNH!! */ 1.4665 +#ifdef INVARIANTS 1.4666 + panic("Gak, inp NULL on add_to_readq"); 1.4667 +#endif 1.4668 + return; 1.4669 + } 1.4670 +#if defined(__APPLE__) 1.4671 + if (so_locked) { 1.4672 + sctp_lock_assert(SCTP_INP_SO(inp)); 1.4673 + } else { 1.4674 + sctp_unlock_assert(SCTP_INP_SO(inp)); 1.4675 + } 1.4676 +#endif 1.4677 + if (inp_read_lock_held == 0) 1.4678 + SCTP_INP_READ_LOCK(inp); 1.4679 + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) { 1.4680 + sctp_free_remote_addr(control->whoFrom); 1.4681 + if (control->data) { 1.4682 + sctp_m_freem(control->data); 1.4683 + control->data = NULL; 1.4684 + } 1.4685 + SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control); 1.4686 + if (inp_read_lock_held == 0) 1.4687 + SCTP_INP_READ_UNLOCK(inp); 1.4688 + return; 1.4689 + } 1.4690 + if (!(control->spec_flags & M_NOTIFICATION)) { 1.4691 + atomic_add_int(&inp->total_recvs, 1); 1.4692 + if (!control->do_not_ref_stcb) { 1.4693 + atomic_add_int(&stcb->total_recvs, 1); 1.4694 + } 1.4695 + } 1.4696 + m = control->data; 1.4697 + control->held_length = 0; 1.4698 + control->length = 0; 1.4699 + while (m) { 1.4700 + if (SCTP_BUF_LEN(m) == 0) { 1.4701 + /* Skip mbufs with NO length */ 1.4702 + if (prev == NULL) { 1.4703 + /* First one */ 1.4704 + control->data = sctp_m_free(m); 1.4705 + m = control->data; 1.4706 + } else { 1.4707 + SCTP_BUF_NEXT(prev) = sctp_m_free(m); 1.4708 + m = SCTP_BUF_NEXT(prev); 1.4709 + } 1.4710 + if (m == NULL) { 1.4711 + control->tail_mbuf = prev; 1.4712 + } 1.4713 + continue; 1.4714 + } 1.4715 + prev = m; 1.4716 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.4717 + sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m)); 1.4718 + } 1.4719 + sctp_sballoc(stcb, sb, m); 1.4720 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.4721 + sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0); 1.4722 + } 1.4723 + atomic_add_int(&control->length, SCTP_BUF_LEN(m)); 1.4724 + m = SCTP_BUF_NEXT(m); 1.4725 + } 1.4726 + if (prev != NULL) { 1.4727 + control->tail_mbuf = prev; 1.4728 + } else { 1.4729 + /* Everything got collapsed out?? */ 1.4730 + sctp_free_remote_addr(control->whoFrom); 1.4731 + SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control); 1.4732 + if (inp_read_lock_held == 0) 1.4733 + SCTP_INP_READ_UNLOCK(inp); 1.4734 + return; 1.4735 + } 1.4736 + if (end) { 1.4737 + control->end_added = 1; 1.4738 + } 1.4739 +#if defined(__Userspace__) 1.4740 + if (inp->recv_callback) { 1.4741 + if (inp_read_lock_held == 0) 1.4742 + SCTP_INP_READ_UNLOCK(inp); 1.4743 + if (control->end_added == 1) { 1.4744 + struct socket *so; 1.4745 + struct mbuf *m; 1.4746 + char *buffer; 1.4747 + struct sctp_rcvinfo rcv; 1.4748 + union sctp_sockstore addr; 1.4749 + int flags; 1.4750 + 1.4751 + if ((buffer = malloc(control->length)) == NULL) { 1.4752 + return; 1.4753 + } 1.4754 + so = stcb->sctp_socket; 1.4755 + for (m = control->data; m; m = SCTP_BUF_NEXT(m)) { 1.4756 + sctp_sbfree(control, control->stcb, &so->so_rcv, m); 1.4757 + } 1.4758 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.4759 + SCTP_TCB_UNLOCK(stcb); 1.4760 + m_copydata(control->data, 0, control->length, buffer); 1.4761 + memset(&rcv, 0, sizeof(struct sctp_rcvinfo)); 1.4762 + rcv.rcv_sid = control->sinfo_stream; 1.4763 + rcv.rcv_ssn = control->sinfo_ssn; 1.4764 + rcv.rcv_flags = control->sinfo_flags; 1.4765 + rcv.rcv_ppid = control->sinfo_ppid; 1.4766 + rcv.rcv_tsn = control->sinfo_tsn; 1.4767 + rcv.rcv_cumtsn = control->sinfo_cumtsn; 1.4768 + rcv.rcv_context = control->sinfo_context; 1.4769 + rcv.rcv_assoc_id = control->sinfo_assoc_id; 1.4770 + memset(&addr, 0, sizeof(union sctp_sockstore)); 1.4771 + switch (control->whoFrom->ro._l_addr.sa.sa_family) { 1.4772 +#ifdef INET 1.4773 + case AF_INET: 1.4774 + addr.sin = control->whoFrom->ro._l_addr.sin; 1.4775 + break; 1.4776 +#endif 1.4777 +#ifdef INET6 1.4778 + case AF_INET6: 1.4779 + addr.sin6 = control->whoFrom->ro._l_addr.sin6; 1.4780 + break; 1.4781 +#endif 1.4782 + case AF_CONN: 1.4783 + addr.sconn = control->whoFrom->ro._l_addr.sconn; 1.4784 + break; 1.4785 + default: 1.4786 + addr.sa = control->whoFrom->ro._l_addr.sa; 1.4787 + break; 1.4788 + } 1.4789 + flags = MSG_EOR; 1.4790 + if (control->spec_flags & M_NOTIFICATION) { 1.4791 + flags |= MSG_NOTIFICATION; 1.4792 + } 1.4793 + inp->recv_callback(so, addr, buffer, control->length, rcv, flags, inp->ulp_info); 1.4794 + SCTP_TCB_LOCK(stcb); 1.4795 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.4796 + sctp_free_remote_addr(control->whoFrom); 1.4797 + control->whoFrom = NULL; 1.4798 + sctp_m_freem(control->data); 1.4799 + control->data = NULL; 1.4800 + control->length = 0; 1.4801 + sctp_free_a_readq(stcb, control); 1.4802 + } 1.4803 + return; 1.4804 + } 1.4805 +#endif 1.4806 + TAILQ_INSERT_TAIL(&inp->read_queue, control, next); 1.4807 + if (inp_read_lock_held == 0) 1.4808 + SCTP_INP_READ_UNLOCK(inp); 1.4809 + if (inp && inp->sctp_socket) { 1.4810 + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 1.4811 + SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); 1.4812 + } else { 1.4813 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4814 + struct socket *so; 1.4815 + 1.4816 + so = SCTP_INP_SO(inp); 1.4817 + if (!so_locked) { 1.4818 + if (stcb) { 1.4819 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.4820 + SCTP_TCB_UNLOCK(stcb); 1.4821 + } 1.4822 + SCTP_SOCKET_LOCK(so, 1); 1.4823 + if (stcb) { 1.4824 + SCTP_TCB_LOCK(stcb); 1.4825 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.4826 + } 1.4827 + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 1.4828 + SCTP_SOCKET_UNLOCK(so, 1); 1.4829 + return; 1.4830 + } 1.4831 + } 1.4832 +#endif 1.4833 + sctp_sorwakeup(inp, inp->sctp_socket); 1.4834 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.4835 + if (!so_locked) { 1.4836 + SCTP_SOCKET_UNLOCK(so, 1); 1.4837 + } 1.4838 +#endif 1.4839 + } 1.4840 + } 1.4841 +} 1.4842 + 1.4843 + 1.4844 +int 1.4845 +sctp_append_to_readq(struct sctp_inpcb *inp, 1.4846 + struct sctp_tcb *stcb, 1.4847 + struct sctp_queued_to_read *control, 1.4848 + struct mbuf *m, 1.4849 + int end, 1.4850 + int ctls_cumack, 1.4851 + struct sockbuf *sb) 1.4852 +{ 1.4853 + /* 1.4854 + * A partial delivery API event is underway. OR we are appending on 1.4855 + * the reassembly queue. 1.4856 + * 1.4857 + * If PDAPI this means we need to add m to the end of the data. 1.4858 + * Increase the length in the control AND increment the sb_cc. 1.4859 + * Otherwise sb is NULL and all we need to do is put it at the end 1.4860 + * of the mbuf chain. 1.4861 + */ 1.4862 + int len = 0; 1.4863 + struct mbuf *mm, *tail = NULL, *prev = NULL; 1.4864 + 1.4865 + if (inp) { 1.4866 + SCTP_INP_READ_LOCK(inp); 1.4867 + } 1.4868 + if (control == NULL) { 1.4869 + get_out: 1.4870 + if (inp) { 1.4871 + SCTP_INP_READ_UNLOCK(inp); 1.4872 + } 1.4873 + return (-1); 1.4874 + } 1.4875 + if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ)) { 1.4876 + SCTP_INP_READ_UNLOCK(inp); 1.4877 + return (0); 1.4878 + } 1.4879 + if (control->end_added) { 1.4880 + /* huh this one is complete? */ 1.4881 + goto get_out; 1.4882 + } 1.4883 + mm = m; 1.4884 + if (mm == NULL) { 1.4885 + goto get_out; 1.4886 + } 1.4887 + 1.4888 + while (mm) { 1.4889 + if (SCTP_BUF_LEN(mm) == 0) { 1.4890 + /* Skip mbufs with NO lenght */ 1.4891 + if (prev == NULL) { 1.4892 + /* First one */ 1.4893 + m = sctp_m_free(mm); 1.4894 + mm = m; 1.4895 + } else { 1.4896 + SCTP_BUF_NEXT(prev) = sctp_m_free(mm); 1.4897 + mm = SCTP_BUF_NEXT(prev); 1.4898 + } 1.4899 + continue; 1.4900 + } 1.4901 + prev = mm; 1.4902 + len += SCTP_BUF_LEN(mm); 1.4903 + if (sb) { 1.4904 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.4905 + sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(mm)); 1.4906 + } 1.4907 + sctp_sballoc(stcb, sb, mm); 1.4908 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.4909 + sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0); 1.4910 + } 1.4911 + } 1.4912 + mm = SCTP_BUF_NEXT(mm); 1.4913 + } 1.4914 + if (prev) { 1.4915 + tail = prev; 1.4916 + } else { 1.4917 + /* Really there should always be a prev */ 1.4918 + if (m == NULL) { 1.4919 + /* Huh nothing left? */ 1.4920 +#ifdef INVARIANTS 1.4921 + panic("Nothing left to add?"); 1.4922 +#else 1.4923 + goto get_out; 1.4924 +#endif 1.4925 + } 1.4926 + tail = m; 1.4927 + } 1.4928 + if (control->tail_mbuf) { 1.4929 + /* append */ 1.4930 + SCTP_BUF_NEXT(control->tail_mbuf) = m; 1.4931 + control->tail_mbuf = tail; 1.4932 + } else { 1.4933 + /* nothing there */ 1.4934 +#ifdef INVARIANTS 1.4935 + if (control->data != NULL) { 1.4936 + panic("This should NOT happen"); 1.4937 + } 1.4938 +#endif 1.4939 + control->data = m; 1.4940 + control->tail_mbuf = tail; 1.4941 + } 1.4942 + atomic_add_int(&control->length, len); 1.4943 + if (end) { 1.4944 + /* message is complete */ 1.4945 + if (stcb && (control == stcb->asoc.control_pdapi)) { 1.4946 + stcb->asoc.control_pdapi = NULL; 1.4947 + } 1.4948 + control->held_length = 0; 1.4949 + control->end_added = 1; 1.4950 + } 1.4951 + if (stcb == NULL) { 1.4952 + control->do_not_ref_stcb = 1; 1.4953 + } 1.4954 + /* 1.4955 + * When we are appending in partial delivery, the cum-ack is used 1.4956 + * for the actual pd-api highest tsn on this mbuf. The true cum-ack 1.4957 + * is populated in the outbound sinfo structure from the true cumack 1.4958 + * if the association exists... 1.4959 + */ 1.4960 + control->sinfo_tsn = control->sinfo_cumtsn = ctls_cumack; 1.4961 +#if defined(__Userspace__) 1.4962 + if (inp->recv_callback) { 1.4963 + uint32_t pd_point, length; 1.4964 + 1.4965 + length = control->length; 1.4966 + if (stcb != NULL && stcb->sctp_socket != NULL) { 1.4967 + pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT, 1.4968 + stcb->sctp_ep->partial_delivery_point); 1.4969 + } else { 1.4970 + pd_point = inp->partial_delivery_point; 1.4971 + } 1.4972 + if ((control->end_added == 1) || (length >= pd_point)) { 1.4973 + struct socket *so; 1.4974 + char *buffer; 1.4975 + struct sctp_rcvinfo rcv; 1.4976 + union sctp_sockstore addr; 1.4977 + int flags; 1.4978 + 1.4979 + if ((buffer = malloc(control->length)) == NULL) { 1.4980 + return (-1); 1.4981 + } 1.4982 + so = stcb->sctp_socket; 1.4983 + for (m = control->data; m; m = SCTP_BUF_NEXT(m)) { 1.4984 + sctp_sbfree(control, control->stcb, &so->so_rcv, m); 1.4985 + } 1.4986 + m_copydata(control->data, 0, control->length, buffer); 1.4987 + memset(&rcv, 0, sizeof(struct sctp_rcvinfo)); 1.4988 + rcv.rcv_sid = control->sinfo_stream; 1.4989 + rcv.rcv_ssn = control->sinfo_ssn; 1.4990 + rcv.rcv_flags = control->sinfo_flags; 1.4991 + rcv.rcv_ppid = control->sinfo_ppid; 1.4992 + rcv.rcv_tsn = control->sinfo_tsn; 1.4993 + rcv.rcv_cumtsn = control->sinfo_cumtsn; 1.4994 + rcv.rcv_context = control->sinfo_context; 1.4995 + rcv.rcv_assoc_id = control->sinfo_assoc_id; 1.4996 + memset(&addr, 0, sizeof(union sctp_sockstore)); 1.4997 + switch (control->whoFrom->ro._l_addr.sa.sa_family) { 1.4998 +#ifdef INET 1.4999 + case AF_INET: 1.5000 + addr.sin = control->whoFrom->ro._l_addr.sin; 1.5001 + break; 1.5002 +#endif 1.5003 +#ifdef INET6 1.5004 + case AF_INET6: 1.5005 + addr.sin6 = control->whoFrom->ro._l_addr.sin6; 1.5006 + break; 1.5007 +#endif 1.5008 + case AF_CONN: 1.5009 + addr.sconn = control->whoFrom->ro._l_addr.sconn; 1.5010 + break; 1.5011 + default: 1.5012 + addr.sa = control->whoFrom->ro._l_addr.sa; 1.5013 + break; 1.5014 + } 1.5015 + flags = 0; 1.5016 + if (control->end_added == 1) { 1.5017 + flags |= MSG_EOR; 1.5018 + } 1.5019 + if (control->spec_flags & M_NOTIFICATION) { 1.5020 + flags |= MSG_NOTIFICATION; 1.5021 + } 1.5022 + sctp_m_freem(control->data); 1.5023 + control->data = NULL; 1.5024 + control->tail_mbuf = NULL; 1.5025 + control->length = 0; 1.5026 + if (control->end_added) { 1.5027 + sctp_free_remote_addr(control->whoFrom); 1.5028 + control->whoFrom = NULL; 1.5029 + sctp_free_a_readq(stcb, control); 1.5030 + } else { 1.5031 + control->some_taken = 1; 1.5032 + } 1.5033 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.5034 + SCTP_TCB_UNLOCK(stcb); 1.5035 + inp->recv_callback(so, addr, buffer, length, rcv, flags, inp->ulp_info); 1.5036 + SCTP_TCB_LOCK(stcb); 1.5037 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.5038 + } 1.5039 + if (inp) 1.5040 + SCTP_INP_READ_UNLOCK(inp); 1.5041 + return (0); 1.5042 + } 1.5043 +#endif 1.5044 + if (inp) { 1.5045 + SCTP_INP_READ_UNLOCK(inp); 1.5046 + } 1.5047 + if (inp && inp->sctp_socket) { 1.5048 + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) { 1.5049 + SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket); 1.5050 + } else { 1.5051 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.5052 + struct socket *so; 1.5053 + 1.5054 + so = SCTP_INP_SO(inp); 1.5055 + if (stcb) { 1.5056 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.5057 + SCTP_TCB_UNLOCK(stcb); 1.5058 + } 1.5059 + SCTP_SOCKET_LOCK(so, 1); 1.5060 + if (stcb) { 1.5061 + SCTP_TCB_LOCK(stcb); 1.5062 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.5063 + } 1.5064 + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 1.5065 + SCTP_SOCKET_UNLOCK(so, 1); 1.5066 + return (0); 1.5067 + } 1.5068 +#endif 1.5069 + sctp_sorwakeup(inp, inp->sctp_socket); 1.5070 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.5071 + SCTP_SOCKET_UNLOCK(so, 1); 1.5072 +#endif 1.5073 + } 1.5074 + } 1.5075 + return (0); 1.5076 +} 1.5077 + 1.5078 + 1.5079 + 1.5080 +/*************HOLD THIS COMMENT FOR PATCH FILE OF 1.5081 + *************ALTERNATE ROUTING CODE 1.5082 + */ 1.5083 + 1.5084 +/*************HOLD THIS COMMENT FOR END OF PATCH FILE OF 1.5085 + *************ALTERNATE ROUTING CODE 1.5086 + */ 1.5087 + 1.5088 +struct mbuf * 1.5089 +sctp_generate_invmanparam(int err) 1.5090 +{ 1.5091 + /* Return a MBUF with a invalid mandatory parameter */ 1.5092 + struct mbuf *m; 1.5093 + 1.5094 + m = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA); 1.5095 + if (m) { 1.5096 + struct sctp_paramhdr *ph; 1.5097 + 1.5098 + SCTP_BUF_LEN(m) = sizeof(struct sctp_paramhdr); 1.5099 + ph = mtod(m, struct sctp_paramhdr *); 1.5100 + ph->param_length = htons(sizeof(struct sctp_paramhdr)); 1.5101 + ph->param_type = htons(err); 1.5102 + } 1.5103 + return (m); 1.5104 +} 1.5105 + 1.5106 +#ifdef SCTP_MBCNT_LOGGING 1.5107 +void 1.5108 +sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc, 1.5109 + struct sctp_tmit_chunk *tp1, int chk_cnt) 1.5110 +{ 1.5111 + if (tp1->data == NULL) { 1.5112 + return; 1.5113 + } 1.5114 + asoc->chunks_on_out_queue -= chk_cnt; 1.5115 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBCNT_LOGGING_ENABLE) { 1.5116 + sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE, 1.5117 + asoc->total_output_queue_size, 1.5118 + tp1->book_size, 1.5119 + 0, 1.5120 + tp1->mbcnt); 1.5121 + } 1.5122 + if (asoc->total_output_queue_size >= tp1->book_size) { 1.5123 + atomic_add_int(&asoc->total_output_queue_size, -tp1->book_size); 1.5124 + } else { 1.5125 + asoc->total_output_queue_size = 0; 1.5126 + } 1.5127 + 1.5128 + if (stcb->sctp_socket && (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) || 1.5129 + ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)))) { 1.5130 + if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) { 1.5131 + stcb->sctp_socket->so_snd.sb_cc -= tp1->book_size; 1.5132 + } else { 1.5133 + stcb->sctp_socket->so_snd.sb_cc = 0; 1.5134 + 1.5135 + } 1.5136 + } 1.5137 +} 1.5138 + 1.5139 +#endif 1.5140 + 1.5141 +int 1.5142 +sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1, 1.5143 + uint8_t sent, int so_locked 1.5144 +#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING) 1.5145 + SCTP_UNUSED 1.5146 +#endif 1.5147 + ) 1.5148 +{ 1.5149 + struct sctp_stream_out *strq; 1.5150 + struct sctp_tmit_chunk *chk = NULL, *tp2; 1.5151 + struct sctp_stream_queue_pending *sp; 1.5152 + uint16_t stream = 0, seq = 0; 1.5153 + uint8_t foundeom = 0; 1.5154 + int ret_sz = 0; 1.5155 + int notdone; 1.5156 + int do_wakeup_routine = 0; 1.5157 +#if defined(__APPLE__) 1.5158 + if (so_locked) { 1.5159 + sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep)); 1.5160 + } else { 1.5161 + sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep)); 1.5162 + } 1.5163 +#endif 1.5164 + stream = tp1->rec.data.stream_number; 1.5165 + seq = tp1->rec.data.stream_seq; 1.5166 + do { 1.5167 + ret_sz += tp1->book_size; 1.5168 + if (tp1->data != NULL) { 1.5169 + if (tp1->sent < SCTP_DATAGRAM_RESEND) { 1.5170 + sctp_flight_size_decrease(tp1); 1.5171 + sctp_total_flight_decrease(stcb, tp1); 1.5172 + } 1.5173 + sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1); 1.5174 + stcb->asoc.peers_rwnd += tp1->send_size; 1.5175 + stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh); 1.5176 + if (sent) { 1.5177 + sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked); 1.5178 + } else { 1.5179 + sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked); 1.5180 + } 1.5181 + if (tp1->data) { 1.5182 + sctp_m_freem(tp1->data); 1.5183 + tp1->data = NULL; 1.5184 + } 1.5185 + do_wakeup_routine = 1; 1.5186 + if (PR_SCTP_BUF_ENABLED(tp1->flags)) { 1.5187 + stcb->asoc.sent_queue_cnt_removeable--; 1.5188 + } 1.5189 + } 1.5190 + tp1->sent = SCTP_FORWARD_TSN_SKIP; 1.5191 + if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) == 1.5192 + SCTP_DATA_NOT_FRAG) { 1.5193 + /* not frag'ed we ae done */ 1.5194 + notdone = 0; 1.5195 + foundeom = 1; 1.5196 + } else if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { 1.5197 + /* end of frag, we are done */ 1.5198 + notdone = 0; 1.5199 + foundeom = 1; 1.5200 + } else { 1.5201 + /* 1.5202 + * Its a begin or middle piece, we must mark all of 1.5203 + * it 1.5204 + */ 1.5205 + notdone = 1; 1.5206 + tp1 = TAILQ_NEXT(tp1, sctp_next); 1.5207 + } 1.5208 + } while (tp1 && notdone); 1.5209 + if (foundeom == 0) { 1.5210 + /* 1.5211 + * The multi-part message was scattered across the send and 1.5212 + * sent queue. 1.5213 + */ 1.5214 + TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) { 1.5215 + if ((tp1->rec.data.stream_number != stream) || 1.5216 + (tp1->rec.data.stream_seq != seq)) { 1.5217 + break; 1.5218 + } 1.5219 + /* save to chk in case we have some on stream out 1.5220 + * queue. If so and we have an un-transmitted one 1.5221 + * we don't have to fudge the TSN. 1.5222 + */ 1.5223 + chk = tp1; 1.5224 + ret_sz += tp1->book_size; 1.5225 + sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1); 1.5226 + if (sent) { 1.5227 + sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked); 1.5228 + } else { 1.5229 + sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked); 1.5230 + } 1.5231 + if (tp1->data) { 1.5232 + sctp_m_freem(tp1->data); 1.5233 + tp1->data = NULL; 1.5234 + } 1.5235 + /* No flight involved here book the size to 0 */ 1.5236 + tp1->book_size = 0; 1.5237 + if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) { 1.5238 + foundeom = 1; 1.5239 + } 1.5240 + do_wakeup_routine = 1; 1.5241 + tp1->sent = SCTP_FORWARD_TSN_SKIP; 1.5242 + TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next); 1.5243 + /* on to the sent queue so we can wait for it to be passed by. */ 1.5244 + TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1, 1.5245 + sctp_next); 1.5246 + stcb->asoc.send_queue_cnt--; 1.5247 + stcb->asoc.sent_queue_cnt++; 1.5248 + } 1.5249 + } 1.5250 + if (foundeom == 0) { 1.5251 + /* 1.5252 + * Still no eom found. That means there 1.5253 + * is stuff left on the stream out queue.. yuck. 1.5254 + */ 1.5255 + SCTP_TCB_SEND_LOCK(stcb); 1.5256 + strq = &stcb->asoc.strmout[stream]; 1.5257 + sp = TAILQ_FIRST(&strq->outqueue); 1.5258 + if (sp != NULL) { 1.5259 + sp->discard_rest = 1; 1.5260 + /* 1.5261 + * We may need to put a chunk on the 1.5262 + * queue that holds the TSN that 1.5263 + * would have been sent with the LAST 1.5264 + * bit. 1.5265 + */ 1.5266 + if (chk == NULL) { 1.5267 + /* Yep, we have to */ 1.5268 + sctp_alloc_a_chunk(stcb, chk); 1.5269 + if (chk == NULL) { 1.5270 + /* we are hosed. All we can 1.5271 + * do is nothing.. which will 1.5272 + * cause an abort if the peer is 1.5273 + * paying attention. 1.5274 + */ 1.5275 + goto oh_well; 1.5276 + } 1.5277 + memset(chk, 0, sizeof(*chk)); 1.5278 + chk->rec.data.rcv_flags = SCTP_DATA_LAST_FRAG; 1.5279 + chk->sent = SCTP_FORWARD_TSN_SKIP; 1.5280 + chk->asoc = &stcb->asoc; 1.5281 + chk->rec.data.stream_seq = strq->next_sequence_send; 1.5282 + chk->rec.data.stream_number = sp->stream; 1.5283 + chk->rec.data.payloadtype = sp->ppid; 1.5284 + chk->rec.data.context = sp->context; 1.5285 + chk->flags = sp->act_flags; 1.5286 + if (sp->net) 1.5287 + chk->whoTo = sp->net; 1.5288 + else 1.5289 + chk->whoTo = stcb->asoc.primary_destination; 1.5290 + atomic_add_int(&chk->whoTo->ref_count, 1); 1.5291 +#if defined(__FreeBSD__) || defined(__Panda__) 1.5292 + chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1); 1.5293 +#else 1.5294 + chk->rec.data.TSN_seq = stcb->asoc.sending_seq++; 1.5295 +#endif 1.5296 + stcb->asoc.pr_sctp_cnt++; 1.5297 + TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next); 1.5298 + stcb->asoc.sent_queue_cnt++; 1.5299 + stcb->asoc.pr_sctp_cnt++; 1.5300 + } else { 1.5301 + chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG; 1.5302 + } 1.5303 + strq->next_sequence_send++; 1.5304 + oh_well: 1.5305 + if (sp->data) { 1.5306 + /* Pull any data to free up the SB and 1.5307 + * allow sender to "add more" while we 1.5308 + * will throw away :-) 1.5309 + */ 1.5310 + sctp_free_spbufspace(stcb, &stcb->asoc, sp); 1.5311 + ret_sz += sp->length; 1.5312 + do_wakeup_routine = 1; 1.5313 + sp->some_taken = 1; 1.5314 + sctp_m_freem(sp->data); 1.5315 + sp->data = NULL; 1.5316 + sp->tail_mbuf = NULL; 1.5317 + sp->length = 0; 1.5318 + } 1.5319 + } 1.5320 + SCTP_TCB_SEND_UNLOCK(stcb); 1.5321 + } 1.5322 + if (do_wakeup_routine) { 1.5323 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.5324 + struct socket *so; 1.5325 + 1.5326 + so = SCTP_INP_SO(stcb->sctp_ep); 1.5327 + if (!so_locked) { 1.5328 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.5329 + SCTP_TCB_UNLOCK(stcb); 1.5330 + SCTP_SOCKET_LOCK(so, 1); 1.5331 + SCTP_TCB_LOCK(stcb); 1.5332 + atomic_subtract_int(&stcb->asoc.refcnt, 1); 1.5333 + if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) { 1.5334 + /* assoc was freed while we were unlocked */ 1.5335 + SCTP_SOCKET_UNLOCK(so, 1); 1.5336 + return (ret_sz); 1.5337 + } 1.5338 + } 1.5339 +#endif 1.5340 + sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket); 1.5341 +#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING) 1.5342 + if (!so_locked) { 1.5343 + SCTP_SOCKET_UNLOCK(so, 1); 1.5344 + } 1.5345 +#endif 1.5346 + } 1.5347 + return (ret_sz); 1.5348 +} 1.5349 + 1.5350 +/* 1.5351 + * checks to see if the given address, sa, is one that is currently known by 1.5352 + * the kernel note: can't distinguish the same address on multiple interfaces 1.5353 + * and doesn't handle multiple addresses with different zone/scope id's note: 1.5354 + * ifa_ifwithaddr() compares the entire sockaddr struct 1.5355 + */ 1.5356 +struct sctp_ifa * 1.5357 +sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, 1.5358 + int holds_lock) 1.5359 +{ 1.5360 + struct sctp_laddr *laddr; 1.5361 + 1.5362 + if (holds_lock == 0) { 1.5363 + SCTP_INP_RLOCK(inp); 1.5364 + } 1.5365 + 1.5366 + LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 1.5367 + if (laddr->ifa == NULL) 1.5368 + continue; 1.5369 + if (addr->sa_family != laddr->ifa->address.sa.sa_family) 1.5370 + continue; 1.5371 +#ifdef INET 1.5372 + if (addr->sa_family == AF_INET) { 1.5373 + if (((struct sockaddr_in *)addr)->sin_addr.s_addr == 1.5374 + laddr->ifa->address.sin.sin_addr.s_addr) { 1.5375 + /* found him. */ 1.5376 + if (holds_lock == 0) { 1.5377 + SCTP_INP_RUNLOCK(inp); 1.5378 + } 1.5379 + return (laddr->ifa); 1.5380 + break; 1.5381 + } 1.5382 + } 1.5383 +#endif 1.5384 +#ifdef INET6 1.5385 + if (addr->sa_family == AF_INET6) { 1.5386 + if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr, 1.5387 + &laddr->ifa->address.sin6)) { 1.5388 + /* found him. */ 1.5389 + if (holds_lock == 0) { 1.5390 + SCTP_INP_RUNLOCK(inp); 1.5391 + } 1.5392 + return (laddr->ifa); 1.5393 + break; 1.5394 + } 1.5395 + } 1.5396 +#endif 1.5397 +#if defined(__Userspace__) 1.5398 + if (addr->sa_family == AF_CONN) { 1.5399 + if (((struct sockaddr_conn *)addr)->sconn_addr == laddr->ifa->address.sconn.sconn_addr) { 1.5400 + /* found him. */ 1.5401 + if (holds_lock == 0) { 1.5402 + SCTP_INP_RUNLOCK(inp); 1.5403 + } 1.5404 + return (laddr->ifa); 1.5405 + break; 1.5406 + } 1.5407 + } 1.5408 +#endif 1.5409 + } 1.5410 + if (holds_lock == 0) { 1.5411 + SCTP_INP_RUNLOCK(inp); 1.5412 + } 1.5413 + return (NULL); 1.5414 +} 1.5415 + 1.5416 +uint32_t 1.5417 +sctp_get_ifa_hash_val(struct sockaddr *addr) 1.5418 +{ 1.5419 + switch (addr->sa_family) { 1.5420 +#ifdef INET 1.5421 + case AF_INET: 1.5422 + { 1.5423 + struct sockaddr_in *sin; 1.5424 + 1.5425 + sin = (struct sockaddr_in *)addr; 1.5426 + return (sin->sin_addr.s_addr ^ (sin->sin_addr.s_addr >> 16)); 1.5427 + } 1.5428 +#endif 1.5429 +#ifdef INET6 1.5430 + case AF_INET6: 1.5431 + { 1.5432 + struct sockaddr_in6 *sin6; 1.5433 + uint32_t hash_of_addr; 1.5434 + 1.5435 + sin6 = (struct sockaddr_in6 *)addr; 1.5436 +#if !defined(__Windows__) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_Darwin) && !defined(__Userspace_os_Windows) 1.5437 + hash_of_addr = (sin6->sin6_addr.s6_addr32[0] + 1.5438 + sin6->sin6_addr.s6_addr32[1] + 1.5439 + sin6->sin6_addr.s6_addr32[2] + 1.5440 + sin6->sin6_addr.s6_addr32[3]); 1.5441 +#else 1.5442 + hash_of_addr = (((uint32_t *)&sin6->sin6_addr)[0] + 1.5443 + ((uint32_t *)&sin6->sin6_addr)[1] + 1.5444 + ((uint32_t *)&sin6->sin6_addr)[2] + 1.5445 + ((uint32_t *)&sin6->sin6_addr)[3]); 1.5446 +#endif 1.5447 + hash_of_addr = (hash_of_addr ^ (hash_of_addr >> 16)); 1.5448 + return (hash_of_addr); 1.5449 + } 1.5450 +#endif 1.5451 +#if defined(__Userspace__) 1.5452 + case AF_CONN: 1.5453 + { 1.5454 + struct sockaddr_conn *sconn; 1.5455 + uintptr_t temp; 1.5456 + 1.5457 + sconn = (struct sockaddr_conn *)addr; 1.5458 + temp = (uintptr_t)sconn->sconn_addr; 1.5459 + return ((uint32_t)(temp ^ (temp >> 16))); 1.5460 + } 1.5461 +#endif 1.5462 + default: 1.5463 + break; 1.5464 + } 1.5465 + return (0); 1.5466 +} 1.5467 + 1.5468 +struct sctp_ifa * 1.5469 +sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock) 1.5470 +{ 1.5471 + struct sctp_ifa *sctp_ifap; 1.5472 + struct sctp_vrf *vrf; 1.5473 + struct sctp_ifalist *hash_head; 1.5474 + uint32_t hash_of_addr; 1.5475 + 1.5476 + if (holds_lock == 0) 1.5477 + SCTP_IPI_ADDR_RLOCK(); 1.5478 + 1.5479 + vrf = sctp_find_vrf(vrf_id); 1.5480 + if (vrf == NULL) { 1.5481 + stage_right: 1.5482 + if (holds_lock == 0) 1.5483 + SCTP_IPI_ADDR_RUNLOCK(); 1.5484 + return (NULL); 1.5485 + } 1.5486 + 1.5487 + hash_of_addr = sctp_get_ifa_hash_val(addr); 1.5488 + 1.5489 + hash_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_addr_hashmark)]; 1.5490 + if (hash_head == NULL) { 1.5491 + SCTP_PRINTF("hash_of_addr:%x mask:%x table:%x - ", 1.5492 + hash_of_addr, (uint32_t)vrf->vrf_addr_hashmark, 1.5493 + (uint32_t)(hash_of_addr & vrf->vrf_addr_hashmark)); 1.5494 + sctp_print_address(addr); 1.5495 + SCTP_PRINTF("No such bucket for address\n"); 1.5496 + if (holds_lock == 0) 1.5497 + SCTP_IPI_ADDR_RUNLOCK(); 1.5498 + 1.5499 + return (NULL); 1.5500 + } 1.5501 + LIST_FOREACH(sctp_ifap, hash_head, next_bucket) { 1.5502 + if (sctp_ifap == NULL) { 1.5503 +#ifdef INVARIANTS 1.5504 + panic("Huh LIST_FOREACH corrupt"); 1.5505 + goto stage_right; 1.5506 +#else 1.5507 + SCTP_PRINTF("LIST corrupt of sctp_ifap's?\n"); 1.5508 + goto stage_right; 1.5509 +#endif 1.5510 + } 1.5511 + if (addr->sa_family != sctp_ifap->address.sa.sa_family) 1.5512 + continue; 1.5513 +#ifdef INET 1.5514 + if (addr->sa_family == AF_INET) { 1.5515 + if (((struct sockaddr_in *)addr)->sin_addr.s_addr == 1.5516 + sctp_ifap->address.sin.sin_addr.s_addr) { 1.5517 + /* found him. */ 1.5518 + if (holds_lock == 0) 1.5519 + SCTP_IPI_ADDR_RUNLOCK(); 1.5520 + return (sctp_ifap); 1.5521 + break; 1.5522 + } 1.5523 + } 1.5524 +#endif 1.5525 +#ifdef INET6 1.5526 + if (addr->sa_family == AF_INET6) { 1.5527 + if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr, 1.5528 + &sctp_ifap->address.sin6)) { 1.5529 + /* found him. */ 1.5530 + if (holds_lock == 0) 1.5531 + SCTP_IPI_ADDR_RUNLOCK(); 1.5532 + return (sctp_ifap); 1.5533 + break; 1.5534 + } 1.5535 + } 1.5536 +#endif 1.5537 +#if defined(__Userspace__) 1.5538 + if (addr->sa_family == AF_CONN) { 1.5539 + if (((struct sockaddr_conn *)addr)->sconn_addr == sctp_ifap->address.sconn.sconn_addr) { 1.5540 + /* found him. */ 1.5541 + if (holds_lock == 0) 1.5542 + SCTP_IPI_ADDR_RUNLOCK(); 1.5543 + return (sctp_ifap); 1.5544 + break; 1.5545 + } 1.5546 + } 1.5547 +#endif 1.5548 + } 1.5549 + if (holds_lock == 0) 1.5550 + SCTP_IPI_ADDR_RUNLOCK(); 1.5551 + return (NULL); 1.5552 +} 1.5553 + 1.5554 +static void 1.5555 +sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t *freed_so_far, int hold_rlock, 1.5556 + uint32_t rwnd_req) 1.5557 +{ 1.5558 + /* User pulled some data, do we need a rwnd update? */ 1.5559 + int r_unlocked = 0; 1.5560 + uint32_t dif, rwnd; 1.5561 + struct socket *so = NULL; 1.5562 + 1.5563 + if (stcb == NULL) 1.5564 + return; 1.5565 + 1.5566 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.5567 + 1.5568 + if (stcb->asoc.state & (SCTP_STATE_ABOUT_TO_BE_FREED | 1.5569 + SCTP_STATE_SHUTDOWN_RECEIVED | 1.5570 + SCTP_STATE_SHUTDOWN_ACK_SENT)) { 1.5571 + /* Pre-check If we are freeing no update */ 1.5572 + goto no_lock; 1.5573 + } 1.5574 + SCTP_INP_INCR_REF(stcb->sctp_ep); 1.5575 + if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 1.5576 + (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 1.5577 + goto out; 1.5578 + } 1.5579 + so = stcb->sctp_socket; 1.5580 + if (so == NULL) { 1.5581 + goto out; 1.5582 + } 1.5583 + atomic_add_int(&stcb->freed_by_sorcv_sincelast, *freed_so_far); 1.5584 + /* Have you have freed enough to look */ 1.5585 + *freed_so_far = 0; 1.5586 + /* Yep, its worth a look and the lock overhead */ 1.5587 + 1.5588 + /* Figure out what the rwnd would be */ 1.5589 + rwnd = sctp_calc_rwnd(stcb, &stcb->asoc); 1.5590 + if (rwnd >= stcb->asoc.my_last_reported_rwnd) { 1.5591 + dif = rwnd - stcb->asoc.my_last_reported_rwnd; 1.5592 + } else { 1.5593 + dif = 0; 1.5594 + } 1.5595 + if (dif >= rwnd_req) { 1.5596 + if (hold_rlock) { 1.5597 + SCTP_INP_READ_UNLOCK(stcb->sctp_ep); 1.5598 + r_unlocked = 1; 1.5599 + } 1.5600 + if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 1.5601 + /* 1.5602 + * One last check before we allow the guy possibly 1.5603 + * to get in. There is a race, where the guy has not 1.5604 + * reached the gate. In that case 1.5605 + */ 1.5606 + goto out; 1.5607 + } 1.5608 + SCTP_TCB_LOCK(stcb); 1.5609 + if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 1.5610 + /* No reports here */ 1.5611 + SCTP_TCB_UNLOCK(stcb); 1.5612 + goto out; 1.5613 + } 1.5614 + SCTP_STAT_INCR(sctps_wu_sacks_sent); 1.5615 + sctp_send_sack(stcb, SCTP_SO_LOCKED); 1.5616 + 1.5617 + sctp_chunk_output(stcb->sctp_ep, stcb, 1.5618 + SCTP_OUTPUT_FROM_USR_RCVD, SCTP_SO_LOCKED); 1.5619 + /* make sure no timer is running */ 1.5620 + sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_6); 1.5621 + SCTP_TCB_UNLOCK(stcb); 1.5622 + } else { 1.5623 + /* Update how much we have pending */ 1.5624 + stcb->freed_by_sorcv_sincelast = dif; 1.5625 + } 1.5626 + out: 1.5627 + if (so && r_unlocked && hold_rlock) { 1.5628 + SCTP_INP_READ_LOCK(stcb->sctp_ep); 1.5629 + } 1.5630 + 1.5631 + SCTP_INP_DECR_REF(stcb->sctp_ep); 1.5632 + no_lock: 1.5633 + atomic_add_int(&stcb->asoc.refcnt, -1); 1.5634 + return; 1.5635 +} 1.5636 + 1.5637 +int 1.5638 +sctp_sorecvmsg(struct socket *so, 1.5639 + struct uio *uio, 1.5640 + struct mbuf **mp, 1.5641 + struct sockaddr *from, 1.5642 + int fromlen, 1.5643 + int *msg_flags, 1.5644 + struct sctp_sndrcvinfo *sinfo, 1.5645 + int filling_sinfo) 1.5646 +{ 1.5647 + /* 1.5648 + * MSG flags we will look at MSG_DONTWAIT - non-blocking IO. 1.5649 + * MSG_PEEK - Look don't touch :-D (only valid with OUT mbuf copy 1.5650 + * mp=NULL thus uio is the copy method to userland) MSG_WAITALL - ?? 1.5651 + * On the way out we may send out any combination of: 1.5652 + * MSG_NOTIFICATION MSG_EOR 1.5653 + * 1.5654 + */ 1.5655 + struct sctp_inpcb *inp = NULL; 1.5656 + int my_len = 0; 1.5657 + int cp_len = 0, error = 0; 1.5658 + struct sctp_queued_to_read *control = NULL, *ctl = NULL, *nxt = NULL; 1.5659 + struct mbuf *m = NULL; 1.5660 + struct sctp_tcb *stcb = NULL; 1.5661 + int wakeup_read_socket = 0; 1.5662 + int freecnt_applied = 0; 1.5663 + int out_flags = 0, in_flags = 0; 1.5664 + int block_allowed = 1; 1.5665 + uint32_t freed_so_far = 0; 1.5666 + uint32_t copied_so_far = 0; 1.5667 + int in_eeor_mode = 0; 1.5668 + int no_rcv_needed = 0; 1.5669 + uint32_t rwnd_req = 0; 1.5670 + int hold_sblock = 0; 1.5671 + int hold_rlock = 0; 1.5672 + int slen = 0; 1.5673 + uint32_t held_length = 0; 1.5674 +#if defined(__FreeBSD__) && __FreeBSD_version >= 700000 1.5675 + int sockbuf_lock = 0; 1.5676 +#endif 1.5677 + 1.5678 + if (uio == NULL) { 1.5679 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.5680 + return (EINVAL); 1.5681 + } 1.5682 + 1.5683 + if (msg_flags) { 1.5684 + in_flags = *msg_flags; 1.5685 + if (in_flags & MSG_PEEK) 1.5686 + SCTP_STAT_INCR(sctps_read_peeks); 1.5687 + } else { 1.5688 + in_flags = 0; 1.5689 + } 1.5690 +#if defined(__APPLE__) 1.5691 +#if defined(APPLE_LEOPARD) 1.5692 + slen = uio->uio_resid; 1.5693 +#else 1.5694 + slen = uio_resid(uio); 1.5695 +#endif 1.5696 +#else 1.5697 + slen = uio->uio_resid; 1.5698 +#endif 1.5699 + 1.5700 + /* Pull in and set up our int flags */ 1.5701 + if (in_flags & MSG_OOB) { 1.5702 + /* Out of band's NOT supported */ 1.5703 + return (EOPNOTSUPP); 1.5704 + } 1.5705 + if ((in_flags & MSG_PEEK) && (mp != NULL)) { 1.5706 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.5707 + return (EINVAL); 1.5708 + } 1.5709 + if ((in_flags & (MSG_DONTWAIT 1.5710 +#if defined(__FreeBSD__) && __FreeBSD_version > 500000 1.5711 + | MSG_NBIO 1.5712 +#endif 1.5713 + )) || 1.5714 + SCTP_SO_IS_NBIO(so)) { 1.5715 + block_allowed = 0; 1.5716 + } 1.5717 + /* setup the endpoint */ 1.5718 + inp = (struct sctp_inpcb *)so->so_pcb; 1.5719 + if (inp == NULL) { 1.5720 + SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT); 1.5721 + return (EFAULT); 1.5722 + } 1.5723 + rwnd_req = (SCTP_SB_LIMIT_RCV(so) >> SCTP_RWND_HIWAT_SHIFT); 1.5724 + /* Must be at least a MTU's worth */ 1.5725 + if (rwnd_req < SCTP_MIN_RWND) 1.5726 + rwnd_req = SCTP_MIN_RWND; 1.5727 + in_eeor_mode = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR); 1.5728 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) { 1.5729 +#if defined(__APPLE__) 1.5730 +#if defined(APPLE_LEOPARD) 1.5731 + sctp_misc_ints(SCTP_SORECV_ENTER, 1.5732 + rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid); 1.5733 +#else 1.5734 + sctp_misc_ints(SCTP_SORECV_ENTER, 1.5735 + rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio_resid(uio)); 1.5736 +#endif 1.5737 +#else 1.5738 + sctp_misc_ints(SCTP_SORECV_ENTER, 1.5739 + rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid); 1.5740 +#endif 1.5741 + } 1.5742 +#if (defined(__FreeBSD__) && __FreeBSD_version < 700000) || defined(__Userspace__) 1.5743 + SOCKBUF_LOCK(&so->so_rcv); 1.5744 + hold_sblock = 1; 1.5745 +#endif 1.5746 + if (SCTP_BASE_SYSCTL(sctp_logging_level) &SCTP_RECV_RWND_LOGGING_ENABLE) { 1.5747 +#if defined(__APPLE__) 1.5748 +#if defined(APPLE_LEOPARD) 1.5749 + sctp_misc_ints(SCTP_SORECV_ENTERPL, 1.5750 + rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid); 1.5751 +#else 1.5752 + sctp_misc_ints(SCTP_SORECV_ENTERPL, 1.5753 + rwnd_req, block_allowed, so->so_rcv.sb_cc, uio_resid(uio)); 1.5754 +#endif 1.5755 +#else 1.5756 + sctp_misc_ints(SCTP_SORECV_ENTERPL, 1.5757 + rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid); 1.5758 +#endif 1.5759 + } 1.5760 + 1.5761 +#if defined(__APPLE__) 1.5762 + error = sblock(&so->so_rcv, SBLOCKWAIT(in_flags)); 1.5763 +#endif 1.5764 + 1.5765 +#if defined(__FreeBSD__) 1.5766 + error = sblock(&so->so_rcv, (block_allowed ? SBL_WAIT : 0)); 1.5767 +#endif 1.5768 + if (error) { 1.5769 + goto release_unlocked; 1.5770 + } 1.5771 +#if defined(__FreeBSD__) && __FreeBSD_version >= 700000 1.5772 + sockbuf_lock = 1; 1.5773 +#endif 1.5774 + restart: 1.5775 +#if (defined(__FreeBSD__) && __FreeBSD_version < 700000) || defined(__Userspace__) 1.5776 + if (hold_sblock == 0) { 1.5777 + SOCKBUF_LOCK(&so->so_rcv); 1.5778 + hold_sblock = 1; 1.5779 + } 1.5780 +#endif 1.5781 +#if defined(__APPLE__) 1.5782 + sbunlock(&so->so_rcv, 1); 1.5783 +#endif 1.5784 + 1.5785 +#if defined(__FreeBSD__) && __FreeBSD_version < 700000 1.5786 + sbunlock(&so->so_rcv); 1.5787 +#endif 1.5788 + 1.5789 + restart_nosblocks: 1.5790 + if (hold_sblock == 0) { 1.5791 + SOCKBUF_LOCK(&so->so_rcv); 1.5792 + hold_sblock = 1; 1.5793 + } 1.5794 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) || 1.5795 + (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) { 1.5796 + goto out; 1.5797 + } 1.5798 +#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__) 1.5799 + if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) && (so->so_rcv.sb_cc == 0)) { 1.5800 +#else 1.5801 + if ((so->so_state & SS_CANTRCVMORE) && (so->so_rcv.sb_cc == 0)) { 1.5802 +#endif 1.5803 + if (so->so_error) { 1.5804 + error = so->so_error; 1.5805 + if ((in_flags & MSG_PEEK) == 0) 1.5806 + so->so_error = 0; 1.5807 + goto out; 1.5808 + } else { 1.5809 + if (so->so_rcv.sb_cc == 0) { 1.5810 + /* indicate EOF */ 1.5811 + error = 0; 1.5812 + goto out; 1.5813 + } 1.5814 + } 1.5815 + } 1.5816 + if ((so->so_rcv.sb_cc <= held_length) && block_allowed) { 1.5817 + /* we need to wait for data */ 1.5818 + if ((so->so_rcv.sb_cc == 0) && 1.5819 + ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1.5820 + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) { 1.5821 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) { 1.5822 + /* For active open side clear flags for re-use 1.5823 + * passive open is blocked by connect. 1.5824 + */ 1.5825 + if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) { 1.5826 + /* You were aborted, passive side always hits here */ 1.5827 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET); 1.5828 + error = ECONNRESET; 1.5829 + } 1.5830 + so->so_state &= ~(SS_ISCONNECTING | 1.5831 + SS_ISDISCONNECTING | 1.5832 + SS_ISCONFIRMING | 1.5833 + SS_ISCONNECTED); 1.5834 + if (error == 0) { 1.5835 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) { 1.5836 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN); 1.5837 + error = ENOTCONN; 1.5838 + } 1.5839 + } 1.5840 + goto out; 1.5841 + } 1.5842 + } 1.5843 + error = sbwait(&so->so_rcv); 1.5844 + if (error) { 1.5845 + goto out; 1.5846 + } 1.5847 + held_length = 0; 1.5848 + goto restart_nosblocks; 1.5849 + } else if (so->so_rcv.sb_cc == 0) { 1.5850 + if (so->so_error) { 1.5851 + error = so->so_error; 1.5852 + if ((in_flags & MSG_PEEK) == 0) 1.5853 + so->so_error = 0; 1.5854 + } else { 1.5855 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 1.5856 + (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 1.5857 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) { 1.5858 + /* For active open side clear flags for re-use 1.5859 + * passive open is blocked by connect. 1.5860 + */ 1.5861 + if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) { 1.5862 + /* You were aborted, passive side always hits here */ 1.5863 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET); 1.5864 + error = ECONNRESET; 1.5865 + } 1.5866 + so->so_state &= ~(SS_ISCONNECTING | 1.5867 + SS_ISDISCONNECTING | 1.5868 + SS_ISCONFIRMING | 1.5869 + SS_ISCONNECTED); 1.5870 + if (error == 0) { 1.5871 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) { 1.5872 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN); 1.5873 + error = ENOTCONN; 1.5874 + } 1.5875 + } 1.5876 + goto out; 1.5877 + } 1.5878 + } 1.5879 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EWOULDBLOCK); 1.5880 + error = EWOULDBLOCK; 1.5881 + } 1.5882 + goto out; 1.5883 + } 1.5884 + if (hold_sblock == 1) { 1.5885 + SOCKBUF_UNLOCK(&so->so_rcv); 1.5886 + hold_sblock = 0; 1.5887 + } 1.5888 +#if defined(__APPLE__) 1.5889 + error = sblock(&so->so_rcv, SBLOCKWAIT(in_flags)); 1.5890 +#endif 1.5891 +#if defined(__FreeBSD__) && __FreeBSD_version < 700000 1.5892 + error = sblock(&so->so_rcv, (block_allowed ? M_WAITOK : 0)); 1.5893 +#endif 1.5894 + /* we possibly have data we can read */ 1.5895 + /*sa_ignore FREED_MEMORY*/ 1.5896 + control = TAILQ_FIRST(&inp->read_queue); 1.5897 + if (control == NULL) { 1.5898 + /* This could be happening since 1.5899 + * the appender did the increment but as not 1.5900 + * yet did the tailq insert onto the read_queue 1.5901 + */ 1.5902 + if (hold_rlock == 0) { 1.5903 + SCTP_INP_READ_LOCK(inp); 1.5904 + } 1.5905 + control = TAILQ_FIRST(&inp->read_queue); 1.5906 + if ((control == NULL) && (so->so_rcv.sb_cc != 0)) { 1.5907 +#ifdef INVARIANTS 1.5908 + panic("Huh, its non zero and nothing on control?"); 1.5909 +#endif 1.5910 + so->so_rcv.sb_cc = 0; 1.5911 + } 1.5912 + SCTP_INP_READ_UNLOCK(inp); 1.5913 + hold_rlock = 0; 1.5914 + goto restart; 1.5915 + } 1.5916 + 1.5917 + if ((control->length == 0) && 1.5918 + (control->do_not_ref_stcb)) { 1.5919 + /* Clean up code for freeing assoc that left behind a pdapi.. 1.5920 + * maybe a peer in EEOR that just closed after sending and 1.5921 + * never indicated a EOR. 1.5922 + */ 1.5923 + if (hold_rlock == 0) { 1.5924 + hold_rlock = 1; 1.5925 + SCTP_INP_READ_LOCK(inp); 1.5926 + } 1.5927 + control->held_length = 0; 1.5928 + if (control->data) { 1.5929 + /* Hmm there is data here .. fix */ 1.5930 + struct mbuf *m_tmp; 1.5931 + int cnt = 0; 1.5932 + m_tmp = control->data; 1.5933 + while (m_tmp) { 1.5934 + cnt += SCTP_BUF_LEN(m_tmp); 1.5935 + if (SCTP_BUF_NEXT(m_tmp) == NULL) { 1.5936 + control->tail_mbuf = m_tmp; 1.5937 + control->end_added = 1; 1.5938 + } 1.5939 + m_tmp = SCTP_BUF_NEXT(m_tmp); 1.5940 + } 1.5941 + control->length = cnt; 1.5942 + } else { 1.5943 + /* remove it */ 1.5944 + TAILQ_REMOVE(&inp->read_queue, control, next); 1.5945 + /* Add back any hiddend data */ 1.5946 + sctp_free_remote_addr(control->whoFrom); 1.5947 + sctp_free_a_readq(stcb, control); 1.5948 + } 1.5949 + if (hold_rlock) { 1.5950 + hold_rlock = 0; 1.5951 + SCTP_INP_READ_UNLOCK(inp); 1.5952 + } 1.5953 + goto restart; 1.5954 + } 1.5955 + if ((control->length == 0) && 1.5956 + (control->end_added == 1)) { 1.5957 + /* Do we also need to check for (control->pdapi_aborted == 1)? */ 1.5958 + if (hold_rlock == 0) { 1.5959 + hold_rlock = 1; 1.5960 + SCTP_INP_READ_LOCK(inp); 1.5961 + } 1.5962 + TAILQ_REMOVE(&inp->read_queue, control, next); 1.5963 + if (control->data) { 1.5964 +#ifdef INVARIANTS 1.5965 + panic("control->data not null but control->length == 0"); 1.5966 +#else 1.5967 + SCTP_PRINTF("Strange, data left in the control buffer. Cleaning up.\n"); 1.5968 + sctp_m_freem(control->data); 1.5969 + control->data = NULL; 1.5970 +#endif 1.5971 + } 1.5972 + if (control->aux_data) { 1.5973 + sctp_m_free (control->aux_data); 1.5974 + control->aux_data = NULL; 1.5975 + } 1.5976 + sctp_free_remote_addr(control->whoFrom); 1.5977 + sctp_free_a_readq(stcb, control); 1.5978 + if (hold_rlock) { 1.5979 + hold_rlock = 0; 1.5980 + SCTP_INP_READ_UNLOCK(inp); 1.5981 + } 1.5982 + goto restart; 1.5983 + } 1.5984 + if (control->length == 0) { 1.5985 + if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) && 1.5986 + (filling_sinfo)) { 1.5987 + /* find a more suitable one then this */ 1.5988 + ctl = TAILQ_NEXT(control, next); 1.5989 + while (ctl) { 1.5990 + if ((ctl->stcb != control->stcb) && (ctl->length) && 1.5991 + (ctl->some_taken || 1.5992 + (ctl->spec_flags & M_NOTIFICATION) || 1.5993 + ((ctl->do_not_ref_stcb == 0) && 1.5994 + (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0))) 1.5995 + ) { 1.5996 + /*- 1.5997 + * If we have a different TCB next, and there is data 1.5998 + * present. If we have already taken some (pdapi), OR we can 1.5999 + * ref the tcb and no delivery as started on this stream, we 1.6000 + * take it. Note we allow a notification on a different 1.6001 + * assoc to be delivered.. 1.6002 + */ 1.6003 + control = ctl; 1.6004 + goto found_one; 1.6005 + } else if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) && 1.6006 + (ctl->length) && 1.6007 + ((ctl->some_taken) || 1.6008 + ((ctl->do_not_ref_stcb == 0) && 1.6009 + ((ctl->spec_flags & M_NOTIFICATION) == 0) && 1.6010 + (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0)))) { 1.6011 + /*- 1.6012 + * If we have the same tcb, and there is data present, and we 1.6013 + * have the strm interleave feature present. Then if we have 1.6014 + * taken some (pdapi) or we can refer to tht tcb AND we have 1.6015 + * not started a delivery for this stream, we can take it. 1.6016 + * Note we do NOT allow a notificaiton on the same assoc to 1.6017 + * be delivered. 1.6018 + */ 1.6019 + control = ctl; 1.6020 + goto found_one; 1.6021 + } 1.6022 + ctl = TAILQ_NEXT(ctl, next); 1.6023 + } 1.6024 + } 1.6025 + /* 1.6026 + * if we reach here, not suitable replacement is available 1.6027 + * <or> fragment interleave is NOT on. So stuff the sb_cc 1.6028 + * into the our held count, and its time to sleep again. 1.6029 + */ 1.6030 + held_length = so->so_rcv.sb_cc; 1.6031 + control->held_length = so->so_rcv.sb_cc; 1.6032 + goto restart; 1.6033 + } 1.6034 + /* Clear the held length since there is something to read */ 1.6035 + control->held_length = 0; 1.6036 + if (hold_rlock) { 1.6037 + SCTP_INP_READ_UNLOCK(inp); 1.6038 + hold_rlock = 0; 1.6039 + } 1.6040 + found_one: 1.6041 + /* 1.6042 + * If we reach here, control has a some data for us to read off. 1.6043 + * Note that stcb COULD be NULL. 1.6044 + */ 1.6045 + control->some_taken++; 1.6046 + if (hold_sblock) { 1.6047 + SOCKBUF_UNLOCK(&so->so_rcv); 1.6048 + hold_sblock = 0; 1.6049 + } 1.6050 + stcb = control->stcb; 1.6051 + if (stcb) { 1.6052 + if ((control->do_not_ref_stcb == 0) && 1.6053 + (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) { 1.6054 + if (freecnt_applied == 0) 1.6055 + stcb = NULL; 1.6056 + } else if (control->do_not_ref_stcb == 0) { 1.6057 + /* you can't free it on me please */ 1.6058 + /* 1.6059 + * The lock on the socket buffer protects us so the 1.6060 + * free code will stop. But since we used the socketbuf 1.6061 + * lock and the sender uses the tcb_lock to increment, 1.6062 + * we need to use the atomic add to the refcnt 1.6063 + */ 1.6064 + if (freecnt_applied) { 1.6065 +#ifdef INVARIANTS 1.6066 + panic("refcnt already incremented"); 1.6067 +#else 1.6068 + SCTP_PRINTF("refcnt already incremented?\n"); 1.6069 +#endif 1.6070 + } else { 1.6071 + atomic_add_int(&stcb->asoc.refcnt, 1); 1.6072 + freecnt_applied = 1; 1.6073 + } 1.6074 + /* 1.6075 + * Setup to remember how much we have not yet told 1.6076 + * the peer our rwnd has opened up. Note we grab 1.6077 + * the value from the tcb from last time. 1.6078 + * Note too that sack sending clears this when a sack 1.6079 + * is sent, which is fine. Once we hit the rwnd_req, 1.6080 + * we then will go to the sctp_user_rcvd() that will 1.6081 + * not lock until it KNOWs it MUST send a WUP-SACK. 1.6082 + */ 1.6083 + freed_so_far = stcb->freed_by_sorcv_sincelast; 1.6084 + stcb->freed_by_sorcv_sincelast = 0; 1.6085 + } 1.6086 + } 1.6087 + if (stcb && 1.6088 + ((control->spec_flags & M_NOTIFICATION) == 0) && 1.6089 + control->do_not_ref_stcb == 0) { 1.6090 + stcb->asoc.strmin[control->sinfo_stream].delivery_started = 1; 1.6091 + } 1.6092 + 1.6093 + /* First lets get off the sinfo and sockaddr info */ 1.6094 + if ((sinfo) && filling_sinfo) { 1.6095 + memcpy(sinfo, control, sizeof(struct sctp_nonpad_sndrcvinfo)); 1.6096 + nxt = TAILQ_NEXT(control, next); 1.6097 + if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) || 1.6098 + sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) { 1.6099 + struct sctp_extrcvinfo *s_extra; 1.6100 + s_extra = (struct sctp_extrcvinfo *)sinfo; 1.6101 + if ((nxt) && 1.6102 + (nxt->length)) { 1.6103 + s_extra->sreinfo_next_flags = SCTP_NEXT_MSG_AVAIL; 1.6104 + if (nxt->sinfo_flags & SCTP_UNORDERED) { 1.6105 + s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED; 1.6106 + } 1.6107 + if (nxt->spec_flags & M_NOTIFICATION) { 1.6108 + s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION; 1.6109 + } 1.6110 + s_extra->sreinfo_next_aid = nxt->sinfo_assoc_id; 1.6111 + s_extra->sreinfo_next_length = nxt->length; 1.6112 + s_extra->sreinfo_next_ppid = nxt->sinfo_ppid; 1.6113 + s_extra->sreinfo_next_stream = nxt->sinfo_stream; 1.6114 + if (nxt->tail_mbuf != NULL) { 1.6115 + if (nxt->end_added) { 1.6116 + s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE; 1.6117 + } 1.6118 + } 1.6119 + } else { 1.6120 + /* we explicitly 0 this, since the memcpy got 1.6121 + * some other things beyond the older sinfo_ 1.6122 + * that is on the control's structure :-D 1.6123 + */ 1.6124 + nxt = NULL; 1.6125 + s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG; 1.6126 + s_extra->sreinfo_next_aid = 0; 1.6127 + s_extra->sreinfo_next_length = 0; 1.6128 + s_extra->sreinfo_next_ppid = 0; 1.6129 + s_extra->sreinfo_next_stream = 0; 1.6130 + } 1.6131 + } 1.6132 + /* 1.6133 + * update off the real current cum-ack, if we have an stcb. 1.6134 + */ 1.6135 + if ((control->do_not_ref_stcb == 0) && stcb) 1.6136 + sinfo->sinfo_cumtsn = stcb->asoc.cumulative_tsn; 1.6137 + /* 1.6138 + * mask off the high bits, we keep the actual chunk bits in 1.6139 + * there. 1.6140 + */ 1.6141 + sinfo->sinfo_flags &= 0x00ff; 1.6142 + if ((control->sinfo_flags >> 8) & SCTP_DATA_UNORDERED) { 1.6143 + sinfo->sinfo_flags |= SCTP_UNORDERED; 1.6144 + } 1.6145 + } 1.6146 +#ifdef SCTP_ASOCLOG_OF_TSNS 1.6147 + { 1.6148 + int index, newindex; 1.6149 + struct sctp_pcbtsn_rlog *entry; 1.6150 + do { 1.6151 + index = inp->readlog_index; 1.6152 + newindex = index + 1; 1.6153 + if (newindex >= SCTP_READ_LOG_SIZE) { 1.6154 + newindex = 0; 1.6155 + } 1.6156 + } while (atomic_cmpset_int(&inp->readlog_index, index, newindex) == 0); 1.6157 + entry = &inp->readlog[index]; 1.6158 + entry->vtag = control->sinfo_assoc_id; 1.6159 + entry->strm = control->sinfo_stream; 1.6160 + entry->seq = control->sinfo_ssn; 1.6161 + entry->sz = control->length; 1.6162 + entry->flgs = control->sinfo_flags; 1.6163 + } 1.6164 +#endif 1.6165 + if (fromlen && from) { 1.6166 +#ifdef HAVE_SA_LEN 1.6167 + cp_len = min((size_t)fromlen, (size_t)control->whoFrom->ro._l_addr.sa.sa_len); 1.6168 +#endif 1.6169 + switch (control->whoFrom->ro._l_addr.sa.sa_family) { 1.6170 +#ifdef INET6 1.6171 + case AF_INET6: 1.6172 +#ifndef HAVE_SA_LEN 1.6173 + cp_len = min((size_t)fromlen, sizeof(struct sockaddr_in6)); 1.6174 +#endif 1.6175 + ((struct sockaddr_in6 *)from)->sin6_port = control->port_from; 1.6176 + break; 1.6177 +#endif 1.6178 +#ifdef INET 1.6179 + case AF_INET: 1.6180 +#ifndef HAVE_SA_LEN 1.6181 + cp_len = min((size_t)fromlen, sizeof(struct sockaddr_in)); 1.6182 +#endif 1.6183 + ((struct sockaddr_in *)from)->sin_port = control->port_from; 1.6184 + break; 1.6185 +#endif 1.6186 +#if defined(__Userspace__) 1.6187 + case AF_CONN: 1.6188 +#ifndef HAVE_SA_LEN 1.6189 + cp_len = min((size_t)fromlen, sizeof(struct sockaddr_conn)); 1.6190 +#endif 1.6191 + ((struct sockaddr_conn *)from)->sconn_port = control->port_from; 1.6192 + break; 1.6193 +#endif 1.6194 + default: 1.6195 +#ifndef HAVE_SA_LEN 1.6196 + cp_len = min((size_t)fromlen, sizeof(struct sockaddr)); 1.6197 +#endif 1.6198 + break; 1.6199 + } 1.6200 + memcpy(from, &control->whoFrom->ro._l_addr, cp_len); 1.6201 + 1.6202 +#if defined(INET) && defined(INET6) 1.6203 + if ((sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) && 1.6204 + (from->sa_family == AF_INET) && 1.6205 + ((size_t)fromlen >= sizeof(struct sockaddr_in6))) { 1.6206 + struct sockaddr_in *sin; 1.6207 + struct sockaddr_in6 sin6; 1.6208 + 1.6209 + sin = (struct sockaddr_in *)from; 1.6210 + bzero(&sin6, sizeof(sin6)); 1.6211 + sin6.sin6_family = AF_INET6; 1.6212 +#ifdef HAVE_SIN6_LEN 1.6213 + sin6.sin6_len = sizeof(struct sockaddr_in6); 1.6214 +#endif 1.6215 +#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Darwin) || defined(__Userspace_os_Windows) 1.6216 + ((uint32_t *)&sin6.sin6_addr)[2] = htonl(0xffff); 1.6217 + bcopy(&sin->sin_addr, 1.6218 + &(((uint32_t *)&sin6.sin6_addr)[3]), 1.6219 + sizeof(uint32_t)); 1.6220 +#elif defined(__Windows__) 1.6221 + ((uint32_t *)&sin6.sin6_addr)[2] = htonl(0xffff); 1.6222 + bcopy(&sin->sin_addr, 1.6223 + &((uint32_t *)&sin6.sin6_addr)[3], 1.6224 + sizeof(uint32_t)); 1.6225 +#else 1.6226 + sin6.sin6_addr.s6_addr32[2] = htonl(0xffff); 1.6227 + bcopy(&sin->sin_addr, 1.6228 + &sin6.sin6_addr.s6_addr32[3], 1.6229 + sizeof(sin6.sin6_addr.s6_addr32[3])); 1.6230 +#endif 1.6231 + sin6.sin6_port = sin->sin_port; 1.6232 + memcpy(from, &sin6, sizeof(struct sockaddr_in6)); 1.6233 + } 1.6234 +#endif 1.6235 +#if defined(SCTP_EMBEDDED_V6_SCOPE) 1.6236 +#ifdef INET6 1.6237 + { 1.6238 + struct sockaddr_in6 lsa6, *from6; 1.6239 + 1.6240 + from6 = (struct sockaddr_in6 *)from; 1.6241 + sctp_recover_scope_mac(from6, (&lsa6)); 1.6242 + } 1.6243 +#endif 1.6244 +#endif 1.6245 + } 1.6246 + /* now copy out what data we can */ 1.6247 + if (mp == NULL) { 1.6248 + /* copy out each mbuf in the chain up to length */ 1.6249 + get_more_data: 1.6250 + m = control->data; 1.6251 + while (m) { 1.6252 + /* Move out all we can */ 1.6253 +#if defined(__APPLE__) 1.6254 +#if defined(APPLE_LEOPARD) 1.6255 + cp_len = (int)uio->uio_resid; 1.6256 +#else 1.6257 + cp_len = (int)uio_resid(uio); 1.6258 +#endif 1.6259 +#else 1.6260 + cp_len = (int)uio->uio_resid; 1.6261 +#endif 1.6262 + my_len = (int)SCTP_BUF_LEN(m); 1.6263 + if (cp_len > my_len) { 1.6264 + /* not enough in this buf */ 1.6265 + cp_len = my_len; 1.6266 + } 1.6267 + if (hold_rlock) { 1.6268 + SCTP_INP_READ_UNLOCK(inp); 1.6269 + hold_rlock = 0; 1.6270 + } 1.6271 +#if defined(__APPLE__) 1.6272 + SCTP_SOCKET_UNLOCK(so, 0); 1.6273 +#endif 1.6274 + if (cp_len > 0) 1.6275 + error = uiomove(mtod(m, char *), cp_len, uio); 1.6276 +#if defined(__APPLE__) 1.6277 + SCTP_SOCKET_LOCK(so, 0); 1.6278 +#endif 1.6279 + /* re-read */ 1.6280 + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) { 1.6281 + goto release; 1.6282 + } 1.6283 + 1.6284 + if ((control->do_not_ref_stcb == 0) && stcb && 1.6285 + stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 1.6286 + no_rcv_needed = 1; 1.6287 + } 1.6288 + if (error) { 1.6289 + /* error we are out of here */ 1.6290 + goto release; 1.6291 + } 1.6292 + if ((SCTP_BUF_NEXT(m) == NULL) && 1.6293 + (cp_len >= SCTP_BUF_LEN(m)) && 1.6294 + ((control->end_added == 0) || 1.6295 + (control->end_added && 1.6296 + (TAILQ_NEXT(control, next) == NULL))) 1.6297 + ) { 1.6298 + SCTP_INP_READ_LOCK(inp); 1.6299 + hold_rlock = 1; 1.6300 + } 1.6301 + if (cp_len == SCTP_BUF_LEN(m)) { 1.6302 + if ((SCTP_BUF_NEXT(m)== NULL) && 1.6303 + (control->end_added)) { 1.6304 + out_flags |= MSG_EOR; 1.6305 + if ((control->do_not_ref_stcb == 0) && 1.6306 + (control->stcb != NULL) && 1.6307 + ((control->spec_flags & M_NOTIFICATION) == 0)) 1.6308 + control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 1.6309 + } 1.6310 + if (control->spec_flags & M_NOTIFICATION) { 1.6311 + out_flags |= MSG_NOTIFICATION; 1.6312 + } 1.6313 + /* we ate up the mbuf */ 1.6314 + if (in_flags & MSG_PEEK) { 1.6315 + /* just looking */ 1.6316 + m = SCTP_BUF_NEXT(m); 1.6317 + copied_so_far += cp_len; 1.6318 + } else { 1.6319 + /* dispose of the mbuf */ 1.6320 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.6321 + sctp_sblog(&so->so_rcv, 1.6322 + control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); 1.6323 + } 1.6324 + sctp_sbfree(control, stcb, &so->so_rcv, m); 1.6325 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.6326 + sctp_sblog(&so->so_rcv, 1.6327 + control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0); 1.6328 + } 1.6329 + copied_so_far += cp_len; 1.6330 + freed_so_far += cp_len; 1.6331 + freed_so_far += MSIZE; 1.6332 + atomic_subtract_int(&control->length, cp_len); 1.6333 + control->data = sctp_m_free(m); 1.6334 + m = control->data; 1.6335 + /* been through it all, must hold sb lock ok to null tail */ 1.6336 + if (control->data == NULL) { 1.6337 +#ifdef INVARIANTS 1.6338 +#if !defined(__APPLE__) 1.6339 + if ((control->end_added == 0) || 1.6340 + (TAILQ_NEXT(control, next) == NULL)) { 1.6341 + /* If the end is not added, OR the 1.6342 + * next is NOT null we MUST have the lock. 1.6343 + */ 1.6344 + if (mtx_owned(&inp->inp_rdata_mtx) == 0) { 1.6345 + panic("Hmm we don't own the lock?"); 1.6346 + } 1.6347 + } 1.6348 +#endif 1.6349 +#endif 1.6350 + control->tail_mbuf = NULL; 1.6351 +#ifdef INVARIANTS 1.6352 + if ((control->end_added) && ((out_flags & MSG_EOR) == 0)) { 1.6353 + panic("end_added, nothing left and no MSG_EOR"); 1.6354 + } 1.6355 +#endif 1.6356 + } 1.6357 + } 1.6358 + } else { 1.6359 + /* Do we need to trim the mbuf? */ 1.6360 + if (control->spec_flags & M_NOTIFICATION) { 1.6361 + out_flags |= MSG_NOTIFICATION; 1.6362 + } 1.6363 + if ((in_flags & MSG_PEEK) == 0) { 1.6364 + SCTP_BUF_RESV_UF(m, cp_len); 1.6365 + SCTP_BUF_LEN(m) -= cp_len; 1.6366 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.6367 + sctp_sblog(&so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE, cp_len); 1.6368 + } 1.6369 + atomic_subtract_int(&so->so_rcv.sb_cc, cp_len); 1.6370 + if ((control->do_not_ref_stcb == 0) && 1.6371 + stcb) { 1.6372 + atomic_subtract_int(&stcb->asoc.sb_cc, cp_len); 1.6373 + } 1.6374 + copied_so_far += cp_len; 1.6375 + freed_so_far += cp_len; 1.6376 + freed_so_far += MSIZE; 1.6377 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.6378 + sctp_sblog(&so->so_rcv, control->do_not_ref_stcb?NULL:stcb, 1.6379 + SCTP_LOG_SBRESULT, 0); 1.6380 + } 1.6381 + atomic_subtract_int(&control->length, cp_len); 1.6382 + } else { 1.6383 + copied_so_far += cp_len; 1.6384 + } 1.6385 + } 1.6386 +#if defined(__APPLE__) 1.6387 +#if defined(APPLE_LEOPARD) 1.6388 + if ((out_flags & MSG_EOR) || (uio->uio_resid == 0)) { 1.6389 +#else 1.6390 + if ((out_flags & MSG_EOR) || (uio_resid(uio) == 0)) { 1.6391 +#endif 1.6392 +#else 1.6393 + if ((out_flags & MSG_EOR) || (uio->uio_resid == 0)) { 1.6394 +#endif 1.6395 + break; 1.6396 + } 1.6397 + if (((stcb) && (in_flags & MSG_PEEK) == 0) && 1.6398 + (control->do_not_ref_stcb == 0) && 1.6399 + (freed_so_far >= rwnd_req)) { 1.6400 + sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 1.6401 + } 1.6402 + } /* end while(m) */ 1.6403 + /* 1.6404 + * At this point we have looked at it all and we either have 1.6405 + * a MSG_EOR/or read all the user wants... <OR> 1.6406 + * control->length == 0. 1.6407 + */ 1.6408 + if ((out_flags & MSG_EOR) && ((in_flags & MSG_PEEK) == 0)) { 1.6409 + /* we are done with this control */ 1.6410 + if (control->length == 0) { 1.6411 + if (control->data) { 1.6412 +#ifdef INVARIANTS 1.6413 + panic("control->data not null at read eor?"); 1.6414 +#else 1.6415 + SCTP_PRINTF("Strange, data left in the control buffer .. invarients would panic?\n"); 1.6416 + sctp_m_freem(control->data); 1.6417 + control->data = NULL; 1.6418 +#endif 1.6419 + } 1.6420 + done_with_control: 1.6421 + if (TAILQ_NEXT(control, next) == NULL) { 1.6422 + /* If we don't have a next we need a 1.6423 + * lock, if there is a next interrupt 1.6424 + * is filling ahead of us and we don't 1.6425 + * need a lock to remove this guy 1.6426 + * (which is the head of the queue). 1.6427 + */ 1.6428 + if (hold_rlock == 0) { 1.6429 + SCTP_INP_READ_LOCK(inp); 1.6430 + hold_rlock = 1; 1.6431 + } 1.6432 + } 1.6433 + TAILQ_REMOVE(&inp->read_queue, control, next); 1.6434 + /* Add back any hiddend data */ 1.6435 + if (control->held_length) { 1.6436 + held_length = 0; 1.6437 + control->held_length = 0; 1.6438 + wakeup_read_socket = 1; 1.6439 + } 1.6440 + if (control->aux_data) { 1.6441 + sctp_m_free (control->aux_data); 1.6442 + control->aux_data = NULL; 1.6443 + } 1.6444 + no_rcv_needed = control->do_not_ref_stcb; 1.6445 + sctp_free_remote_addr(control->whoFrom); 1.6446 + control->data = NULL; 1.6447 + sctp_free_a_readq(stcb, control); 1.6448 + control = NULL; 1.6449 + if ((freed_so_far >= rwnd_req) && 1.6450 + (no_rcv_needed == 0)) 1.6451 + sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 1.6452 + 1.6453 + } else { 1.6454 + /* 1.6455 + * The user did not read all of this 1.6456 + * message, turn off the returned MSG_EOR 1.6457 + * since we are leaving more behind on the 1.6458 + * control to read. 1.6459 + */ 1.6460 +#ifdef INVARIANTS 1.6461 + if (control->end_added && 1.6462 + (control->data == NULL) && 1.6463 + (control->tail_mbuf == NULL)) { 1.6464 + panic("Gak, control->length is corrupt?"); 1.6465 + } 1.6466 +#endif 1.6467 + no_rcv_needed = control->do_not_ref_stcb; 1.6468 + out_flags &= ~MSG_EOR; 1.6469 + } 1.6470 + } 1.6471 + if (out_flags & MSG_EOR) { 1.6472 + goto release; 1.6473 + } 1.6474 +#if defined(__APPLE__) 1.6475 +#if defined(APPLE_LEOPARD) 1.6476 + if ((uio->uio_resid == 0) || 1.6477 +#else 1.6478 + if ((uio_resid(uio) == 0) || 1.6479 +#endif 1.6480 +#else 1.6481 + if ((uio->uio_resid == 0) || 1.6482 +#endif 1.6483 + ((in_eeor_mode) && 1.6484 + (copied_so_far >= (uint32_t)max(so->so_rcv.sb_lowat, 1)))) { 1.6485 + goto release; 1.6486 + } 1.6487 + /* 1.6488 + * If I hit here the receiver wants more and this message is 1.6489 + * NOT done (pd-api). So two questions. Can we block? if not 1.6490 + * we are done. Did the user NOT set MSG_WAITALL? 1.6491 + */ 1.6492 + if (block_allowed == 0) { 1.6493 + goto release; 1.6494 + } 1.6495 + /* 1.6496 + * We need to wait for more data a few things: - We don't 1.6497 + * sbunlock() so we don't get someone else reading. - We 1.6498 + * must be sure to account for the case where what is added 1.6499 + * is NOT to our control when we wakeup. 1.6500 + */ 1.6501 + 1.6502 + /* Do we need to tell the transport a rwnd update might be 1.6503 + * needed before we go to sleep? 1.6504 + */ 1.6505 + if (((stcb) && (in_flags & MSG_PEEK) == 0) && 1.6506 + ((freed_so_far >= rwnd_req) && 1.6507 + (control->do_not_ref_stcb == 0) && 1.6508 + (no_rcv_needed == 0))) { 1.6509 + sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 1.6510 + } 1.6511 + wait_some_more: 1.6512 +#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__) 1.6513 + if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { 1.6514 + goto release; 1.6515 + } 1.6516 +#else 1.6517 + if (so->so_state & SS_CANTRCVMORE) { 1.6518 + goto release; 1.6519 + } 1.6520 +#endif 1.6521 + 1.6522 + if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) 1.6523 + goto release; 1.6524 + 1.6525 + if (hold_rlock == 1) { 1.6526 + SCTP_INP_READ_UNLOCK(inp); 1.6527 + hold_rlock = 0; 1.6528 + } 1.6529 + if (hold_sblock == 0) { 1.6530 + SOCKBUF_LOCK(&so->so_rcv); 1.6531 + hold_sblock = 1; 1.6532 + } 1.6533 +#if defined(__APPLE__) 1.6534 + sbunlock(&so->so_rcv, 1); 1.6535 +#endif 1.6536 + if ((copied_so_far) && (control->length == 0) && 1.6537 + (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE))) { 1.6538 + goto release; 1.6539 + } 1.6540 + if (so->so_rcv.sb_cc <= control->held_length) { 1.6541 + error = sbwait(&so->so_rcv); 1.6542 + if (error) { 1.6543 +#if defined(__FreeBSD__) 1.6544 + goto release; 1.6545 +#else 1.6546 + goto release_unlocked; 1.6547 +#endif 1.6548 + } 1.6549 + control->held_length = 0; 1.6550 + } 1.6551 +#if defined(__APPLE__) 1.6552 + error = sblock(&so->so_rcv, SBLOCKWAIT(in_flags)); 1.6553 +#endif 1.6554 + if (hold_sblock) { 1.6555 + SOCKBUF_UNLOCK(&so->so_rcv); 1.6556 + hold_sblock = 0; 1.6557 + } 1.6558 + if (control->length == 0) { 1.6559 + /* still nothing here */ 1.6560 + if (control->end_added == 1) { 1.6561 + /* he aborted, or is done i.e.did a shutdown */ 1.6562 + out_flags |= MSG_EOR; 1.6563 + if (control->pdapi_aborted) { 1.6564 + if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0)) 1.6565 + control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 1.6566 + 1.6567 + out_flags |= MSG_TRUNC; 1.6568 + } else { 1.6569 + if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0)) 1.6570 + control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 1.6571 + } 1.6572 + goto done_with_control; 1.6573 + } 1.6574 + if (so->so_rcv.sb_cc > held_length) { 1.6575 + control->held_length = so->so_rcv.sb_cc; 1.6576 + held_length = 0; 1.6577 + } 1.6578 + goto wait_some_more; 1.6579 + } else if (control->data == NULL) { 1.6580 + /* we must re-sync since data 1.6581 + * is probably being added 1.6582 + */ 1.6583 + SCTP_INP_READ_LOCK(inp); 1.6584 + if ((control->length > 0) && (control->data == NULL)) { 1.6585 + /* big trouble.. we have the lock and its corrupt? */ 1.6586 +#ifdef INVARIANTS 1.6587 + panic ("Impossible data==NULL length !=0"); 1.6588 +#endif 1.6589 + out_flags |= MSG_EOR; 1.6590 + out_flags |= MSG_TRUNC; 1.6591 + control->length = 0; 1.6592 + SCTP_INP_READ_UNLOCK(inp); 1.6593 + goto done_with_control; 1.6594 + } 1.6595 + SCTP_INP_READ_UNLOCK(inp); 1.6596 + /* We will fall around to get more data */ 1.6597 + } 1.6598 + goto get_more_data; 1.6599 + } else { 1.6600 + /*- 1.6601 + * Give caller back the mbuf chain, 1.6602 + * store in uio_resid the length 1.6603 + */ 1.6604 + wakeup_read_socket = 0; 1.6605 + if ((control->end_added == 0) || 1.6606 + (TAILQ_NEXT(control, next) == NULL)) { 1.6607 + /* Need to get rlock */ 1.6608 + if (hold_rlock == 0) { 1.6609 + SCTP_INP_READ_LOCK(inp); 1.6610 + hold_rlock = 1; 1.6611 + } 1.6612 + } 1.6613 + if (control->end_added) { 1.6614 + out_flags |= MSG_EOR; 1.6615 + if ((control->do_not_ref_stcb == 0) && 1.6616 + (control->stcb != NULL) && 1.6617 + ((control->spec_flags & M_NOTIFICATION) == 0)) 1.6618 + control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0; 1.6619 + } 1.6620 + if (control->spec_flags & M_NOTIFICATION) { 1.6621 + out_flags |= MSG_NOTIFICATION; 1.6622 + } 1.6623 +#if defined(__APPLE__) 1.6624 +#if defined(APPLE_LEOPARD) 1.6625 + uio->uio_resid = control->length; 1.6626 +#else 1.6627 + uio_setresid(uio, control->length); 1.6628 +#endif 1.6629 +#else 1.6630 + uio->uio_resid = control->length; 1.6631 +#endif 1.6632 + *mp = control->data; 1.6633 + m = control->data; 1.6634 + while (m) { 1.6635 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.6636 + sctp_sblog(&so->so_rcv, 1.6637 + control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m)); 1.6638 + } 1.6639 + sctp_sbfree(control, stcb, &so->so_rcv, m); 1.6640 + freed_so_far += SCTP_BUF_LEN(m); 1.6641 + freed_so_far += MSIZE; 1.6642 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) { 1.6643 + sctp_sblog(&so->so_rcv, 1.6644 + control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0); 1.6645 + } 1.6646 + m = SCTP_BUF_NEXT(m); 1.6647 + } 1.6648 + control->data = control->tail_mbuf = NULL; 1.6649 + control->length = 0; 1.6650 + if (out_flags & MSG_EOR) { 1.6651 + /* Done with this control */ 1.6652 + goto done_with_control; 1.6653 + } 1.6654 + } 1.6655 + release: 1.6656 + if (hold_rlock == 1) { 1.6657 + SCTP_INP_READ_UNLOCK(inp); 1.6658 + hold_rlock = 0; 1.6659 + } 1.6660 +#if (defined(__FreeBSD__) && __FreeBSD_version < 700000) || defined(__Userspace__) 1.6661 + if (hold_sblock == 0) { 1.6662 + SOCKBUF_LOCK(&so->so_rcv); 1.6663 + hold_sblock = 1; 1.6664 + } 1.6665 +#else 1.6666 + if (hold_sblock == 1) { 1.6667 + SOCKBUF_UNLOCK(&so->so_rcv); 1.6668 + hold_sblock = 0; 1.6669 + } 1.6670 +#endif 1.6671 +#if defined(__APPLE__) 1.6672 + sbunlock(&so->so_rcv, 1); 1.6673 +#endif 1.6674 + 1.6675 +#if defined(__FreeBSD__) 1.6676 + sbunlock(&so->so_rcv); 1.6677 +#if defined(__FreeBSD__) && __FreeBSD_version >= 700000 1.6678 + sockbuf_lock = 0; 1.6679 +#endif 1.6680 +#endif 1.6681 + 1.6682 + release_unlocked: 1.6683 + if (hold_sblock) { 1.6684 + SOCKBUF_UNLOCK(&so->so_rcv); 1.6685 + hold_sblock = 0; 1.6686 + } 1.6687 + if ((stcb) && (in_flags & MSG_PEEK) == 0) { 1.6688 + if ((freed_so_far >= rwnd_req) && 1.6689 + (control && (control->do_not_ref_stcb == 0)) && 1.6690 + (no_rcv_needed == 0)) 1.6691 + sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req); 1.6692 + } 1.6693 + out: 1.6694 + if (msg_flags) { 1.6695 + *msg_flags = out_flags; 1.6696 + } 1.6697 + if (((out_flags & MSG_EOR) == 0) && 1.6698 + ((in_flags & MSG_PEEK) == 0) && 1.6699 + (sinfo) && 1.6700 + (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) || 1.6701 + sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO))) { 1.6702 + struct sctp_extrcvinfo *s_extra; 1.6703 + s_extra = (struct sctp_extrcvinfo *)sinfo; 1.6704 + s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG; 1.6705 + } 1.6706 + if (hold_rlock == 1) { 1.6707 + SCTP_INP_READ_UNLOCK(inp); 1.6708 + } 1.6709 + if (hold_sblock) { 1.6710 + SOCKBUF_UNLOCK(&so->so_rcv); 1.6711 + } 1.6712 +#if defined(__FreeBSD__) && __FreeBSD_version >= 700000 1.6713 + if (sockbuf_lock) { 1.6714 + sbunlock(&so->so_rcv); 1.6715 + } 1.6716 +#endif 1.6717 + 1.6718 + if (freecnt_applied) { 1.6719 + /* 1.6720 + * The lock on the socket buffer protects us so the free 1.6721 + * code will stop. But since we used the socketbuf lock and 1.6722 + * the sender uses the tcb_lock to increment, we need to use 1.6723 + * the atomic add to the refcnt. 1.6724 + */ 1.6725 + if (stcb == NULL) { 1.6726 +#ifdef INVARIANTS 1.6727 + panic("stcb for refcnt has gone NULL?"); 1.6728 + goto stage_left; 1.6729 +#else 1.6730 + goto stage_left; 1.6731 +#endif 1.6732 + } 1.6733 + atomic_add_int(&stcb->asoc.refcnt, -1); 1.6734 + /* Save the value back for next time */ 1.6735 + stcb->freed_by_sorcv_sincelast = freed_so_far; 1.6736 + } 1.6737 + if (SCTP_BASE_SYSCTL(sctp_logging_level) &SCTP_RECV_RWND_LOGGING_ENABLE) { 1.6738 + if (stcb) { 1.6739 + sctp_misc_ints(SCTP_SORECV_DONE, 1.6740 + freed_so_far, 1.6741 +#if defined(__APPLE__) 1.6742 +#if defined(APPLE_LEOPARD) 1.6743 + ((uio) ? (slen - uio->uio_resid) : slen), 1.6744 +#else 1.6745 + ((uio) ? (slen - uio_resid(uio)) : slen), 1.6746 +#endif 1.6747 +#else 1.6748 + ((uio) ? (slen - uio->uio_resid) : slen), 1.6749 +#endif 1.6750 + stcb->asoc.my_rwnd, 1.6751 + so->so_rcv.sb_cc); 1.6752 + } else { 1.6753 + sctp_misc_ints(SCTP_SORECV_DONE, 1.6754 + freed_so_far, 1.6755 +#if defined(__APPLE__) 1.6756 +#if defined(APPLE_LEOPARD) 1.6757 + ((uio) ? (slen - uio->uio_resid) : slen), 1.6758 +#else 1.6759 + ((uio) ? (slen - uio_resid(uio)) : slen), 1.6760 +#endif 1.6761 +#else 1.6762 + ((uio) ? (slen - uio->uio_resid) : slen), 1.6763 +#endif 1.6764 + 0, 1.6765 + so->so_rcv.sb_cc); 1.6766 + } 1.6767 + } 1.6768 + stage_left: 1.6769 + if (wakeup_read_socket) { 1.6770 + sctp_sorwakeup(inp, so); 1.6771 + } 1.6772 + return (error); 1.6773 +} 1.6774 + 1.6775 + 1.6776 +#ifdef SCTP_MBUF_LOGGING 1.6777 +struct mbuf * 1.6778 +sctp_m_free(struct mbuf *m) 1.6779 +{ 1.6780 + if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { 1.6781 + if (SCTP_BUF_IS_EXTENDED(m)) { 1.6782 + sctp_log_mb(m, SCTP_MBUF_IFREE); 1.6783 + } 1.6784 + } 1.6785 + return (m_free(m)); 1.6786 +} 1.6787 + 1.6788 +void sctp_m_freem(struct mbuf *mb) 1.6789 +{ 1.6790 + while (mb != NULL) 1.6791 + mb = sctp_m_free(mb); 1.6792 +} 1.6793 + 1.6794 +#endif 1.6795 + 1.6796 +int 1.6797 +sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id) 1.6798 +{ 1.6799 + /* Given a local address. For all associations 1.6800 + * that holds the address, request a peer-set-primary. 1.6801 + */ 1.6802 + struct sctp_ifa *ifa; 1.6803 + struct sctp_laddr *wi; 1.6804 + 1.6805 + ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0); 1.6806 + if (ifa == NULL) { 1.6807 + SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EADDRNOTAVAIL); 1.6808 + return (EADDRNOTAVAIL); 1.6809 + } 1.6810 + /* Now that we have the ifa we must awaken the 1.6811 + * iterator with this message. 1.6812 + */ 1.6813 + wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); 1.6814 + if (wi == NULL) { 1.6815 + SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOMEM); 1.6816 + return (ENOMEM); 1.6817 + } 1.6818 + /* Now incr the count and int wi structure */ 1.6819 + SCTP_INCR_LADDR_COUNT(); 1.6820 + bzero(wi, sizeof(*wi)); 1.6821 + (void)SCTP_GETTIME_TIMEVAL(&wi->start_time); 1.6822 + wi->ifa = ifa; 1.6823 + wi->action = SCTP_SET_PRIM_ADDR; 1.6824 + atomic_add_int(&ifa->refcount, 1); 1.6825 + 1.6826 + /* Now add it to the work queue */ 1.6827 + SCTP_WQ_ADDR_LOCK(); 1.6828 + /* 1.6829 + * Should this really be a tailq? As it is we will process the 1.6830 + * newest first :-0 1.6831 + */ 1.6832 + LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr); 1.6833 + SCTP_WQ_ADDR_UNLOCK(); 1.6834 + sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ, 1.6835 + (struct sctp_inpcb *)NULL, 1.6836 + (struct sctp_tcb *)NULL, 1.6837 + (struct sctp_nets *)NULL); 1.6838 + return (0); 1.6839 +} 1.6840 + 1.6841 +#if defined(__Userspace__) 1.6842 +/* no sctp_soreceive for __Userspace__ now */ 1.6843 +#endif 1.6844 + 1.6845 +#if !defined(__Userspace__) 1.6846 +int 1.6847 +sctp_soreceive( struct socket *so, 1.6848 + struct sockaddr **psa, 1.6849 + struct uio *uio, 1.6850 + struct mbuf **mp0, 1.6851 + struct mbuf **controlp, 1.6852 + int *flagsp) 1.6853 +{ 1.6854 + int error, fromlen; 1.6855 + uint8_t sockbuf[256]; 1.6856 + struct sockaddr *from; 1.6857 + struct sctp_extrcvinfo sinfo; 1.6858 + int filling_sinfo = 1; 1.6859 + struct sctp_inpcb *inp; 1.6860 + 1.6861 + inp = (struct sctp_inpcb *)so->so_pcb; 1.6862 + /* pickup the assoc we are reading from */ 1.6863 + if (inp == NULL) { 1.6864 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.6865 + return (EINVAL); 1.6866 + } 1.6867 + if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) && 1.6868 + sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) && 1.6869 + sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) || 1.6870 + (controlp == NULL)) { 1.6871 + /* user does not want the sndrcv ctl */ 1.6872 + filling_sinfo = 0; 1.6873 + } 1.6874 + if (psa) { 1.6875 + from = (struct sockaddr *)sockbuf; 1.6876 + fromlen = sizeof(sockbuf); 1.6877 +#ifdef HAVE_SA_LEN 1.6878 + from->sa_len = 0; 1.6879 +#endif 1.6880 + } else { 1.6881 + from = NULL; 1.6882 + fromlen = 0; 1.6883 + } 1.6884 + 1.6885 +#if defined(__APPLE__) 1.6886 + SCTP_SOCKET_LOCK(so, 1); 1.6887 +#endif 1.6888 + error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, flagsp, 1.6889 + (struct sctp_sndrcvinfo *)&sinfo, filling_sinfo); 1.6890 + if ((controlp) && (filling_sinfo)) { 1.6891 + /* copy back the sinfo in a CMSG format */ 1.6892 + if (filling_sinfo) 1.6893 + *controlp = sctp_build_ctl_nchunk(inp, 1.6894 + (struct sctp_sndrcvinfo *)&sinfo); 1.6895 + else 1.6896 + *controlp = NULL; 1.6897 + } 1.6898 + if (psa) { 1.6899 + /* copy back the address info */ 1.6900 +#ifdef HAVE_SA_LEN 1.6901 + if (from && from->sa_len) { 1.6902 +#else 1.6903 + if (from) { 1.6904 +#endif 1.6905 +#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__) 1.6906 + *psa = sodupsockaddr(from, M_NOWAIT); 1.6907 +#else 1.6908 + *psa = dup_sockaddr(from, mp0 == 0); 1.6909 +#endif 1.6910 + } else { 1.6911 + *psa = NULL; 1.6912 + } 1.6913 + } 1.6914 +#if defined(__APPLE__) 1.6915 + SCTP_SOCKET_UNLOCK(so, 1); 1.6916 +#endif 1.6917 + return (error); 1.6918 +} 1.6919 + 1.6920 + 1.6921 +#if (defined(__FreeBSD__) && __FreeBSD_version < 603000) || defined(__Windows__) 1.6922 +/* 1.6923 + * General routine to allocate a hash table with control of memory flags. 1.6924 + * is in 7.0 and beyond for sure :-) 1.6925 + */ 1.6926 +void * 1.6927 +sctp_hashinit_flags(int elements, struct malloc_type *type, 1.6928 + u_long *hashmask, int flags) 1.6929 +{ 1.6930 + long hashsize; 1.6931 + LIST_HEAD(generic, generic) *hashtbl; 1.6932 + int i; 1.6933 + 1.6934 + 1.6935 + if (elements <= 0) { 1.6936 +#ifdef INVARIANTS 1.6937 + panic("hashinit: bad elements"); 1.6938 +#else 1.6939 + SCTP_PRINTF("hashinit: bad elements?"); 1.6940 + elements = 1; 1.6941 +#endif 1.6942 + } 1.6943 + for (hashsize = 1; hashsize <= elements; hashsize <<= 1) 1.6944 + continue; 1.6945 + hashsize >>= 1; 1.6946 + if (flags & HASH_WAITOK) 1.6947 + hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK); 1.6948 + else if (flags & HASH_NOWAIT) 1.6949 + hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_NOWAIT); 1.6950 + else { 1.6951 +#ifdef INVARIANTS 1.6952 + panic("flag incorrect in hashinit_flags"); 1.6953 +#else 1.6954 + return (NULL); 1.6955 +#endif 1.6956 + } 1.6957 + 1.6958 + /* no memory? */ 1.6959 + if (hashtbl == NULL) 1.6960 + return (NULL); 1.6961 + 1.6962 + for (i = 0; i < hashsize; i++) 1.6963 + LIST_INIT(&hashtbl[i]); 1.6964 + *hashmask = hashsize - 1; 1.6965 + return (hashtbl); 1.6966 +} 1.6967 +#endif 1.6968 + 1.6969 +#else /* __Userspace__ ifdef above sctp_soreceive */ 1.6970 +/* 1.6971 + * __Userspace__ Defining sctp_hashinit_flags() and sctp_hashdestroy() for userland. 1.6972 + * NOTE: We don't want multiple definitions here. So sctp_hashinit_flags() above for 1.6973 + *__FreeBSD__ must be excluded. 1.6974 + * 1.6975 + */ 1.6976 + 1.6977 +void * 1.6978 +sctp_hashinit_flags(int elements, struct malloc_type *type, 1.6979 + u_long *hashmask, int flags) 1.6980 +{ 1.6981 + long hashsize; 1.6982 + LIST_HEAD(generic, generic) *hashtbl; 1.6983 + int i; 1.6984 + 1.6985 + if (elements <= 0) { 1.6986 + SCTP_PRINTF("hashinit: bad elements?"); 1.6987 +#ifdef INVARIANTS 1.6988 + return (NULL); 1.6989 +#else 1.6990 + elements = 1; 1.6991 +#endif 1.6992 + } 1.6993 + for (hashsize = 1; hashsize <= elements; hashsize <<= 1) 1.6994 + continue; 1.6995 + hashsize >>= 1; 1.6996 + /*cannot use MALLOC here because it has to be declared or defined 1.6997 + using MALLOC_DECLARE or MALLOC_DEFINE first. */ 1.6998 + if (flags & HASH_WAITOK) 1.6999 + hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl)); 1.7000 + else if (flags & HASH_NOWAIT) 1.7001 + hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl)); 1.7002 + else { 1.7003 +#ifdef INVARIANTS 1.7004 + SCTP_PRINTF("flag incorrect in hashinit_flags.\n"); 1.7005 +#endif 1.7006 + return (NULL); 1.7007 + } 1.7008 + 1.7009 + /* no memory? */ 1.7010 + if (hashtbl == NULL) 1.7011 + return (NULL); 1.7012 + 1.7013 + for (i = 0; i < hashsize; i++) 1.7014 + LIST_INIT(&hashtbl[i]); 1.7015 + *hashmask = hashsize - 1; 1.7016 + return (hashtbl); 1.7017 +} 1.7018 + 1.7019 + 1.7020 +void 1.7021 +sctp_hashdestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask) 1.7022 +{ 1.7023 + LIST_HEAD(generic, generic) *hashtbl, *hp; 1.7024 + 1.7025 + hashtbl = vhashtbl; 1.7026 + for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++) 1.7027 + if (!LIST_EMPTY(hp)) { 1.7028 + SCTP_PRINTF("hashdestroy: hash not empty.\n"); 1.7029 + return; 1.7030 + } 1.7031 + FREE(hashtbl, type); 1.7032 +} 1.7033 + 1.7034 + 1.7035 +void 1.7036 +sctp_hashfreedestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask) 1.7037 +{ 1.7038 + LIST_HEAD(generic, generic) *hashtbl/*, *hp*/; 1.7039 + /* 1.7040 + LIST_ENTRY(type) *start, *temp; 1.7041 + */ 1.7042 + hashtbl = vhashtbl; 1.7043 + /* Apparently temp is not dynamically allocated, so attempts to 1.7044 + free it results in error. 1.7045 + for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++) 1.7046 + if (!LIST_EMPTY(hp)) { 1.7047 + start = LIST_FIRST(hp); 1.7048 + while (start != NULL) { 1.7049 + temp = start; 1.7050 + start = start->le_next; 1.7051 + SCTP_PRINTF("%s: %p \n", __func__, (void *)temp); 1.7052 + FREE(temp, type); 1.7053 + } 1.7054 + } 1.7055 + */ 1.7056 + FREE(hashtbl, type); 1.7057 +} 1.7058 + 1.7059 + 1.7060 +#endif 1.7061 + 1.7062 + 1.7063 +int 1.7064 +sctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr, 1.7065 + int totaddr, int *error) 1.7066 +{ 1.7067 + int added = 0; 1.7068 + int i; 1.7069 + struct sctp_inpcb *inp; 1.7070 + struct sockaddr *sa; 1.7071 + size_t incr = 0; 1.7072 +#ifdef INET 1.7073 + struct sockaddr_in *sin; 1.7074 +#endif 1.7075 +#ifdef INET6 1.7076 + struct sockaddr_in6 *sin6; 1.7077 +#endif 1.7078 + 1.7079 + sa = addr; 1.7080 + inp = stcb->sctp_ep; 1.7081 + *error = 0; 1.7082 + for (i = 0; i < totaddr; i++) { 1.7083 + switch (sa->sa_family) { 1.7084 +#ifdef INET 1.7085 + case AF_INET: 1.7086 + incr = sizeof(struct sockaddr_in); 1.7087 + sin = (struct sockaddr_in *)sa; 1.7088 + if ((sin->sin_addr.s_addr == INADDR_ANY) || 1.7089 + (sin->sin_addr.s_addr == INADDR_BROADCAST) || 1.7090 + IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { 1.7091 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7092 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7); 1.7093 + *error = EINVAL; 1.7094 + goto out_now; 1.7095 + } 1.7096 + if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { 1.7097 + /* assoc gone no un-lock */ 1.7098 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); 1.7099 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7); 1.7100 + *error = ENOBUFS; 1.7101 + goto out_now; 1.7102 + } 1.7103 + added++; 1.7104 + break; 1.7105 +#endif 1.7106 +#ifdef INET6 1.7107 + case AF_INET6: 1.7108 + incr = sizeof(struct sockaddr_in6); 1.7109 + sin6 = (struct sockaddr_in6 *)sa; 1.7110 + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || 1.7111 + IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { 1.7112 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7113 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8); 1.7114 + *error = EINVAL; 1.7115 + goto out_now; 1.7116 + } 1.7117 + if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { 1.7118 + /* assoc gone no un-lock */ 1.7119 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); 1.7120 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8); 1.7121 + *error = ENOBUFS; 1.7122 + goto out_now; 1.7123 + } 1.7124 + added++; 1.7125 + break; 1.7126 +#endif 1.7127 +#if defined(__Userspace__) 1.7128 + case AF_CONN: 1.7129 + incr = sizeof(struct sockaddr_in6); 1.7130 + if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) { 1.7131 + /* assoc gone no un-lock */ 1.7132 + SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS); 1.7133 + (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8); 1.7134 + *error = ENOBUFS; 1.7135 + goto out_now; 1.7136 + } 1.7137 + added++; 1.7138 + break; 1.7139 +#endif 1.7140 + default: 1.7141 + break; 1.7142 + } 1.7143 + sa = (struct sockaddr *)((caddr_t)sa + incr); 1.7144 + } 1.7145 + out_now: 1.7146 + return (added); 1.7147 +} 1.7148 + 1.7149 +struct sctp_tcb * 1.7150 +sctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr, 1.7151 + int *totaddr, int *num_v4, int *num_v6, int *error, 1.7152 + int limit, int *bad_addr) 1.7153 +{ 1.7154 + struct sockaddr *sa; 1.7155 + struct sctp_tcb *stcb = NULL; 1.7156 + size_t incr, at, i; 1.7157 + at = incr = 0; 1.7158 + sa = addr; 1.7159 + 1.7160 + *error = *num_v6 = *num_v4 = 0; 1.7161 + /* account and validate addresses */ 1.7162 + for (i = 0; i < (size_t)*totaddr; i++) { 1.7163 + switch (sa->sa_family) { 1.7164 +#ifdef INET 1.7165 + case AF_INET: 1.7166 + (*num_v4) += 1; 1.7167 + incr = sizeof(struct sockaddr_in); 1.7168 +#ifdef HAVE_SA_LEN 1.7169 + if (sa->sa_len != incr) { 1.7170 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7171 + *error = EINVAL; 1.7172 + *bad_addr = 1; 1.7173 + return (NULL); 1.7174 + } 1.7175 +#endif 1.7176 + break; 1.7177 +#endif 1.7178 +#ifdef INET6 1.7179 + case AF_INET6: 1.7180 + { 1.7181 + struct sockaddr_in6 *sin6; 1.7182 + 1.7183 + sin6 = (struct sockaddr_in6 *)sa; 1.7184 + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 1.7185 + /* Must be non-mapped for connectx */ 1.7186 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7187 + *error = EINVAL; 1.7188 + *bad_addr = 1; 1.7189 + return (NULL); 1.7190 + } 1.7191 + (*num_v6) += 1; 1.7192 + incr = sizeof(struct sockaddr_in6); 1.7193 +#ifdef HAVE_SA_LEN 1.7194 + if (sa->sa_len != incr) { 1.7195 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7196 + *error = EINVAL; 1.7197 + *bad_addr = 1; 1.7198 + return (NULL); 1.7199 + } 1.7200 +#endif 1.7201 + break; 1.7202 + } 1.7203 +#endif 1.7204 + default: 1.7205 + *totaddr = i; 1.7206 + /* we are done */ 1.7207 + break; 1.7208 + } 1.7209 + if (i == (size_t)*totaddr) { 1.7210 + break; 1.7211 + } 1.7212 + SCTP_INP_INCR_REF(inp); 1.7213 + stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL); 1.7214 + if (stcb != NULL) { 1.7215 + /* Already have or am bring up an association */ 1.7216 + return (stcb); 1.7217 + } else { 1.7218 + SCTP_INP_DECR_REF(inp); 1.7219 + } 1.7220 + if ((at + incr) > (size_t)limit) { 1.7221 + *totaddr = i; 1.7222 + break; 1.7223 + } 1.7224 + sa = (struct sockaddr *)((caddr_t)sa + incr); 1.7225 + } 1.7226 + return ((struct sctp_tcb *)NULL); 1.7227 +} 1.7228 + 1.7229 +/* 1.7230 + * sctp_bindx(ADD) for one address. 1.7231 + * assumes all arguments are valid/checked by caller. 1.7232 + */ 1.7233 +void 1.7234 +sctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp, 1.7235 + struct sockaddr *sa, sctp_assoc_t assoc_id, 1.7236 + uint32_t vrf_id, int *error, void *p) 1.7237 +{ 1.7238 + struct sockaddr *addr_touse; 1.7239 +#ifdef INET6 1.7240 + struct sockaddr_in sin; 1.7241 +#endif 1.7242 +#ifdef SCTP_MVRF 1.7243 + int i, fnd = 0; 1.7244 +#endif 1.7245 + 1.7246 + /* see if we're bound all already! */ 1.7247 + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 1.7248 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7249 + *error = EINVAL; 1.7250 + return; 1.7251 + } 1.7252 +#ifdef SCTP_MVRF 1.7253 + /* Is the VRF one we have */ 1.7254 + for (i = 0; i < inp->num_vrfs; i++) { 1.7255 + if (vrf_id == inp->m_vrf_ids[i]) { 1.7256 + fnd = 1; 1.7257 + break; 1.7258 + } 1.7259 + } 1.7260 + if (!fnd) { 1.7261 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7262 + *error = EINVAL; 1.7263 + return; 1.7264 + } 1.7265 +#endif 1.7266 + addr_touse = sa; 1.7267 +#ifdef INET6 1.7268 + if (sa->sa_family == AF_INET6) { 1.7269 + struct sockaddr_in6 *sin6; 1.7270 +#ifdef HAVE_SA_LEN 1.7271 + if (sa->sa_len != sizeof(struct sockaddr_in6)) { 1.7272 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7273 + *error = EINVAL; 1.7274 + return; 1.7275 + } 1.7276 +#endif 1.7277 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 1.7278 + /* can only bind v6 on PF_INET6 sockets */ 1.7279 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7280 + *error = EINVAL; 1.7281 + return; 1.7282 + } 1.7283 + sin6 = (struct sockaddr_in6 *)addr_touse; 1.7284 + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 1.7285 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1.7286 + SCTP_IPV6_V6ONLY(inp)) { 1.7287 + /* can't bind v4-mapped on PF_INET sockets */ 1.7288 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7289 + *error = EINVAL; 1.7290 + return; 1.7291 + } 1.7292 + in6_sin6_2_sin(&sin, sin6); 1.7293 + addr_touse = (struct sockaddr *)&sin; 1.7294 + } 1.7295 + } 1.7296 +#endif 1.7297 +#ifdef INET 1.7298 + if (sa->sa_family == AF_INET) { 1.7299 +#ifdef HAVE_SA_LEN 1.7300 + if (sa->sa_len != sizeof(struct sockaddr_in)) { 1.7301 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7302 + *error = EINVAL; 1.7303 + return; 1.7304 + } 1.7305 +#endif 1.7306 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1.7307 + SCTP_IPV6_V6ONLY(inp)) { 1.7308 + /* can't bind v4 on PF_INET sockets */ 1.7309 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7310 + *error = EINVAL; 1.7311 + return; 1.7312 + } 1.7313 + } 1.7314 +#endif 1.7315 + if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) { 1.7316 +#if !(defined(__Panda__) || defined(__Windows__)) 1.7317 + if (p == NULL) { 1.7318 + /* Can't get proc for Net/Open BSD */ 1.7319 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7320 + *error = EINVAL; 1.7321 + return; 1.7322 + } 1.7323 +#endif 1.7324 + *error = sctp_inpcb_bind(so, addr_touse, NULL, p); 1.7325 + return; 1.7326 + } 1.7327 + /* 1.7328 + * No locks required here since bind and mgmt_ep_sa 1.7329 + * all do their own locking. If we do something for 1.7330 + * the FIX: below we may need to lock in that case. 1.7331 + */ 1.7332 + if (assoc_id == 0) { 1.7333 + /* add the address */ 1.7334 + struct sctp_inpcb *lep; 1.7335 + struct sockaddr_in *lsin = (struct sockaddr_in *)addr_touse; 1.7336 + 1.7337 + /* validate the incoming port */ 1.7338 + if ((lsin->sin_port != 0) && 1.7339 + (lsin->sin_port != inp->sctp_lport)) { 1.7340 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7341 + *error = EINVAL; 1.7342 + return; 1.7343 + } else { 1.7344 + /* user specified 0 port, set it to existing port */ 1.7345 + lsin->sin_port = inp->sctp_lport; 1.7346 + } 1.7347 + 1.7348 + lep = sctp_pcb_findep(addr_touse, 1, 0, vrf_id); 1.7349 + if (lep != NULL) { 1.7350 + /* 1.7351 + * We must decrement the refcount 1.7352 + * since we have the ep already and 1.7353 + * are binding. No remove going on 1.7354 + * here. 1.7355 + */ 1.7356 + SCTP_INP_DECR_REF(lep); 1.7357 + } 1.7358 + if (lep == inp) { 1.7359 + /* already bound to it.. ok */ 1.7360 + return; 1.7361 + } else if (lep == NULL) { 1.7362 + ((struct sockaddr_in *)addr_touse)->sin_port = 0; 1.7363 + *error = sctp_addr_mgmt_ep_sa(inp, addr_touse, 1.7364 + SCTP_ADD_IP_ADDRESS, 1.7365 + vrf_id, NULL); 1.7366 + } else { 1.7367 + *error = EADDRINUSE; 1.7368 + } 1.7369 + if (*error) 1.7370 + return; 1.7371 + } else { 1.7372 + /* 1.7373 + * FIX: decide whether we allow assoc based 1.7374 + * bindx 1.7375 + */ 1.7376 + } 1.7377 +} 1.7378 + 1.7379 +/* 1.7380 + * sctp_bindx(DELETE) for one address. 1.7381 + * assumes all arguments are valid/checked by caller. 1.7382 + */ 1.7383 +void 1.7384 +sctp_bindx_delete_address(struct sctp_inpcb *inp, 1.7385 + struct sockaddr *sa, sctp_assoc_t assoc_id, 1.7386 + uint32_t vrf_id, int *error) 1.7387 +{ 1.7388 + struct sockaddr *addr_touse; 1.7389 +#ifdef INET6 1.7390 + struct sockaddr_in sin; 1.7391 +#endif 1.7392 +#ifdef SCTP_MVRF 1.7393 + int i, fnd = 0; 1.7394 +#endif 1.7395 + 1.7396 + /* see if we're bound all already! */ 1.7397 + if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 1.7398 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7399 + *error = EINVAL; 1.7400 + return; 1.7401 + } 1.7402 +#ifdef SCTP_MVRF 1.7403 + /* Is the VRF one we have */ 1.7404 + for (i = 0; i < inp->num_vrfs; i++) { 1.7405 + if (vrf_id == inp->m_vrf_ids[i]) { 1.7406 + fnd = 1; 1.7407 + break; 1.7408 + } 1.7409 + } 1.7410 + if (!fnd) { 1.7411 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7412 + *error = EINVAL; 1.7413 + return; 1.7414 + } 1.7415 +#endif 1.7416 + addr_touse = sa; 1.7417 +#ifdef INET6 1.7418 + if (sa->sa_family == AF_INET6) { 1.7419 + struct sockaddr_in6 *sin6; 1.7420 +#ifdef HAVE_SA_LEN 1.7421 + if (sa->sa_len != sizeof(struct sockaddr_in6)) { 1.7422 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7423 + *error = EINVAL; 1.7424 + return; 1.7425 + } 1.7426 +#endif 1.7427 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 1.7428 + /* can only bind v6 on PF_INET6 sockets */ 1.7429 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7430 + *error = EINVAL; 1.7431 + return; 1.7432 + } 1.7433 + sin6 = (struct sockaddr_in6 *)addr_touse; 1.7434 + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 1.7435 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1.7436 + SCTP_IPV6_V6ONLY(inp)) { 1.7437 + /* can't bind mapped-v4 on PF_INET sockets */ 1.7438 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7439 + *error = EINVAL; 1.7440 + return; 1.7441 + } 1.7442 + in6_sin6_2_sin(&sin, sin6); 1.7443 + addr_touse = (struct sockaddr *)&sin; 1.7444 + } 1.7445 + } 1.7446 +#endif 1.7447 +#ifdef INET 1.7448 + if (sa->sa_family == AF_INET) { 1.7449 +#ifdef HAVE_SA_LEN 1.7450 + if (sa->sa_len != sizeof(struct sockaddr_in)) { 1.7451 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7452 + *error = EINVAL; 1.7453 + return; 1.7454 + } 1.7455 +#endif 1.7456 + if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) && 1.7457 + SCTP_IPV6_V6ONLY(inp)) { 1.7458 + /* can't bind v4 on PF_INET sockets */ 1.7459 + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL); 1.7460 + *error = EINVAL; 1.7461 + return; 1.7462 + } 1.7463 + } 1.7464 +#endif 1.7465 + /* 1.7466 + * No lock required mgmt_ep_sa does its own locking. 1.7467 + * If the FIX: below is ever changed we may need to 1.7468 + * lock before calling association level binding. 1.7469 + */ 1.7470 + if (assoc_id == 0) { 1.7471 + /* delete the address */ 1.7472 + *error = sctp_addr_mgmt_ep_sa(inp, addr_touse, 1.7473 + SCTP_DEL_IP_ADDRESS, 1.7474 + vrf_id, NULL); 1.7475 + } else { 1.7476 + /* 1.7477 + * FIX: decide whether we allow assoc based 1.7478 + * bindx 1.7479 + */ 1.7480 + } 1.7481 +} 1.7482 + 1.7483 +/* 1.7484 + * returns the valid local address count for an assoc, taking into account 1.7485 + * all scoping rules 1.7486 + */ 1.7487 +int 1.7488 +sctp_local_addr_count(struct sctp_tcb *stcb) 1.7489 +{ 1.7490 + int loopback_scope; 1.7491 +#if defined(INET) 1.7492 + int ipv4_local_scope, ipv4_addr_legal; 1.7493 +#endif 1.7494 +#if defined (INET6) 1.7495 + int local_scope, site_scope, ipv6_addr_legal; 1.7496 +#endif 1.7497 +#if defined(__Userspace__) 1.7498 + int conn_addr_legal; 1.7499 +#endif 1.7500 + struct sctp_vrf *vrf; 1.7501 + struct sctp_ifn *sctp_ifn; 1.7502 + struct sctp_ifa *sctp_ifa; 1.7503 + int count = 0; 1.7504 + 1.7505 + /* Turn on all the appropriate scopes */ 1.7506 + loopback_scope = stcb->asoc.scope.loopback_scope; 1.7507 +#if defined(INET) 1.7508 + ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope; 1.7509 + ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal; 1.7510 +#endif 1.7511 +#if defined(INET6) 1.7512 + local_scope = stcb->asoc.scope.local_scope; 1.7513 + site_scope = stcb->asoc.scope.site_scope; 1.7514 + ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal; 1.7515 +#endif 1.7516 +#if defined(__Userspace__) 1.7517 + conn_addr_legal = stcb->asoc.scope.conn_addr_legal; 1.7518 +#endif 1.7519 + SCTP_IPI_ADDR_RLOCK(); 1.7520 + vrf = sctp_find_vrf(stcb->asoc.vrf_id); 1.7521 + if (vrf == NULL) { 1.7522 + /* no vrf, no addresses */ 1.7523 + SCTP_IPI_ADDR_RUNLOCK(); 1.7524 + return (0); 1.7525 + } 1.7526 + 1.7527 + if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 1.7528 + /* 1.7529 + * bound all case: go through all ifns on the vrf 1.7530 + */ 1.7531 + LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { 1.7532 + if ((loopback_scope == 0) && 1.7533 + SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { 1.7534 + continue; 1.7535 + } 1.7536 + LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { 1.7537 + if (sctp_is_addr_restricted(stcb, sctp_ifa)) 1.7538 + continue; 1.7539 + switch (sctp_ifa->address.sa.sa_family) { 1.7540 +#ifdef INET 1.7541 + case AF_INET: 1.7542 + if (ipv4_addr_legal) { 1.7543 + struct sockaddr_in *sin; 1.7544 + 1.7545 + sin = (struct sockaddr_in *)&sctp_ifa->address.sa; 1.7546 + if (sin->sin_addr.s_addr == 0) { 1.7547 + /* skip unspecified addrs */ 1.7548 + continue; 1.7549 + } 1.7550 + if ((ipv4_local_scope == 0) && 1.7551 + (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) { 1.7552 + continue; 1.7553 + } 1.7554 + /* count this one */ 1.7555 + count++; 1.7556 + } else { 1.7557 + continue; 1.7558 + } 1.7559 + break; 1.7560 +#endif 1.7561 +#ifdef INET6 1.7562 + case AF_INET6: 1.7563 + if (ipv6_addr_legal) { 1.7564 + struct sockaddr_in6 *sin6; 1.7565 + 1.7566 +#if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME) 1.7567 + struct sockaddr_in6 lsa6; 1.7568 +#endif 1.7569 + sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa; 1.7570 + if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1.7571 + continue; 1.7572 + } 1.7573 + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { 1.7574 + if (local_scope == 0) 1.7575 + continue; 1.7576 +#if defined(SCTP_EMBEDDED_V6_SCOPE) 1.7577 + if (sin6->sin6_scope_id == 0) { 1.7578 +#ifdef SCTP_KAME 1.7579 + if (sa6_recoverscope(sin6) != 0) 1.7580 + /* 1.7581 + * bad link 1.7582 + * local 1.7583 + * address 1.7584 + */ 1.7585 + continue; 1.7586 +#else 1.7587 + lsa6 = *sin6; 1.7588 + if (in6_recoverscope(&lsa6, 1.7589 + &lsa6.sin6_addr, 1.7590 + NULL)) 1.7591 + /* 1.7592 + * bad link 1.7593 + * local 1.7594 + * address 1.7595 + */ 1.7596 + continue; 1.7597 + sin6 = &lsa6; 1.7598 +#endif /* SCTP_KAME */ 1.7599 + } 1.7600 +#endif /* SCTP_EMBEDDED_V6_SCOPE */ 1.7601 + } 1.7602 + if ((site_scope == 0) && 1.7603 + (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) { 1.7604 + continue; 1.7605 + } 1.7606 + /* count this one */ 1.7607 + count++; 1.7608 + } 1.7609 + break; 1.7610 +#endif 1.7611 +#if defined(__Userspace__) 1.7612 + case AF_CONN: 1.7613 + if (conn_addr_legal) { 1.7614 + count++; 1.7615 + } 1.7616 + break; 1.7617 +#endif 1.7618 + default: 1.7619 + /* TSNH */ 1.7620 + break; 1.7621 + } 1.7622 + } 1.7623 + } 1.7624 + } else { 1.7625 + /* 1.7626 + * subset bound case 1.7627 + */ 1.7628 + struct sctp_laddr *laddr; 1.7629 + LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, 1.7630 + sctp_nxt_addr) { 1.7631 + if (sctp_is_addr_restricted(stcb, laddr->ifa)) { 1.7632 + continue; 1.7633 + } 1.7634 + /* count this one */ 1.7635 + count++; 1.7636 + } 1.7637 + } 1.7638 + SCTP_IPI_ADDR_RUNLOCK(); 1.7639 + return (count); 1.7640 +} 1.7641 + 1.7642 +#if defined(SCTP_LOCAL_TRACE_BUF) 1.7643 + 1.7644 +void 1.7645 +sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f) 1.7646 +{ 1.7647 + uint32_t saveindex, newindex; 1.7648 + 1.7649 +#if defined(__Windows__) 1.7650 + if (SCTP_BASE_SYSCTL(sctp_log) == NULL) { 1.7651 + return; 1.7652 + } 1.7653 + do { 1.7654 + saveindex = SCTP_BASE_SYSCTL(sctp_log)->index; 1.7655 + if (saveindex >= SCTP_MAX_LOGGING_SIZE) { 1.7656 + newindex = 1; 1.7657 + } else { 1.7658 + newindex = saveindex + 1; 1.7659 + } 1.7660 + } while (atomic_cmpset_int(&SCTP_BASE_SYSCTL(sctp_log)->index, saveindex, newindex) == 0); 1.7661 + if (saveindex >= SCTP_MAX_LOGGING_SIZE) { 1.7662 + saveindex = 0; 1.7663 + } 1.7664 + SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].timestamp = SCTP_GET_CYCLECOUNT; 1.7665 + SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].subsys = subsys; 1.7666 + SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[0] = a; 1.7667 + SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[1] = b; 1.7668 + SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[2] = c; 1.7669 + SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[3] = d; 1.7670 + SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[4] = e; 1.7671 + SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[5] = f; 1.7672 +#else 1.7673 + do { 1.7674 + saveindex = SCTP_BASE_SYSCTL(sctp_log).index; 1.7675 + if (saveindex >= SCTP_MAX_LOGGING_SIZE) { 1.7676 + newindex = 1; 1.7677 + } else { 1.7678 + newindex = saveindex + 1; 1.7679 + } 1.7680 + } while (atomic_cmpset_int(&SCTP_BASE_SYSCTL(sctp_log).index, saveindex, newindex) == 0); 1.7681 + if (saveindex >= SCTP_MAX_LOGGING_SIZE) { 1.7682 + saveindex = 0; 1.7683 + } 1.7684 + SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].timestamp = SCTP_GET_CYCLECOUNT; 1.7685 + SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].subsys = subsys; 1.7686 + SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[0] = a; 1.7687 + SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[1] = b; 1.7688 + SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[2] = c; 1.7689 + SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[3] = d; 1.7690 + SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[4] = e; 1.7691 + SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[5] = f; 1.7692 +#endif 1.7693 +} 1.7694 + 1.7695 +#endif 1.7696 +#if defined(__FreeBSD__) 1.7697 +#if __FreeBSD_version >= 800044 1.7698 +static void 1.7699 +sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored) 1.7700 +{ 1.7701 + struct ip *iph; 1.7702 +#ifdef INET6 1.7703 + struct ip6_hdr *ip6; 1.7704 +#endif 1.7705 + struct mbuf *sp, *last; 1.7706 + struct udphdr *uhdr; 1.7707 + uint16_t port; 1.7708 + 1.7709 + if ((m->m_flags & M_PKTHDR) == 0) { 1.7710 + /* Can't handle one that is not a pkt hdr */ 1.7711 + goto out; 1.7712 + } 1.7713 + /* Pull the src port */ 1.7714 + iph = mtod(m, struct ip *); 1.7715 + uhdr = (struct udphdr *)((caddr_t)iph + off); 1.7716 + port = uhdr->uh_sport; 1.7717 + /* Split out the mbuf chain. Leave the 1.7718 + * IP header in m, place the 1.7719 + * rest in the sp. 1.7720 + */ 1.7721 + sp = m_split(m, off, M_NOWAIT); 1.7722 + if (sp == NULL) { 1.7723 + /* Gak, drop packet, we can't do a split */ 1.7724 + goto out; 1.7725 + } 1.7726 + if (sp->m_pkthdr.len < sizeof(struct udphdr) + sizeof(struct sctphdr)) { 1.7727 + /* Gak, packet can't have an SCTP header in it - too small */ 1.7728 + m_freem(sp); 1.7729 + goto out; 1.7730 + } 1.7731 + /* Now pull up the UDP header and SCTP header together */ 1.7732 + sp = m_pullup(sp, sizeof(struct udphdr) + sizeof(struct sctphdr)); 1.7733 + if (sp == NULL) { 1.7734 + /* Gak pullup failed */ 1.7735 + goto out; 1.7736 + } 1.7737 + /* Trim out the UDP header */ 1.7738 + m_adj(sp, sizeof(struct udphdr)); 1.7739 + 1.7740 + /* Now reconstruct the mbuf chain */ 1.7741 + for (last = m; last->m_next; last = last->m_next); 1.7742 + last->m_next = sp; 1.7743 + m->m_pkthdr.len += sp->m_pkthdr.len; 1.7744 + iph = mtod(m, struct ip *); 1.7745 + switch (iph->ip_v) { 1.7746 +#ifdef INET 1.7747 + case IPVERSION: 1.7748 +#if __FreeBSD_version >= 1000000 1.7749 + iph->ip_len = htons(ntohs(iph->ip_len) - sizeof(struct udphdr)); 1.7750 +#else 1.7751 + iph->ip_len -= sizeof(struct udphdr); 1.7752 +#endif 1.7753 + sctp_input_with_port(m, off, port); 1.7754 + break; 1.7755 +#endif 1.7756 +#ifdef INET6 1.7757 + case IPV6_VERSION >> 4: 1.7758 + ip6 = mtod(m, struct ip6_hdr *); 1.7759 + ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - sizeof(struct udphdr)); 1.7760 + sctp6_input_with_port(&m, &off, port); 1.7761 + break; 1.7762 +#endif 1.7763 + default: 1.7764 + goto out; 1.7765 + break; 1.7766 + } 1.7767 + return; 1.7768 + out: 1.7769 + m_freem(m); 1.7770 +} 1.7771 +#endif 1.7772 + 1.7773 +void 1.7774 +sctp_over_udp_stop(void) 1.7775 +{ 1.7776 + /* 1.7777 + * This function assumes sysctl caller holds sctp_sysctl_info_lock() for writting! 1.7778 + */ 1.7779 +#ifdef INET 1.7780 + if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) { 1.7781 + soclose(SCTP_BASE_INFO(udp4_tun_socket)); 1.7782 + SCTP_BASE_INFO(udp4_tun_socket) = NULL; 1.7783 + } 1.7784 +#endif 1.7785 +#ifdef INET6 1.7786 + if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) { 1.7787 + soclose(SCTP_BASE_INFO(udp6_tun_socket)); 1.7788 + SCTP_BASE_INFO(udp6_tun_socket) = NULL; 1.7789 + } 1.7790 +#endif 1.7791 +} 1.7792 + 1.7793 +int 1.7794 +sctp_over_udp_start(void) 1.7795 +{ 1.7796 +#if __FreeBSD_version >= 800044 1.7797 + uint16_t port; 1.7798 + int ret; 1.7799 +#ifdef INET 1.7800 + struct sockaddr_in sin; 1.7801 +#endif 1.7802 +#ifdef INET6 1.7803 + struct sockaddr_in6 sin6; 1.7804 +#endif 1.7805 + /* 1.7806 + * This function assumes sysctl caller holds sctp_sysctl_info_lock() for writting! 1.7807 + */ 1.7808 + port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port); 1.7809 + if (ntohs(port) == 0) { 1.7810 + /* Must have a port set */ 1.7811 + return (EINVAL); 1.7812 + } 1.7813 +#ifdef INET 1.7814 + if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) { 1.7815 + /* Already running -- must stop first */ 1.7816 + return (EALREADY); 1.7817 + } 1.7818 +#endif 1.7819 +#ifdef INET6 1.7820 + if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) { 1.7821 + /* Already running -- must stop first */ 1.7822 + return (EALREADY); 1.7823 + } 1.7824 +#endif 1.7825 +#ifdef INET 1.7826 + if ((ret = socreate(PF_INET, &SCTP_BASE_INFO(udp4_tun_socket), 1.7827 + SOCK_DGRAM, IPPROTO_UDP, 1.7828 + curthread->td_ucred, curthread))) { 1.7829 + sctp_over_udp_stop(); 1.7830 + return (ret); 1.7831 + } 1.7832 + /* Call the special UDP hook. */ 1.7833 + if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket), 1.7834 + sctp_recv_udp_tunneled_packet))) { 1.7835 + sctp_over_udp_stop(); 1.7836 + return (ret); 1.7837 + } 1.7838 + /* Ok, we have a socket, bind it to the port. */ 1.7839 + memset(&sin, 0, sizeof(struct sockaddr_in)); 1.7840 + sin.sin_len = sizeof(struct sockaddr_in); 1.7841 + sin.sin_family = AF_INET; 1.7842 + sin.sin_port = htons(port); 1.7843 + if ((ret = sobind(SCTP_BASE_INFO(udp4_tun_socket), 1.7844 + (struct sockaddr *)&sin, curthread))) { 1.7845 + sctp_over_udp_stop(); 1.7846 + return (ret); 1.7847 + } 1.7848 +#endif 1.7849 +#ifdef INET6 1.7850 + if ((ret = socreate(PF_INET6, &SCTP_BASE_INFO(udp6_tun_socket), 1.7851 + SOCK_DGRAM, IPPROTO_UDP, 1.7852 + curthread->td_ucred, curthread))) { 1.7853 + sctp_over_udp_stop(); 1.7854 + return (ret); 1.7855 + } 1.7856 + /* Call the special UDP hook. */ 1.7857 + if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket), 1.7858 + sctp_recv_udp_tunneled_packet))) { 1.7859 + sctp_over_udp_stop(); 1.7860 + return (ret); 1.7861 + } 1.7862 + /* Ok, we have a socket, bind it to the port. */ 1.7863 + memset(&sin6, 0, sizeof(struct sockaddr_in6)); 1.7864 + sin6.sin6_len = sizeof(struct sockaddr_in6); 1.7865 + sin6.sin6_family = AF_INET6; 1.7866 + sin6.sin6_port = htons(port); 1.7867 + if ((ret = sobind(SCTP_BASE_INFO(udp6_tun_socket), 1.7868 + (struct sockaddr *)&sin6, curthread))) { 1.7869 + sctp_over_udp_stop(); 1.7870 + return (ret); 1.7871 + } 1.7872 +#endif 1.7873 + return (0); 1.7874 +#else 1.7875 + return (ENOTSUP); 1.7876 +#endif 1.7877 +} 1.7878 +#endif