netwerk/sctp/src/netinet/sctputil.c

changeset 0
6474c204b198
     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

mercurial