18c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
28c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
3ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
58c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
68c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Redistribution and use in source and binary forms, with or without
78c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * modification, are permitted provided that the following conditions are met:
88c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
98c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a) Redistributions of source code must retain the above copyright notice,
100ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    this list of conditions and the following disclaimer.
118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * b) Redistributions in binary form must reproduce the above copyright
138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    notice, this list of conditions and the following disclaimer in
140ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    the documentation and/or other materials provided with the distribution.
158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * c) Neither the name of Cisco Systems, Inc. nor the names of its
178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    contributors may be used to endorse or promote products derived
188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    from this software without specific prior written permission.
198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE POSSIBILITY OF SUCH DAMAGE.
318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__
348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/cdefs.h>
35bfb1bf7e665a02b48026482bf33d05c83dfad73bt__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 271221 2014-09-07 09:06:26Z tuexen $");
368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_os.h>
398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_pcb.h>
408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h>
418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h>
428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_sysctl.h>
438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
44b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#if defined(__Userspace__) || defined(__FreeBSD__)
458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet6/sctp6_var.h>
468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_header.h>
498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_output.h>
508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_uio.h>
518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_timer.h>
528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_auth.h>
548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_asconf.h>
558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_bsd_addr.h>
567ec5951ec04f35070419877f6b015541f6b9728dtuexen#if defined(__Userspace__)
57a804fa53b20093a975fc501f62a08313110328cetuexen#include <netinet/sctp_constants.h>
587ec5951ec04f35070419877f6b015541f6b9728dtuexen#endif
59b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#if defined(__FreeBSD__)
60b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#include <netinet/udp.h>
61b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#include <netinet/udp_var.h>
62b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#include <sys/proc.h>
63b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif
648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define APPLE_FILE_NO 8
678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
69000a5bac556b28e74e4e98c540f66b1743e9312dtuexen#if defined(__Windows__)
708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(SCTP_LOCAL_TRACE_BUF)
718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include "eventrace_netinet.h"
728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include "sctputil.tmh" /* this is the file that will be auto generated */
738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef KTR_SCTP
768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define KTR_SCTP KTR_SUBSYS
778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenextern struct sctp_cc_functions sctp_cc_functions[];
818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenextern struct sctp_ss_functions sctp_ss_functions[];
828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
84c95692c15a6ca05efcd306c21fda119862cd66e0tsctp_sblog(struct sockbuf *sb, struct sctp_tcb *stcb, int from, int incr)
858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
86c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
880ac02f34d6041cd0018437596a5a9a94685e6919tuexen
898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.sb.stcb = stcb;
908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.sb.so_sbcc = sb->sb_cc;
918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb)
928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.sb.stcb_sbcc = stcb->asoc.sb_cc;
938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.sb.stcb_sbcc = 0;
958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.sb.incr = incr;
968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_SB,
988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
1008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
1018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
1028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
103c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
1048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
1078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc)
1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
109c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
1108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
1110ac02f34d6041cd0018437596a5a9a94685e6919tuexen
1128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.close.inp = (void *)inp;
1138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.close.sctp_flags = inp->sctp_flags;
1148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
1158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.close.stcb = (void *)stcb;
1168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.close.state = (uint16_t)stcb->asoc.state;
1178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.close.stcb = 0;
1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.close.state = 0;
1208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.close.loc = loc;
1228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
1238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_CLOSE,
1248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     0,
1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
1278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
1288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
129c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
1308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenrto_logging(struct sctp_nets *net, int from)
1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
135c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
1370ac02f34d6041cd0018437596a5a9a94685e6919tuexen
1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(&sctp_clog, 0, sizeof(sctp_clog));
1398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.rto.net = (void *) net;
1408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.rto.rtt = net->rtt / 1000;
1418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
1428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_RTT,
1438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
1448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
1458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
1468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
1478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
148c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
1498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
1528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_strm_del_alt(struct sctp_tcb *stcb, uint32_t tsn, uint16_t sseq, uint16_t stream, int from)
1538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
154c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
1558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
1560ac02f34d6041cd0018437596a5a9a94685e6919tuexen
1578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.strlog.stcb = stcb;
1588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.strlog.n_tsn = tsn;
1598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.strlog.n_sseq = sseq;
1608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.strlog.e_tsn = 0;
1618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.strlog.e_sseq = 0;
1628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.strlog.strm = stream;
1638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
1648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_STRM,
1658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
1668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
1678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
1688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
1698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
170c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
1718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
1748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_nagle_event(struct sctp_tcb *stcb, int action)
1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
176c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
1778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
1780ac02f34d6041cd0018437596a5a9a94685e6919tuexen
1798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.nagle.stcb = (void *)stcb;
1808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.nagle.total_flight = stcb->asoc.total_flight;
1818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.nagle.total_in_queue = stcb->asoc.total_output_queue_size;
1828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.nagle.count_in_queue = stcb->asoc.chunks_on_out_queue;
1838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.nagle.count_in_flight = stcb->asoc.total_flight_count;
1848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_NAGLE,
1868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     action,
1878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
1888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
1898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
1908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
191c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
1928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
1958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_sack(uint32_t old_cumack, uint32_t cumack, uint32_t tsn, uint16_t gaps, uint16_t dups, int from)
1968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
197c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
1988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
1990ac02f34d6041cd0018437596a5a9a94685e6919tuexen
2008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.sack.cumack = cumack;
2018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.sack.oldcumack = old_cumack;
2028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.sack.tsn = tsn;
2038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.sack.numGaps = gaps;
2048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.sack.numDups = dups;
2058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
2068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_SACK,
2078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
2088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
2098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
2108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
2118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
212c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
2138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
2168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from)
2178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
218c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
2198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
2200ac02f34d6041cd0018437596a5a9a94685e6919tuexen
2218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(&sctp_clog, 0, sizeof(sctp_clog));
2228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.map.base = map;
2238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.map.cum = cum;
2248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.map.high = high;
2258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
2268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_MAP,
2278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
2288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
2298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
2308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
2318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
232c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
2338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
236c95692c15a6ca05efcd306c21fda119862cd66e0tsctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn, int from)
2378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
238c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
2398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
2400ac02f34d6041cd0018437596a5a9a94685e6919tuexen
2418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(&sctp_clog, 0, sizeof(sctp_clog));
2428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.fr.largest_tsn = biggest_tsn;
2438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.fr.largest_new_tsn = biggest_new_tsn;
2448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.fr.tsn = tsn;
2458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
2468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_FR,
2478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
2488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
2498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
2508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
2518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
252c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
2538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
2568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_mb(struct mbuf *m, int from)
2578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
258c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
2598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
2600ac02f34d6041cd0018437596a5a9a94685e6919tuexen
2618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.mb.mp = m;
2628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.mb.mbuf_flags = (uint8_t)(SCTP_BUF_GET_FLAGS(m));
2638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.mb.size = (uint16_t)(SCTP_BUF_LEN(m));
2648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.mb.data = SCTP_BUF_AT(m, 0);
2658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BUF_IS_EXTENDED(m)) {
2668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.mb.ext = SCTP_BUF_EXTEND_BASE(m);
2678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
2688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* APPLE does not use a ref_cnt, but a forward/backward ref queue */
2698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.mb.refcnt = (uint8_t)(SCTP_BUF_EXTEND_REFCNT(m));
2718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
2720ac02f34d6041cd0018437596a5a9a94685e6919tuexen	} else {
2738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.mb.ext = 0;
2748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.mb.refcnt = 0;
2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
2778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_MBUF,
2788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
2798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
2808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
2818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
2828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
283c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
2848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
287c95692c15a6ca05efcd306c21fda119862cd66e0tsctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_read *poschk, int from)
2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
289c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
2910ac02f34d6041cd0018437596a5a9a94685e6919tuexen
2928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
2938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("Gak log of NULL?\n");
2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.strlog.stcb = control->stcb;
2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.strlog.n_tsn = control->sinfo_tsn;
2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.strlog.n_sseq = control->sinfo_ssn;
2998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.strlog.strm = control->sinfo_stream;
3008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (poschk != NULL) {
3018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.strlog.e_tsn = poschk->sinfo_tsn;
3028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.strlog.e_sseq = poschk->sinfo_ssn;
3038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
3048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.strlog.e_tsn = 0;
3058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.strlog.e_sseq = 0;
3068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
3088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_STRM,
3098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
3108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
3128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
3138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
314c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
3158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
3188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net, int augment, uint8_t from)
3198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
320c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
3218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
3220ac02f34d6041cd0018437596a5a9a94685e6919tuexen
3238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.cwnd.net = net;
3248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.send_queue_cnt > 255)
3258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.cnt_in_send = 255;
3268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
3278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt;
3288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.stream_queue_cnt > 255)
3298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.cnt_in_str = 255;
3308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
3318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt;
3328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net) {
3348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.cwnd_new_value = net->cwnd;
3358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.inflight = net->flight_size;
3368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.pseudo_cumack = net->pseudo_cumack;
3378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.meets_pseudo_cumack = net->new_pseudo_cumack;
3388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.need_new_pseudo_cumack = net->find_pseudo_cumack;
3398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_CWNDLOG_PRESEND == from) {
3418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.meets_pseudo_cumack = stcb->asoc.peers_rwnd;
3428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.cwnd.cwnd_augment = augment;
3448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
3458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_CWND,
3468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
3478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
3488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
3498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
3508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
351c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
3528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __APPLE__
3558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
3568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from)
3578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
358c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
3598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
3600ac02f34d6041cd0018437596a5a9a94685e6919tuexen
3618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(&sctp_clog, 0, sizeof(sctp_clog));
3628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp) {
363c95692c15a6ca05efcd306c21fda119862cd66e0t		sctp_clog.x.lock.sock = (void *) inp->sctp_socket;
3648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
366c95692c15a6ca05efcd306c21fda119862cd66e0t		sctp_clog.x.lock.sock = (void *) NULL;
3678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.lock.inp = (void *) inp;
3698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version >= 503000) || (defined(__APPLE__))
3708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
3718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.tcb_lock = mtx_owned(&stcb->tcb_mtx);
3728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
3738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.tcb_lock = SCTP_LOCK_UNKNOWN;
3748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp) {
3768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.inp_lock = mtx_owned(&inp->inp_mtx);
3778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.create_lock = mtx_owned(&inp->inp_create_mtx);
3788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
3798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.inp_lock = SCTP_LOCK_UNKNOWN;
3808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.create_lock = SCTP_LOCK_UNKNOWN;
3818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version <= 602000)
3838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.lock.info_lock = mtx_owned(&SCTP_BASE_INFO(ipi_ep_mtx));
3848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
3858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.lock.info_lock = rw_wowned(&SCTP_BASE_INFO(ipi_ep_mtx));
3868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp && (inp->sctp_socket)) {
3888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.sock_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx));
3898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.sockrcvbuf_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx));
3908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.socksndbuf_lock = mtx_owned(&(inp->sctp_socket->so_snd.sb_mtx));
3918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
3928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.sock_lock = SCTP_LOCK_UNKNOWN;
3938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.sockrcvbuf_lock = SCTP_LOCK_UNKNOWN;
3948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.lock.socksndbuf_lock = SCTP_LOCK_UNKNOWN;
3958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
3988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_LOCK_EVENT,
3998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
4008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
4028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
4038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
404c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
4058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
4098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *net, int error, int burst, uint8_t from)
4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
411c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
4130ac02f34d6041cd0018437596a5a9a94685e6919tuexen
4148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(&sctp_clog, 0, sizeof(sctp_clog));
4158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.cwnd.net = net;
4168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.cwnd.cwnd_new_value = error;
4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.cwnd.inflight = net->flight_size;
4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.cwnd.cwnd_augment = burst;
4198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.send_queue_cnt > 255)
4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.cnt_in_send = 255;
4218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
4228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt;
4238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.stream_queue_cnt > 255)
4248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.cnt_in_str = 255;
4258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt;
4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
4288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_MAXBURST,
4298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
4308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
4318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
4328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
4338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
434c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
4358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
4388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_rwnd(uint8_t from, uint32_t peers_rwnd, uint32_t snd_size, uint32_t overhead)
4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
440c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
4418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
4420ac02f34d6041cd0018437596a5a9a94685e6919tuexen
4438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.rwnd.rwnd = peers_rwnd;
4448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.rwnd.send_size = snd_size;
4458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.rwnd.overhead = overhead;
4468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.rwnd.new_rwnd = 0;
4478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
4488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_RWND,
4498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
4508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
4518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
454c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
4568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
4588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_rwnd_set(uint8_t from, uint32_t peers_rwnd, uint32_t flight_size, uint32_t overhead, uint32_t a_rwndval)
4598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
460c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
4618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
4620ac02f34d6041cd0018437596a5a9a94685e6919tuexen
4638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.rwnd.rwnd = peers_rwnd;
4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.rwnd.send_size = flight_size;
4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.rwnd.overhead = overhead;
4668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.rwnd.new_rwnd = a_rwndval;
4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
4688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_RWND,
4698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
4718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
4728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
4738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
474c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
4758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
4788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mbcnt_q, uint32_t mbcnt)
4798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
480c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
4818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
4820ac02f34d6041cd0018437596a5a9a94685e6919tuexen
4838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.mbcnt.total_queue_size = total_oq;
4848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.mbcnt.size_change = book;
4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.mbcnt.total_queue_mb_size = total_mbcnt_q;
4868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.mbcnt.mbcnt_change = mbcnt;
4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
4888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_MBCNT,
4898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
4908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
4918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
4928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
4938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
494c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
4958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
4968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
4988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
4998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
500c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
5018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
5028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_MISC_EVENT,
5038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
5048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     a, b, c, d);
505c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
5068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
5090ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from)
5108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
511c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
5128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
5130ac02f34d6041cd0018437596a5a9a94685e6919tuexen
5148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.wake.stcb = (void *)stcb;
5158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.wake.wake_cnt = wake_cnt;
5168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.wake.flight = stcb->asoc.total_flight_count;
5178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.wake.send_q = stcb->asoc.send_queue_cnt;
5188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.wake.sent_q = stcb->asoc.sent_queue_cnt;
5198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.stream_queue_cnt < 0xff)
5218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.wake.stream_qcnt = (uint8_t) stcb->asoc.stream_queue_cnt;
5228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
5238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.wake.stream_qcnt = 0xff;
5248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.chunks_on_out_queue < 0xff)
5268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.wake.chunks_on_oque = (uint8_t) stcb->asoc.chunks_on_out_queue;
5278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else
5288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.wake.chunks_on_oque = 0xff;
5298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.wake.sctpflags = 0;
5318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* set in the defered mode stuff */
5328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE)
5338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.wake.sctpflags |= 1;
5348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT)
5358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.wake.sctpflags |= 2;
5368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT)
5378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.wake.sctpflags |= 4;
538c95692c15a6ca05efcd306c21fda119862cd66e0t	/* what about the sb */
5398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_socket) {
5408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct socket *so = stcb->sctp_socket;
5418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.wake.sbflags = (uint8_t)((so->so_snd.sb_flags & 0x00ff));
5438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
5448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_clog.x.wake.sbflags = 0xff;
5458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
5478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_WAKE,
5488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
5498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
5508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
5518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
5528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
553c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
5548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
5570ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen)
5588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
559c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) || defined(SCTP_LOCAL_TRACE_BUF)
5608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_cwnd_log sctp_clog;
5610ac02f34d6041cd0018437596a5a9a94685e6919tuexen
5628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.blk.onsb = asoc->total_output_queue_size;
5638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.blk.send_sent_qcnt = (uint16_t) (asoc->send_queue_cnt + asoc->sent_queue_cnt);
5648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.blk.peer_rwnd = asoc->peers_rwnd;
5658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt;
5668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue;
5678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.blk.flight_size = (uint16_t) (asoc->total_flight/1024);
5688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_clog.x.blk.sndlen = sendlen;
5698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
5708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     SCTP_LOG_EVENT_BLOCK,
5718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     from,
5728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log1,
5738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log2,
5748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log3,
5758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_clog.x.misc.log4);
576c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
5778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
5800ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_fill_stat_log(void *optval SCTP_UNUSED, size_t *optsize SCTP_UNUSED)
5818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
5828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* May need to fix this if ktrdump does not work */
5838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
5848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
5878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint8_t sctp_audit_data[SCTP_AUDIT_SIZE][2];
5888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int sctp_audit_indx = 0;
5898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic
5918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
5928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_print_audit_report(void)
5938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
5948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
5958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int cnt;
5968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cnt = 0;
5988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = sctp_audit_indx; i < SCTP_AUDIT_SIZE; i++) {
5998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((sctp_audit_data[i][0] == 0xe0) &&
6008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (sctp_audit_data[i][1] == 0x01)) {
6018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cnt = 0;
6028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("\n");
6038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (sctp_audit_data[i][0] == 0xf0) {
6048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cnt = 0;
6058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("\n");
6068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if ((sctp_audit_data[i][0] == 0xc0) &&
6078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (sctp_audit_data[i][1] == 0x01)) {
6088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("\n");
6098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cnt = 0;
6108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0],
6128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (uint32_t) sctp_audit_data[i][1]);
6138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cnt++;
6148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((cnt % 14) == 0)
6158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("\n");
6168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < sctp_audit_indx; i++) {
6188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((sctp_audit_data[i][0] == 0xe0) &&
6198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (sctp_audit_data[i][1] == 0x01)) {
6208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cnt = 0;
6218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("\n");
6228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (sctp_audit_data[i][0] == 0xf0) {
6238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cnt = 0;
6248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("\n");
6258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if ((sctp_audit_data[i][0] == 0xc0) &&
6268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (sctp_audit_data[i][1] == 0x01)) {
6278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("\n");
6288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cnt = 0;
6298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0],
6318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (uint32_t) sctp_audit_data[i][1]);
6328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		cnt++;
6338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((cnt % 14) == 0)
6348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("\n");
6358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_PRINTF("\n");
6378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
6388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
6408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
6418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_nets *net)
6428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
6438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int resend_cnt, tot_out, rep, tot_book_cnt;
6448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *lnet;
6458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk;
6468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_audit_data[sctp_audit_indx][0] = 0xAA;
6488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_audit_data[sctp_audit_indx][1] = 0x000000ff & from;
6498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_audit_indx++;
6508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
6518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_indx = 0;
6528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL) {
6548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
6558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][1] = 0x01;
6568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_indx++;
6578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
6588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_audit_indx = 0;
6598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
6618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
6638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
6648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][1] = 0x02;
6658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_indx++;
6668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
6678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_audit_indx = 0;
6688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
6708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_audit_data[sctp_audit_indx][0] = 0xA1;
6728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_audit_data[sctp_audit_indx][1] =
6738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
6748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_audit_indx++;
6758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
6768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_indx = 0;
6778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	rep = 0;
6798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tot_book_cnt = 0;
6808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	resend_cnt = tot_out = 0;
6818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
6828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->sent == SCTP_DATAGRAM_RESEND) {
6838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			resend_cnt++;
6848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (chk->sent < SCTP_DATAGRAM_RESEND) {
6858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tot_out += chk->book_size;
6868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tot_book_cnt++;
6878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (resend_cnt != stcb->asoc.sent_queue_retran_cnt) {
6908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
6918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][1] = 0xA1;
6928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_indx++;
6938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
6948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_audit_indx = 0;
6958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("resend_cnt:%d asoc-tot:%d\n",
6978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    resend_cnt, stcb->asoc.sent_queue_retran_cnt);
6988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rep = 1;
6998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.sent_queue_retran_cnt = resend_cnt;
7008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][0] = 0xA2;
7018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][1] =
7028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
7038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_indx++;
7048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
7058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_audit_indx = 0;
7068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (tot_out != stcb->asoc.total_flight) {
7098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
7108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][1] = 0xA2;
7118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_indx++;
7128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
7138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_audit_indx = 0;
7148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rep = 1;
7168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("tot_flt:%d asoc_tot:%d\n", tot_out,
7178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (int)stcb->asoc.total_flight);
7188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.total_flight = tot_out;
7198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (tot_book_cnt != stcb->asoc.total_flight_count) {
7218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
7228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][1] = 0xA5;
7238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_indx++;
7248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
7258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_audit_indx = 0;
7268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rep = 1;
7288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("tot_flt_book:%d\n", tot_book_cnt);
7298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.total_flight_count = tot_book_cnt;
7318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tot_out = 0;
7338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
7348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tot_out += lnet->flight_size;
7358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (tot_out != stcb->asoc.total_flight) {
7378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
7388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_data[sctp_audit_indx][1] = 0xA3;
7398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_indx++;
7408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
7418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_audit_indx = 0;
7428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rep = 1;
7448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("real flight:%d net total was %d\n",
7458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    stcb->asoc.total_flight, tot_out);
7468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* now corrective action */
7478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
7488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tot_out = 0;
7508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
7518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((chk->whoTo == lnet) &&
7528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (chk->sent < SCTP_DATAGRAM_RESEND)) {
7538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					tot_out += chk->book_size;
7548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
7558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
7568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (lnet->flight_size != tot_out) {
7578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_PRINTF("net:%p flight was %d corrected to %d\n",
758ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t					    (void *)lnet, lnet->flight_size,
7598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    tot_out);
7608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				lnet->flight_size = tot_out;
7618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
7628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (rep) {
7658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_print_audit_report();
7668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
7688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
7708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_audit_log(uint8_t ev, uint8_t fd)
7718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_audit_data[sctp_audit_indx][0] = ev;
7748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_audit_data[sctp_audit_indx][1] = fd;
7758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_audit_indx++;
7768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
7778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_audit_indx = 0;
7788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
7808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
7848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_stop_timers_for_shutdown() should be called
7858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * when entering the SHUTDOWN_SENT or SHUTDOWN_ACK_SENT
7868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * state to make sure that all timers are stopped.
7878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
7888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
7898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_stop_timers_for_shutdown(struct sctp_tcb *stcb)
7908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
7928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
7938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
7958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
7978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
7988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
7998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
8008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
8018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
8028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
8038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer);
8048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
8088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a list of sizes based on typical mtu's, used only if next hop size not
8098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returned.
8108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
8118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t sctp_mtu_sizes[] = {
8128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	68,
8138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	296,
8148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	508,
8158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	512,
8168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	544,
8178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	576,
8188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	1006,
8198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	1492,
8208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	1500,
8218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	1536,
8228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	2002,
8238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	2048,
8248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	4352,
8258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	4464,
8268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	8166,
8278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	17914,
8288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	32000,
8298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	65535
8308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen};
8318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
8338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Return the largest MTU smaller than val. If there is no
8348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * entry, just return val.
8358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
8368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
8378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_get_prev_mtu(uint32_t val)
8388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t i;
8408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (val <= sctp_mtu_sizes[0]) {
8428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (val);
8438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 1; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) {
8458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (val <= sctp_mtu_sizes[i]) {
8468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
8478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
8488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (sctp_mtu_sizes[i - 1]);
8508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
8538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Return the smallest MTU larger than val. If there is no
8548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * entry, just return val.
8558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
8568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
8570ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_get_next_mtu(uint32_t val)
8588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* select another MTU that is just bigger than this one */
8608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t i;
8618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) {
8638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (val < sctp_mtu_sizes[i]) {
8648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (sctp_mtu_sizes[i]);
8658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
8668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (val);
8688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
8718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_fill_random_store(struct sctp_pcb *m)
8728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
8748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Here we use the MD5/SHA-1 to hash with our good randomNumbers and
8758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * our counter. The result becomes our good random numbers and we
8768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * then setup to give these out. Note that we do no locking to
8778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * protect this. This is ok, since if competing folks call this we
8788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * will get more gobbled gook in the random store which is what we
8798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * want. There is a danger that two guys will use the same random
8808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * numbers, but thats ok too since that is random as well :->
8818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
8828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m->store_at = 0;
8838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)sctp_hmac(SCTP_HMAC, (uint8_t *)m->random_numbers,
8848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sizeof(m->random_numbers), (uint8_t *)&m->random_counter,
8858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sizeof(m->random_counter), (uint8_t *)m->random_store);
8868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m->random_counter++;
8878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
8908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_select_initial_TSN(struct sctp_pcb *inp)
8918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
8938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * A true implementation should use random selection process to get
8948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * the initial stream sequence number, using RFC1750 as a good
8958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * guideline
8968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
8978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t x, *xp;
8988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t *p;
8998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int store_at, new_store;
9008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->initial_sequence_debug != 0) {
9028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t ret;
9038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ret = inp->initial_sequence_debug;
9058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp->initial_sequence_debug++;
9068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ret);
9078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen retry:
9098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	store_at = inp->store_at;
9108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_store = store_at + sizeof(uint32_t);
9118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_store >= (SCTP_SIGNATURE_SIZE-3)) {
9128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		new_store = 0;
9138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!atomic_cmpset_int(&inp->store_at, store_at, new_store)) {
9158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto retry;
9168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_store == 0) {
9188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Refill the random store */
9198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_fill_random_store(inp);
9208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	p = &inp->random_store[store_at];
9228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	xp = (uint32_t *)p;
9238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	x = *xp;
9248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (x);
9258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
9268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
9280ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int check)
9298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
9300ac02f34d6041cd0018437596a5a9a94685e6919tuexen	uint32_t x;
9318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct timeval now;
9328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9330ac02f34d6041cd0018437596a5a9a94685e6919tuexen	if (check) {
9340ac02f34d6041cd0018437596a5a9a94685e6919tuexen		(void)SCTP_GETTIME_TIMEVAL(&now);
9350ac02f34d6041cd0018437596a5a9a94685e6919tuexen	}
9360ac02f34d6041cd0018437596a5a9a94685e6919tuexen	for (;;) {
9378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		x = sctp_select_initial_TSN(&inp->sctp_ep);
9388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (x == 0) {
9398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* we never use 0 */
9408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
9418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
9420ac02f34d6041cd0018437596a5a9a94685e6919tuexen		if (!check || sctp_is_vtag_good(x, lport, rport, &now)) {
9430ac02f34d6041cd0018437596a5a9a94685e6919tuexen			break;
9448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
9458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (x);
9478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
9488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
9507988ea8f0c067cf3757e798b473b1ae4d34b6dfdtsctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
9518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen               uint32_t override_tag, uint32_t vrf_id)
9528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
9538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
9548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
9558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Anything set to zero is taken care of by the allocation routine's
9568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * bzero
9578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
9588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
9608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Up front select what scoping to apply on addresses I tell my peer
9618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Not sure what to do with these right now, we will need to come up
9628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * with a way to set them. We may need to pass them through from the
9638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * caller in the sctp_aloc_assoc() function.
9648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
9658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
96620d5d287bff2075897105f85287230d55bdfa420t#if defined(SCTP_DETAILED_STR_STATS)
96720d5d287bff2075897105f85287230d55bdfa420t	int j;
96820d5d287bff2075897105f85287230d55bdfa420t#endif
9698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
9718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* init all variables to a known value. */
9728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE);
9737988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->max_burst = inp->sctp_ep.max_burst;
9747988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->fr_max_burst = inp->sctp_ep.fr_max_burst;
9757988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
9767988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->cookie_life = inp->sctp_ep.def_cookie_life;
9777988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off;
978aba62ccbe62e9d5694e5ac85d8aaca0e72d3fd67t	asoc->ecn_supported = inp->ecn_supported;
979a8657c4fc04fb9cc82100f648810d51ec6ab155at	asoc->prsctp_supported = inp->prsctp_supported;
980fb3816eaffe5878bb1286adb120fd160da178a05t	asoc->auth_supported = inp->auth_supported;
981fb3816eaffe5878bb1286adb120fd160da178a05t	asoc->asconf_supported = inp->asconf_supported;
9822344bfccffeb80545fca6a86e8cda3d56a6f50bft	asoc->reconfig_supported = inp->reconfig_supported;
98344318e900a771ba1a5bafb510c38f33fd5cd8a39t	asoc->nrsack_supported = inp->nrsack_supported;
984669cffca0ac8ad73a3c16bb63d1fa0f829f84c10t	asoc->pktdrop_supported = inp->pktdrop_supported;
9858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->sctp_cmt_pf = (uint8_t)0;
9867988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->sctp_frag_point = inp->sctp_frag_point;
9877988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->sctp_features = inp->sctp_features;
9887988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->default_dscp = inp->sctp_ep.default_dscp;
9898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
9907988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	if (inp->sctp_ep.default_flowlabel) {
9917988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		asoc->default_flowlabel = inp->sctp_ep.default_flowlabel;
9928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
9937988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		if (inp->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) {
9947988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			asoc->default_flowlabel = sctp_select_initial_TSN(&inp->sctp_ep);
9958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->default_flowlabel &= 0x000fffff;
996b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			asoc->default_flowlabel |= 0x80000000;
9978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
9988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->default_flowlabel = 0;
9998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->sb_send_resv = 0;
10038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (override_tag) {
10048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->my_vtag = override_tag;
10058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
10067988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		asoc->my_vtag = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport,  1);
10078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Get the nonce tags */
10097988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->my_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
10107988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->peer_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
10118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->vrf_id = vrf_id;
10128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_ASOCLOG_OF_TSNS
10148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->tsn_in_at = 0;
1015e2828360ea9cf8951730d46f5c14626c9425cb30t	asoc->tsn_out_at = 0;
10168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->tsn_in_wrapped = 0;
10178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->tsn_out_wrapped = 0;
10188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->cumack_log_at = 0;
10198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->cumack_log_atsnt = 0;
10208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_FS_SPEC_LOG
10228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->fs_index = 0;
10238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->refcnt = 0;
10258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->assoc_up_sent = 0;
10268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq =
10277988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	    sctp_select_initial_TSN(&inp->sctp_ep);
10288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
10298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* we are optimisitic here */
10308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->peer_supports_nat = 0;
10318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->sent_queue_retran_cnt = 0;
10328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* for CMT */
10348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        asoc->last_net_cmt_send_started = NULL;
10358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* This will need to be adjusted */
10378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->last_acked_seq = asoc->init_seq_number - 1;
10388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->advanced_peer_ack_point = asoc->last_acked_seq;
10398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->asconf_seq_in = asoc->last_acked_seq;
10408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* here we are different, we hold the next one we expect */
10428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->str_reset_seq_in = asoc->last_acked_seq + 1;
10438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10447988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->initial_init_rto_max = inp->sctp_ep.initial_init_rto_max;
10457988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->initial_rto = inp->sctp_ep.initial_rto;
10468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10477988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->max_init_times = inp->sctp_ep.max_init_times;
10487988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->max_send_times = inp->sctp_ep.max_send_times;
10497988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->def_net_failure = inp->sctp_ep.def_net_failure;
10507988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->def_net_pf_threshold = inp->sctp_ep.def_net_pf_threshold;
10518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->free_chunk_cnt = 0;
10528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->iam_blocking = 0;
10547988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->context = inp->sctp_context;
10557988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->local_strreset_support = inp->local_strreset_support;
10567988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->def_send = inp->def_send;
10577988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->delayed_ack = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
10587988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->sack_freq = inp->sctp_ep.sctp_sack_freq;
10598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->pr_sctp_cnt = 0;
10608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->total_output_queue_size = 0;
10618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10627988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
10637988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		asoc->scope.ipv6_addr_legal = 1;
10647988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		if (SCTP_IPV6_V6ONLY(inp) == 0) {
10657988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			asoc->scope.ipv4_addr_legal = 1;
10668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
10677988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			asoc->scope.ipv4_addr_legal = 0;
10688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10697988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
10707988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			asoc->scope.conn_addr_legal = 0;
10717988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
10728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
10737988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		asoc->scope.ipv6_addr_legal = 0;
10747988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
10757988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
10767988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			asoc->scope.conn_addr_legal = 1;
10777988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			asoc->scope.ipv4_addr_legal = 0;
10787988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		} else {
10797988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			asoc->scope.conn_addr_legal = 0;
10807988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			asoc->scope.ipv4_addr_legal = 1;
10817988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		}
10827988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#else
10837988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		asoc->scope.ipv4_addr_legal = 1;
10847988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
10858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10877988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND);
10887988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(inp->sctp_socket);
10898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10907988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->smallest_mtu = inp->sctp_frag_point;
10917988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->minrto = inp->sctp_ep.sctp_minrto;
10927988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->maxrto = inp->sctp_ep.sctp_maxrto;
10938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->locked_on_sending = NULL;
10958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->stream_locked_on = 0;
10968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->ecn_echo_cnt_onq = 0;
10978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->stream_locked = 0;
10988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->send_sack = 1;
11008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_INIT(&asoc->sctp_restricted_addrs);
11028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&asoc->nets);
11048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&asoc->pending_reply_queue);
11058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&asoc->asconf_ack_sent);
11068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Setup to fill the hb random cache at first HB */
11078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->hb_random_idx = 4;
11088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11097988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->sctp_autoclose_ticks = inp->sctp_ep.auto_close_time;
11108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11117988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	stcb->asoc.congestion_control_module = inp->sctp_ep.sctp_default_cc_module;
11127988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	stcb->asoc.cc_functions = sctp_cc_functions[inp->sctp_ep.sctp_default_cc_module];
11138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11147988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	stcb->asoc.stream_scheduling_module = inp->sctp_ep.sctp_default_ss_module;
11157988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	stcb->asoc.ss_functions = sctp_ss_functions[inp->sctp_ep.sctp_default_ss_module];
11168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
11188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Now the stream parameters, here we allocate space for all streams
11198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * that we request by default.
11208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
11218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams =
11227988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	    inp->sctp_ep.pre_open_stream_count;
11238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *,
11248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    asoc->streamoutcnt * sizeof(struct sctp_stream_out),
11258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_M_STRMO);
11268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->strmout == NULL) {
11278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* big trouble no memory */
11288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
11298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOMEM);
11308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < asoc->streamoutcnt; i++) {
11328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
11338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * inbound side must be set to 0xffff, also NOTE when we get
11348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the INIT-ACK back (for INIT sender) we MUST reduce the
11358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * count (streamoutcnt) but first check if we sent to any of
11368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the upper streams that were dropped (if some were). Those
11378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * that were dropped must be notified to the upper layer as
11388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * failed to send.
11398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
1140e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t		asoc->strmout[i].next_sequence_send = 0x0;
11418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_INIT(&asoc->strmout[i].outqueue);
114260db5740d3bcc26fd4ebc19b6b0652506994fd14t		asoc->strmout[i].chunks_on_queues = 0;
114320d5d287bff2075897105f85287230d55bdfa420t#if defined(SCTP_DETAILED_STR_STATS)
114420d5d287bff2075897105f85287230d55bdfa420t		for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) {
114520d5d287bff2075897105f85287230d55bdfa420t			asoc->strmout[i].abandoned_sent[j] = 0;
114620d5d287bff2075897105f85287230d55bdfa420t			asoc->strmout[i].abandoned_unsent[j] = 0;
114720d5d287bff2075897105f85287230d55bdfa420t		}
114820d5d287bff2075897105f85287230d55bdfa420t#else
114920d5d287bff2075897105f85287230d55bdfa420t		asoc->strmout[i].abandoned_sent[0] = 0;
115020d5d287bff2075897105f85287230d55bdfa420t		asoc->strmout[i].abandoned_unsent[0] = 0;
115120d5d287bff2075897105f85287230d55bdfa420t#endif
11528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->strmout[i].stream_no = i;
11538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->strmout[i].last_msg_incomplete = 0;
11548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
11558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->ss_functions.sctp_ss_init(stcb, asoc, 0);
11578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now the mapping array */
11598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;
11608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(asoc->mapping_array, uint8_t *, asoc->mapping_array_size,
11618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_M_MAP);
11628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->mapping_array == NULL) {
11638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
11648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
11658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOMEM);
11668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1167000a5bac556b28e74e4e98c540f66b1743e9312dtuexen	memset(asoc->mapping_array, 0, asoc->mapping_array_size);
11688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(asoc->nr_mapping_array, uint8_t *, asoc->mapping_array_size,
11698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_M_MAP);
11708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->nr_mapping_array == NULL) {
11718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
11728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
11738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
11748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOMEM);
11758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size);
11778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now the init of the other outqueues */
11798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&asoc->free_chunks);
11808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&asoc->control_send_queue);
11818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&asoc->asconf_send_queue);
11828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&asoc->send_queue);
11838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&asoc->sent_queue);
11848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&asoc->reasmqueue);
11858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&asoc->resetHead);
11867988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->max_inbound_streams = inp->sctp_ep.max_open_streams_intome;
11878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&asoc->asconf_queue);
11888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* authentication fields */
11898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->authinfo.random = NULL;
11908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->authinfo.active_keyid = 0;
11918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->authinfo.assoc_key = NULL;
11928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->authinfo.assoc_keyid = 0;
11938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->authinfo.recv_key = NULL;
11948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->authinfo.recv_keyid = 0;
11958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_INIT(&asoc->shared_keys);
11968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->marked_retrans = 0;
11977988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	asoc->port = inp->sctp_ep.port;
11988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->timoinit = 0;
11998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->timodata = 0;
12008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->timosack = 0;
12018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->timoshutdown = 0;
12028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->timoheartbeat = 0;
12038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->timocookie = 0;
12048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->timoshutdownack = 0;
12058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)SCTP_GETTIME_TIMEVAL(&asoc->start_time);
12068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->discontinuity_time = asoc->start_time;
120720d5d287bff2075897105f85287230d55bdfa420t	for (i = 0; i < SCTP_PR_SCTP_MAX + 1; i++) {
120820d5d287bff2075897105f85287230d55bdfa420t		asoc->abandoned_unsent[i] = 0;
120920d5d287bff2075897105f85287230d55bdfa420t		asoc->abandoned_sent[i] = 0;
121020d5d287bff2075897105f85287230d55bdfa420t	}
12118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sa_ignore MEMLEAK {memory is put in the assoc mapping array and freed later when
12128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * the association is freed.
12138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
12148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
12158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
12168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
12188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_print_mapping_array(struct sctp_association *asoc)
12198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
12208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	unsigned int i, limit;
12218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
122247a306d634abf33223ef347472c4b1cd441d139ftuexen	SCTP_PRINTF("Mapping array size: %d, baseTSN: %8.8x, cumAck: %8.8x, highestTSN: (%8.8x, %8.8x).\n",
122347a306d634abf33223ef347472c4b1cd441d139ftuexen	            asoc->mapping_array_size,
122447a306d634abf33223ef347472c4b1cd441d139ftuexen	            asoc->mapping_array_base_tsn,
122547a306d634abf33223ef347472c4b1cd441d139ftuexen	            asoc->cumulative_tsn,
122647a306d634abf33223ef347472c4b1cd441d139ftuexen	            asoc->highest_tsn_inside_map,
122747a306d634abf33223ef347472c4b1cd441d139ftuexen	            asoc->highest_tsn_inside_nr_map);
12288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (limit = asoc->mapping_array_size; limit > 1; limit--) {
1229b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		if (asoc->mapping_array[limit - 1] != 0) {
12308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
12318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
123347a306d634abf33223ef347472c4b1cd441d139ftuexen	SCTP_PRINTF("Renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
12348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < limit; i++) {
123547a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("%2.2x%c", asoc->mapping_array[i], ((i + 1) % 16) ? ' ' : '\n');
12368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (limit % 16)
123847a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\n");
12398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (limit = asoc->mapping_array_size; limit > 1; limit--) {
12408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (asoc->nr_mapping_array[limit - 1]) {
12418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
12428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
124447a306d634abf33223ef347472c4b1cd441d139ftuexen	SCTP_PRINTF("Non renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
12458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < limit; i++) {
124647a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("%2.2x%c", asoc->nr_mapping_array[i], ((i + 1) % 16) ? ' ': '\n');
12478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (limit % 16)
124947a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("\n");
12508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
12518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
12538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed)
12548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
12558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* mapping array needs to grow */
12568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t *new_array1, *new_array2;
12578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t new_size;
12588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_size = asoc->mapping_array_size + ((needed+7)/8 + SCTP_MAPPING_ARRAY_INCR);
12608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(new_array1, uint8_t *, new_size, SCTP_M_MAP);
12618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(new_array2, uint8_t *, new_size, SCTP_M_MAP);
12628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((new_array1 == NULL) || (new_array2 == NULL)) {
12638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* can't get more, forget it */
12648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n", new_size);
12658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (new_array1) {
12668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE(new_array1, SCTP_M_MAP);
12678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (new_array2) {
12698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE(new_array2, SCTP_M_MAP);
12708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
12728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(new_array1, 0, new_size);
12748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(new_array2, 0, new_size);
12758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memcpy(new_array1, asoc->mapping_array, asoc->mapping_array_size);
12768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memcpy(new_array2, asoc->nr_mapping_array, asoc->mapping_array_size);
12778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
12788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP);
12798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->mapping_array = new_array1;
12808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->nr_mapping_array = new_array2;
12818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->mapping_array_size = new_size;
12828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
12838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
12848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
12878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_iterator_work(struct sctp_iterator *it)
12888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
12898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int iteration_count = 0;
12908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int inp_skip = 0;
1291b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int first_in = 1;
12928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *tinp;
1293000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
12948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_INFO_RLOCK();
12958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_ITERATOR_LOCK();
1296e2828360ea9cf8951730d46f5c14626c9425cb30t	if (it->inp) {
12978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(it->inp);
12988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_DECR_REF(it->inp);
12998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (it->inp == NULL) {
13018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* iterator is complete */
13028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexendone_with_iterator:
13038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_ITERATOR_UNLOCK();
13048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_INFO_RUNLOCK();
13058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (it->function_atend != NULL) {
13068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(*it->function_atend) (it->pointer, it->val);
13078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(it, SCTP_M_ITER);
13098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
13108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenselect_a_new_ep:
13128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (first_in) {
13138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		first_in = 0;
13148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
13158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(it->inp);
13168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (((it->pcb_flags) &&
13188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) ||
13198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	       ((it->pcb_features) &&
13208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) {
13218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* endpoint flags or features don't match, so keep looking */
13228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
13238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(it->inp);
13248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto done_with_iterator;
13258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tinp = it->inp;
13278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		it->inp = LIST_NEXT(it->inp, sctp_list);
13288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(tinp);
13298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (it->inp == NULL) {
13308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto done_with_iterator;
13318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(it->inp);
13338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now go through each assoc which is in the desired state */
13358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (it->done_current_ep == 0) {
13368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (it->function_inp != NULL)
13378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp_skip = (*it->function_inp)(it->inp, it->pointer, it->val);
13388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		it->done_current_ep = 1;
13398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (it->stcb == NULL) {
13418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* run the per instance function */
13428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
13438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp_skip) || it->stcb == NULL) {
13458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (it->function_inp_end != NULL) {
13468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp_skip = (*it->function_inp_end)(it->inp,
13478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							   it->pointer,
13488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							   it->val);
13498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(it->inp);
13518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto no_stcb;
13528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (it->stcb) {
13548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(it->stcb);
13558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
13568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* not in the right state... keep looking */
13578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(it->stcb);
13588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto next_assoc;
13598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* see if we have limited out the iterator loop */
13618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		iteration_count++;
13628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) {
13638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Pause to let others grab the lock */
13648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_add_int(&it->stcb->asoc.refcnt, 1);
13658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(it->stcb);
13668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INCR_REF(it->inp);
13678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RUNLOCK(it->inp);
13688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_ITERATOR_UNLOCK();
13698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INFO_RUNLOCK();
13708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_INFO_RLOCK();
13718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_ITERATOR_LOCK();
13728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_it_ctl.iterator_flags) {
13738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* We won't be staying here */
13748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(it->inp);
13758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				atomic_add_int(&it->stcb->asoc.refcnt, -1);
13768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__FreeBSD__)
13778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_it_ctl.iterator_flags &
13788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				   SCTP_ITERATOR_MUST_EXIT) {
13798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					goto done_with_iterator;
13808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
13818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
13828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_it_ctl.iterator_flags &
13838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				   SCTP_ITERATOR_STOP_CUR_IT) {
13848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_IT;
13858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					goto done_with_iterator;
13868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
13878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_it_ctl.iterator_flags &
13888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				   SCTP_ITERATOR_STOP_CUR_INP) {
13898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_INP;
13908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					goto no_stcb;
13918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
13928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* If we reach here huh? */
139347a306d634abf33223ef347472c4b1cd441d139ftuexen				SCTP_PRINTF("Unknown it ctl flag %x\n",
139447a306d634abf33223ef347472c4b1cd441d139ftuexen					    sctp_it_ctl.iterator_flags);
13958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_it_ctl.iterator_flags = 0;
13968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
13978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_RLOCK(it->inp);
13988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_DECR_REF(it->inp);
13998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_LOCK(it->stcb);
14008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_add_int(&it->stcb->asoc.refcnt, -1);
14018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			iteration_count = 0;
14028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* run function on this one */
14058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(*it->function_assoc)(it->inp, it->stcb, it->pointer, it->val);
14068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
14088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * we lie here, it really needs to have its own type but
14098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * first I must verify that this won't effect things :-0
14108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
14118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (it->no_chunk_output == 0)
14128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
14138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(it->stcb);
14158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	next_assoc:
14168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
14178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (it->stcb == NULL) {
14188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Run last function */
14198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (it->function_inp_end != NULL) {
14208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp_skip = (*it->function_inp_end)(it->inp,
14218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								   it->pointer,
14228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								   it->val);
14238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
14248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_RUNLOCK(it->inp);
14278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen no_stcb:
14288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* done with all assocs on this endpoint, move on to next endpoint */
14298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	it->done_current_ep = 0;
14308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
14318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		it->inp = NULL;
14328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
14338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		it->inp = LIST_NEXT(it->inp, sctp_list);
14348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (it->inp == NULL) {
14368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto done_with_iterator;
14378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	goto select_a_new_ep;
14398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
14408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
14428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_iterator_worker(void)
14438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
14448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_iterator *it, *nit;
14458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* This function is called with the WQ lock in place */
14478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_it_ctl.iterator_running = 1;
14498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
14508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_it_ctl.cur_it = it;
14518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* now lets work on this one */
14528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
14538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_IPI_ITERATOR_WQ_UNLOCK();
14548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
14558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		CURVNET_SET(it->vn);
14568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
14578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_iterator_work(it);
14588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_it_ctl.cur_it = NULL;
14598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
14608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		CURVNET_RESTORE();
14618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
14628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_IPI_ITERATOR_WQ_LOCK();
14638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__FreeBSD__)
14648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_it_ctl.iterator_flags & SCTP_ITERATOR_MUST_EXIT) {
14658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
14668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
14688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	        /*sa_ignore FREED_MEMORY*/
14698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_it_ctl.iterator_running = 0;
14718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return;
14728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
14738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
14768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_addr_wq(void)
14778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
14788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* deal with the ADDR wq from the rtsock calls */
14798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_laddr *wi, *nwi;
14808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_iterator *asc;
14818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
14838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct sctp_asconf_iterator), SCTP_M_ASC_IT);
14848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asc == NULL) {
14858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Try later, no memory */
14868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
14878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 (struct sctp_inpcb *)NULL,
14888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 (struct sctp_tcb *)NULL,
14898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 (struct sctp_nets *)NULL);
14908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
14918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_INIT(&asc->list_of_work);
14938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asc->cnt = 0;
14948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_WQ_ADDR_LOCK();
14968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
14978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_REMOVE(wi, sctp_nxt_addr);
14988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
14998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asc->cnt++;
15008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_WQ_ADDR_UNLOCK();
15028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asc->cnt == 0) {
15048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(asc, SCTP_M_ASC_IT);
15058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
15068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)sctp_initiate_iterator(sctp_asconf_iterator_ep,
15078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     sctp_asconf_iterator_stcb,
15088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     NULL, /* No ep end for boundall */
15098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     SCTP_PCB_FLAGS_BOUNDALL,
15108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     SCTP_PCB_ANY_FEATURES,
15118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     SCTP_ASOC_ANY_STATE,
15128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     (void *)asc, 0,
15138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     sctp_asconf_iterator_end, NULL, 0);
15148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
15168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
15188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_timeout_handler(void *t)
15198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
15208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
15218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb;
15228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
15238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_timer *tmr;
15240612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
15258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct socket *so;
15268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int did_output, type;
15288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr = (struct sctp_timer *)t;
15308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)tmr->ep;
15318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = (struct sctp_tcb *)tmr->tcb;
15328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net = (struct sctp_nets *)tmr->net;
15338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
15348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	CURVNET_SET((struct vnet *)tmr->vnet);
15358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	did_output = 1;
15378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
15398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_audit_log(0xF0, (uint8_t) tmr->type);
15408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_auditing(3, inp, stcb, net);
15418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sanity checks... */
15448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (tmr->self != (void *)tmr) {
15458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
15468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * SCTP_PRINTF("Stale SCTP timer fired (%p), ignoring...\n",
1547ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t		 *             (void *)tmr);
15488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
15498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
15508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		CURVNET_RESTORE();
15518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
15538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->stopped_from = 0xa001;
15558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!SCTP_IS_TIMER_TYPE_VALID(tmr->type)) {
15568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
15578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * SCTP_PRINTF("SCTP timer fired with invalid type: 0x%x\n",
15588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * tmr->type);
15598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
15608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
15618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		CURVNET_RESTORE();
15628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
15648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->stopped_from = 0xa002;
15668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((tmr->type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) {
15678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
15688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		CURVNET_RESTORE();
15698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
15718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* if this is an iterator timeout, get the struct and clear inp */
15738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->stopped_from = 0xa003;
15748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	type = tmr->type;
15758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp) {
15768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_INCR_REF(inp);
157723273859c39742f09cc5ec7c9bf32ff225661e82tuexen		if ((inp->sctp_socket == NULL) &&
15788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((tmr->type != SCTP_TIMER_TYPE_INPKILL) &&
15798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (tmr->type != SCTP_TIMER_TYPE_INIT) &&
15808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (tmr->type != SCTP_TIMER_TYPE_SEND) &&
15818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (tmr->type != SCTP_TIMER_TYPE_RECV) &&
15828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (tmr->type != SCTP_TIMER_TYPE_HEARTBEAT) &&
15838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (tmr->type != SCTP_TIMER_TYPE_SHUTDOWN) &&
15848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNACK) &&
15858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNGUARD) &&
15868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (tmr->type != SCTP_TIMER_TYPE_ASOCKILL))
15878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			) {
15888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_DECR_REF(inp);
15898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
15908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			CURVNET_RESTORE();
15918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
15938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->stopped_from = 0xa004;
15968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
15978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
15988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.state == 0) {
15998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_add_int(&stcb->asoc.refcnt, -1);
16008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp) {
16018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
16028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
16038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
16048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			CURVNET_RESTORE();
16058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
16068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
16078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->stopped_from = 0xa005;
16108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_TIMER1, "Timer type %d goes off\n", tmr->type);
16118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) {
16128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp) {
16138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_DECR_REF(inp);
16148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
16168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_add_int(&stcb->asoc.refcnt, -1);
16178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
16198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		CURVNET_RESTORE();
16208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
16218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
16228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->stopped_from = 0xa006;
16248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
16268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
16278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&stcb->asoc.refcnt, -1);
16288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((tmr->type != SCTP_TIMER_TYPE_ASOCKILL) &&
16298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((stcb->asoc.state == 0) ||
16308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED))) {
16318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
16328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp) {
16338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_DECR_REF(inp);
16348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
16358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
16368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			CURVNET_RESTORE();
16378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
16388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
16398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* record in stopped what t-o occured */
16428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->stopped_from = tmr->type;
16438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* mark as being serviced now */
16458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
16468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
16478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Callout has been rescheduled.
16488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
16498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto get_out;
16508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) {
16528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
16538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Not active, so no action.
16548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
16558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto get_out;
16568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_OS_TIMER_DEACTIVATE(&tmr->timer);
16588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* call the handler for the appropriate timer type */
16608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (tmr->type) {
16618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ZERO_COPY:
16628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp == NULL) {
16638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
16648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
16668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
16678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
16698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
16708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp == NULL) {
16718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
16728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
16748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_ZERO_COPY_SENDQ_EVENT(inp, inp->sctp_socket);
16758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                break;
16778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ADDR_WQ:
16788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_handle_addr_wq();
16798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
16808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SEND:
16818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
16828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
16838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timodata);
16858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.timodata++;
16868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.num_send_timers_up--;
16878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.num_send_timers_up < 0) {
16888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.num_send_timers_up = 0;
16898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK_ASSERT(stcb);
1691b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		if (sctp_t3rxt_timer(inp, stcb, net)) {
16928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no need to unlock on tcb its gone */
16938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_decr;
16958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK_ASSERT(stcb);
16978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
16988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auditing(4, inp, stcb, net);
16998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
17018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb->asoc.num_send_timers_up == 0) &&
17028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (stcb->asoc.sent_queue_cnt > 0)) {
17038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_tmit_chunk *chk;
17048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
17068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * safeguard. If there on some on the sent queue
17078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * somewhere but no timers running something is
17088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * wrong... so we start a timer on the first chunk
17098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * on the send queue on whatever net it is sent to.
17108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
17118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
17128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb,
17138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    chk->whoTo);
17148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
17168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_INIT:
17178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
17188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
17198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timoinit);
17218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.timoinit++;
17228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_t1init_timer(inp, stcb, net)) {
17238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no need to unlock on tcb its gone */
17248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_decr;
17258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We do output but not here */
17278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		did_output = 0;
17288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
17298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_RECV:
17308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
17318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
17328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timosack);
17348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.timosack++;
17358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
17368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
17378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auditing(4, inp, stcb, net);
17388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SACK_TMR, SCTP_SO_NOT_LOCKED);
17408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
17418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SHUTDOWN:
17428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
17438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
17448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_shutdown_timer(inp, stcb, net)) {
17468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no need to unlock on tcb its gone */
17478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_decr;
17488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timoshutdown);
17508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.timoshutdown++;
17518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
17528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auditing(4, inp, stcb, net);
17538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_NOT_LOCKED);
17558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
17568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_HEARTBEAT:
17578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL) || (net == NULL)) {
17588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
17598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timoheartbeat);
17618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.timoheartbeat++;
17628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_heartbeat_timer(inp, stcb, net)) {
17638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no need to unlock on tcb its gone */
17648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_decr;
17658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
17678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auditing(4, inp, stcb, net);
17688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!(net->dest_state & SCTP_ADDR_NOHB)) {
17708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
17718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_HB_TMR, SCTP_SO_NOT_LOCKED);
17728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
17748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_COOKIE:
17758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
17768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
17778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_cookie_timer(inp, stcb, net)) {
17808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no need to unlock on tcb its gone */
17818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_decr;
17828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timocookie);
17848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.timocookie++;
17858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
17868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auditing(4, inp, stcb, net);
17878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
17888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
17898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * We consider T3 and Cookie timer pretty much the same with
17908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * respect to where from in chunk_output.
17918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
17928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
17938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
17948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_NEWCOOKIE:
17958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
17968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct timeval tv;
17978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int i, secret;
17988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp == NULL) {
17998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
18008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_INCR(sctps_timosecret);
18028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(void)SCTP_GETTIME_TIMEVAL(&tv);
18038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WLOCK(inp);
18048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.time_of_secret_change = tv.tv_sec;
18058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.last_secret_number =
18068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    inp->sctp_ep.current_secret_number;
18078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp->sctp_ep.current_secret_number++;
18088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->sctp_ep.current_secret_number >=
18098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_HOW_MANY_SECRETS) {
18108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.current_secret_number = 0;
18118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			secret = (int)inp->sctp_ep.current_secret_number;
18138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) {
18148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				inp->sctp_ep.secret_key[secret][i] =
18158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    sctp_select_initial_TSN(&inp->sctp_ep);
18168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
18178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_WUNLOCK(inp);
18188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net);
18198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		did_output = 0;
18218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
18228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_PATHMTURAISE:
18238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
18248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
18258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timopathmtu);
18278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_pathmtu_timer(inp, stcb, net);
18288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		did_output = 0;
18298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
18308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SHUTDOWNACK:
18318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
18328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
18338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_shutdownack_timer(inp, stcb, net)) {
18358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no need to unlock on tcb its gone */
18368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_decr;
18378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timoshutdownack);
1839e2828360ea9cf8951730d46f5c14626c9425cb30t		stcb->asoc.timoshutdownack++;
18408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
18418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auditing(4, inp, stcb, net);
18428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_ACK_TMR, SCTP_SO_NOT_LOCKED);
18448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
18458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
18468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
18478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
18488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timoshutdownguard);
185047674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_abort_an_association(inp, stcb, NULL, SCTP_SO_NOT_LOCKED);
18518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no need to unlock on tcb its gone */
18528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_decr;
18538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_STRRESET:
18558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
18568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
18578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_strreset_timer(inp, stcb, net)) {
18598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no need to unlock on tcb its gone */
18608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_decr;
18618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timostrmrst);
18638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_TMR, SCTP_SO_NOT_LOCKED);
18648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
18658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ASCONF:
18668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
18678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
18688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_asconf_timer(inp, stcb, net)) {
18708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no need to unlock on tcb its gone */
18718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out_decr;
18728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timoasconf);
18748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
18758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auditing(4, inp, stcb, net);
18768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_ASCONF_TMR, SCTP_SO_NOT_LOCKED);
18788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
18798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_PRIM_DELETED:
18808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
18818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
18828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_delete_prim_timer(inp, stcb, net);
18848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timodelprim);
18858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
18868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_AUTOCLOSE:
18888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
18898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
18908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timoautoclose);
18928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_autoclose_timer(inp, stcb, net);
18938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED);
18948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		did_output = 0;
18958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
18968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ASOCKILL:
18978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
18988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
18998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timoassockill);
19018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Can we free it yet? */
19028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_DECR_REF(inp);
19038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_1);
19040612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
19058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so = SCTP_INP_SO(inp);
19068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
19078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
19088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_LOCK(so, 1);
19098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
19108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
19118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_2);
19130612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
19148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_UNLOCK(so, 1);
19158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
19178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * free asoc, always unlocks (or destroy's) so prevent
19188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * duplicate unlock or unlock of a free mtx :-0
19198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
19208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = NULL;
19218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_no_decr;
19228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_INPKILL:
19238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_timoinpkill);
19248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp == NULL) {
19258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
19268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
19288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * special case, take away our increment since WE are the
19298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * killer
19308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
19318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_DECR_REF(inp);
19328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_3);
19338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
19348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_LOCK(SCTP_INP_SO(inp), 1);
19358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
19378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_CALLED_FROM_INPKILL_TIMER);
19388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
19398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_UNLOCK(SCTP_INP_SO(inp), 1);
19408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp = NULL;
19428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out_no_decr;
19438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
19448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_TIMER1, "sctp_timeout_handler:unknown timer %d\n",
19458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tmr->type);
19468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
1947b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	}
19488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
19498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_audit_log(0xF1, (uint8_t) tmr->type);
19508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp)
19518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auditing(5, inp, stcb, net);
19528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((did_output) && stcb) {
19548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
19558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Now we need to clean up the control chunk chain if an
19568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * ECNE is on it. It must be marked as UNSENT again so next
19578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * call will continue to send it until such time that we get
19588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * a CWR, to remove it. It is, however, less likely that we
19598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * will find a ecn echo on the chain though.
19608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
19618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_fix_ecn_echo(&stcb->asoc);
19628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenget_out:
19648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
19658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
19668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenout_decr:
19698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp) {
19708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_DECR_REF(inp);
19718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenout_no_decr:
19748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type %d)\n",
19758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  type);
19768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 801000
19778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	CURVNET_RESTORE();
19788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
19808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
19828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
19838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_nets *net)
19848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
19858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t to_ticks;
19868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_timer *tmr;
19878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL))
19898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
19908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr = NULL;
19928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
19938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK_ASSERT(stcb);
19948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (t_type) {
19968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ZERO_COPY:
19978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &inp->sctp_ep.zero_copy_timer;
19988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to_ticks = SCTP_ZERO_COPY_TICK_DELAY;
19998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
20008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
20018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &inp->sctp_ep.zero_copy_sendq_timer;
20028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to_ticks = SCTP_ZERO_COPY_SENDQ_TICK_DELAY;
20038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
20048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ADDR_WQ:
20058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Only 1 tick away :-) */
20068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &SCTP_BASE_INFO(addr_wq_timer);
20078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to_ticks = SCTP_ADDRESS_TICK_DELAY;
20088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
20098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SEND:
20108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Here we use the RTO timer */
20118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
20128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int rto_val;
20138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((stcb == NULL) || (net == NULL)) {
20158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
20168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tmr = &net->rxt_timer;
20188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->RTO == 0) {
20198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				rto_val = stcb->asoc.initial_rto;
20208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
20218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				rto_val = net->RTO;
20228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(rto_val);
20248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
20268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_INIT:
20278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
20288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Here we use the INIT timer default usually about 1
20298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * minute.
20308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
20318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
20328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
20338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->rxt_timer;
20358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->RTO == 0) {
20368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
20378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
20388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(net->RTO);
20398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
20418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_RECV:
20428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
20438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Here we use the Delayed-Ack timer value from the inp
20448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * ususually about 200ms.
20458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
20468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
20478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
20488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.dack_timer;
20508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to_ticks = MSEC_TO_TICKS(stcb->asoc.delayed_ack);
20518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
20528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SHUTDOWN:
20538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Here we use the RTO of the destination. */
20548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
20558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
20568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->RTO == 0) {
20588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
20598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
20608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(net->RTO);
20618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->rxt_timer;
20638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
20648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_HEARTBEAT:
20658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
20668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the net is used here so that we can add in the RTO. Even
20678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * though we use a different timer. We also add the HB timer
20688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * PLUS a random jitter.
20698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
20708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp == NULL) || (stcb == NULL) || (net == NULL)) {
20718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
20728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
20738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint32_t rndval;
20748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint32_t jitter;
20758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((net->dest_state & SCTP_ADDR_NOHB) &&
20778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    !(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
20788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
20798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->RTO == 0) {
20818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				to_ticks = stcb->asoc.initial_rto;
20828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
20838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				to_ticks = net->RTO;
20848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			rndval = sctp_select_initial_TSN(&inp->sctp_ep);
20868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			jitter = rndval % to_ticks;
20878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (jitter >= (to_ticks >> 1)) {
20888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				to_ticks = to_ticks + (jitter - (to_ticks >> 1));
20898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
20908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				to_ticks = to_ticks - jitter;
20918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
20938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    !(net->dest_state & SCTP_ADDR_PF)) {
20948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				to_ticks += net->heart_beat_delay;
20958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
20978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Now we must convert the to_ticks that are now in
20988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * ms to ticks.
20998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
21008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(to_ticks);
21018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tmr = &net->hb_timer;
21028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_COOKIE:
21058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
21068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Here we can use the RTO timer from the network since one
21078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * RTT was compelete. If a retran happened then we will be
21088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * using the RTO initial value.
21098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
21108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
21118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
21128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->RTO == 0) {
21148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
21158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
21168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(net->RTO);
21178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->rxt_timer;
21198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_NEWCOOKIE:
21218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
21228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * nothing needed but the endpoint here ususually about 60
21238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * minutes.
21248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
21258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp == NULL) {
21268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
21278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &inp->sctp_ep.signature_change;
21298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE];
21308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ASOCKILL:
21328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
21338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
21348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.strreset_timer;
21368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to_ticks = MSEC_TO_TICKS(SCTP_ASOC_KILL_TIMEOUT);
21378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_INPKILL:
21398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
21408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * The inp is setup to die. We re-use the signature_chage
21418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * timer since that has stopped and we are in the GONE
21428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * state.
21438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
21448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp == NULL) {
21458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
21468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &inp->sctp_ep.signature_change;
21488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to_ticks = MSEC_TO_TICKS(SCTP_INP_KILL_TIMEOUT);
21498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_PATHMTURAISE:
21518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
21528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Here we use the value found in the EP for PMTU ususually
21538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * about 10 minutes.
21548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
21558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (inp == NULL)) {
21568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
21578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net == NULL) {
21598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
21608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
21628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
21638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU];
21658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->pmtu_timer;
21668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SHUTDOWNACK:
21688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Here we use the RTO of the destination */
21698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
21708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
21718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->RTO == 0) {
21738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
21748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
21758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(net->RTO);
21768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->rxt_timer;
21788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
21808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
21818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Here we use the endpoints shutdown guard timer usually
21828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * about 3 minutes.
21838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
21848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp == NULL) || (stcb == NULL)) {
21858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
21868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN];
21888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.shut_guard_timer;
21898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
21908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_STRRESET:
21918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
21928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Here the timer comes from the stcb but its value is from
21938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the net's RTO.
21948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
21958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
21968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
21978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->RTO == 0) {
21998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
22008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
22018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(net->RTO);
22028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.strreset_timer;
22048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
22058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ASCONF:
22068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
22078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Here the timer comes from the stcb but its value is from
22088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the net's RTO.
22098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
22108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
22118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
22128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->RTO == 0) {
22148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
22158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
22168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			to_ticks = MSEC_TO_TICKS(net->RTO);
22178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.asconf_timer;
22198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
22208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_PRIM_DELETED:
22218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net != NULL)) {
22228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
22238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
22258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.delete_prim_timer;
22268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
22278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_AUTOCLOSE:
22288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
22298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
22308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.sctp_autoclose_ticks == 0) {
22328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
22338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Really an error since stcb is NOT set to
22348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * autoclose
22358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
22368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
22378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		to_ticks = stcb->asoc.sctp_autoclose_ticks;
22398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.autoclose_timer;
22408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
22418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
22428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n",
22438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			__FUNCTION__, t_type);
22448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
22458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
2246b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	}
22478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((to_ticks <= 0) || (tmr == NULL)) {
22488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_TIMER1, "%s: %d:software error to_ticks:%d tmr:%p not set ??\n",
2249ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t			__FUNCTION__, t_type, to_ticks, (void *)tmr);
22508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
22518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
22538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
22548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * we do NOT allow you to have it already running. if it is
22558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * we leave the current one up unchanged
22568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
22578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
22588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* At this point we can proceed */
22608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (t_type == SCTP_TIMER_TYPE_SEND) {
22618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.num_send_timers_up++;
22628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->stopped_from = 0;
22648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->type = t_type;
22658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->ep = (void *)inp;
22668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->tcb = (void *)stcb;
22678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->net = (void *)net;
22688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->self = (void *)tmr;
22698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 800000
22708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->vnet = (void *)curvnet;
22718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
22728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifndef __Panda__
22738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->ticks = sctp_get_tick_count();
22748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
22758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)SCTP_OS_TIMER_START(&tmr->timer, to_ticks, sctp_timeout_handler, tmr);
22768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return;
22778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
22788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
22808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
22818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_nets *net, uint32_t from)
22828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
22838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_timer *tmr;
22848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) &&
22868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp == NULL))
22878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
22888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr = NULL;
22908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
22918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK_ASSERT(stcb);
22928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (t_type) {
22948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ZERO_COPY:
22958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &inp->sctp_ep.zero_copy_timer;
22968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
22978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
22988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &inp->sctp_ep.zero_copy_sendq_timer;
22998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ADDR_WQ:
23018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &SCTP_BASE_INFO(addr_wq_timer);
23028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SEND:
23048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
23058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->rxt_timer;
23088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_INIT:
23108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
23118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->rxt_timer;
23148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_RECV:
23168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
23178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.dack_timer;
23208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SHUTDOWN:
23228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
23238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->rxt_timer;
23268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_HEARTBEAT:
23288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
23298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->hb_timer;
23328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_COOKIE:
23348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
23358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->rxt_timer;
23388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_NEWCOOKIE:
23408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* nothing needed but the endpoint here */
23418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &inp->sctp_ep.signature_change;
23428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
23438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * We re-use the newcookie timer for the INP kill timer. We
23448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * must assure that we do not kill it by accident.
23458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
23468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ASOCKILL:
23488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
23498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Stop the asoc kill timer.
23508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
23518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
23528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.strreset_timer;
23558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_INPKILL:
23588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
23598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * The inp is setup to die. We re-use the signature_chage
23608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * timer since that has stopped and we are in the GONE
23618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * state.
23628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
23638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &inp->sctp_ep.signature_change;
23648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_PATHMTURAISE:
23668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
23678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->pmtu_timer;
23708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SHUTDOWNACK:
23728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb == NULL) || (net == NULL)) {
23738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &net->rxt_timer;
23768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
23788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
23798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.shut_guard_timer;
23828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_STRRESET:
23848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
23858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.strreset_timer;
23888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_ASCONF:
23908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
23918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.asconf_timer;
23948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
23958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_PRIM_DELETED:
23968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
23978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
23988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.delete_prim_timer;
24008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
24018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_TIMER_TYPE_AUTOCLOSE:
24028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
24038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
24048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tmr = &stcb->asoc.autoclose_timer;
24068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
24078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
24088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n",
24098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			__FUNCTION__, t_type);
24108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
2411b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	}
24128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (tmr == NULL) {
24138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
24148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((tmr->type != t_type) && tmr->type) {
24168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
24178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Ok we have a timer that is under joint use. Cookie timer
24188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * per chance with the SEND timer. We therefore are NOT
24198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * running the timer that the caller wants stopped.  So just
24208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * return.
24218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
24228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
24238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((t_type == SCTP_TIMER_TYPE_SEND) && (stcb != NULL)) {
24258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.num_send_timers_up--;
24268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.num_send_timers_up < 0) {
24278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.num_send_timers_up = 0;
24288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->self = NULL;
24318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	tmr->stopped_from = from;
24328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)SCTP_OS_TIMER_STOP(&tmr->timer);
24338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return;
24348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
24358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
24378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_calculate_len(struct mbuf *m)
24388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
24398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t tlen = 0;
24408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *at;
24418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	at = m;
24438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (at) {
24448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tlen += SCTP_BUF_LEN(at);
24458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		at = SCTP_BUF_NEXT(at);
24468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (tlen);
24488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
24498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
24518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_mtu_size_reset(struct sctp_inpcb *inp,
24528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_association *asoc, uint32_t mtu)
24538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
24548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
24558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Reset the P-MTU size on this association, this involves changing
24568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * the asoc MTU, going through ANY chunk+overhead larger than mtu to
24578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * allow the DF flag to be cleared.
24588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
24598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk;
24608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	unsigned int eff_mtu, ovh;
24618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->smallest_mtu = mtu;
24638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
24648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ovh = SCTP_MIN_OVERHEAD;
24658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
24668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ovh = SCTP_MIN_V4_OVERHEAD;
24678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	eff_mtu = mtu - ovh;
24698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
24708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->send_size > eff_mtu) {
24718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
24728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
24758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->send_size > eff_mtu) {
24768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
24778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
24808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
24838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * given an association and starting time of the current RTT period return
24848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * RTO in number of msecs net should point to the current network
24858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
24868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
24888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_calculate_rto(struct sctp_tcb *stcb,
24898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   struct sctp_association *asoc,
24908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   struct sctp_nets *net,
24918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   struct timeval *told,
24928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   int safe, int rtt_from_sack)
24938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
24948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
24958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * given an association and the starting time of the current RTT
24968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * period (in value1/value2) return RTO in number of msecs.
24978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
24988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int32_t rtt; /* RTT in ms */
24998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t new_rto;
25008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int first_measure = 0;
25018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct timeval now, then, *old;
25028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Copy it out for sparc64 */
25048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (safe == sctp_align_unsafe_makecopy) {
25058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		old = &then;
25068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(&then, told, sizeof(struct timeval));
25078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (safe == sctp_align_safe_nocopy) {
25088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		old = told;
25098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
25108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* error */
25118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("Huh, bad rto calc call\n");
25128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
25138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/************************/
25158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* 1. calculate new RTT */
25168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/************************/
25178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* get the current time */
25188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.use_precise_time) {
25198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)SCTP_GETPTIME_TIMEVAL(&now);
25208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
25218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)SCTP_GETTIME_TIMEVAL(&now);
25228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	timevalsub(&now, old);
25248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* store the current RTT in us */
25251349669d594d3cd36f3e28ce0f755c303f766723t	net->rtt = (uint64_t)1000000 * (uint64_t)now.tv_sec +
25268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	           (uint64_t)now.tv_usec;
25278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* computer rtt in ms */
25288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	rtt = net->rtt / 1000;
2529b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) {
25308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Tell the CC module that a new update has just occurred from a sack */
25318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(*asoc->cc_functions.sctp_rtt_calculated)(stcb, net, &now);
25328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Do we need to determine the lan? We do this only
25348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * on sacks i.e. RTT being determined from data not
25358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * non-data (HB/INIT->INITACK).
25368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
25378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((rtt_from_sack == SCTP_RTT_FROM_DATA) &&
25388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (net->lan_type == SCTP_LAN_UNKNOWN)) {
25398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->rtt > SCTP_LOCAL_LAN_RTT) {
25408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->lan_type = SCTP_LAN_INTERNET;
25418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
25428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->lan_type = SCTP_LAN_LOCAL;
2543000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		}
25448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/***************************/
25478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* 2. update RTTVAR & SRTT */
25488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/***************************/
25498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*-
25508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Compute the scaled average lastsa and the
25518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * scaled variance lastsv as described in van Jacobson
25528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Paper "Congestion Avoidance and Control", Annex A.
25538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *
25548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * (net->lastsa >> SCTP_RTT_SHIFT) is the srtt
25558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * (net->lastsa >> SCTP_RTT_VAR_SHIFT) is the rttvar
25568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
25578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->RTO_measured) {
25588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rtt -= (net->lastsa >> SCTP_RTT_SHIFT);
25598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->lastsa += rtt;
25608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (rtt < 0) {
25618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			rtt = -rtt;
25628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rtt -= (net->lastsv >> SCTP_RTT_VAR_SHIFT);
25648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->lastsv += rtt;
25658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) {
25668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			rto_logging(net, SCTP_LOG_RTTVAR);
25678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
25698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* First RTO measurment */
25708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->RTO_measured = 1;
25718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		first_measure = 1;
25728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->lastsa = rtt << SCTP_RTT_SHIFT;
25738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->lastsv = (rtt / 2) << SCTP_RTT_VAR_SHIFT;
25748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) {
25758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			rto_logging(net, SCTP_LOG_INITIAL_RTT);
25768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->lastsv == 0) {
25798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net->lastsv = SCTP_CLOCK_GRANULARITY;
25808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
25828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((new_rto > SCTP_SAT_NETWORK_MIN) &&
25838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->asoc.sat_network_lockout == 0)) {
25848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.sat_network = 1;
25858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if ((!first_measure) && stcb->asoc.sat_network) {
25868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.sat_network = 0;
25878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.sat_network_lockout = 1;
25888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2589e2828360ea9cf8951730d46f5c14626c9425cb30t	/* bound it, per C6/C7 in Section 5.3.1 */
2590e2828360ea9cf8951730d46f5c14626c9425cb30t	if (new_rto < stcb->asoc.minrto) {
25918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		new_rto = stcb->asoc.minrto;
25928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (new_rto > stcb->asoc.maxrto) {
25948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		new_rto = stcb->asoc.maxrto;
25958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* we are now returning the RTO */
2597e2828360ea9cf8951730d46f5c14626c9425cb30t	return (new_rto);
25988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
25998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
26018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * return a pointer to a contiguous piece of data from the given mbuf chain
26028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * starting at 'off' for 'len' bytes.  If the desired piece spans more than
26038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * one mbuf, a copy is made at 'ptr'. caller must ensure that the buffer size
26048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is >= 'len' returns NULL if there there isn't 'len' bytes in the chain.
26058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
26068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexencaddr_t
26078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_m_getptr(struct mbuf *m, int off, int len, uint8_t * in_ptr)
26088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
26098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t count;
26108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t *ptr;
26118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ptr = in_ptr;
26138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((off < 0) || (len <= 0))
26148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
26158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* find the desired start location */
26178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while ((m != NULL) && (off > 0)) {
26188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (off < SCTP_BUF_LEN(m))
26198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
26208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		off -= SCTP_BUF_LEN(m);
26218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m = SCTP_BUF_NEXT(m);
26228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m == NULL)
26248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
26258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* is the current mbuf large enough (eg. contiguous)? */
26278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((SCTP_BUF_LEN(m) - off) >= len) {
26288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (mtod(m, caddr_t) + off);
26298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
26308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* else, it spans more than one mbuf, so save a temp copy... */
26318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		while ((m != NULL) && (len > 0)) {
26328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			count = min(SCTP_BUF_LEN(m) - off, len);
26338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bcopy(mtod(m, caddr_t) + off, ptr, count);
26348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			len -= count;
26358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ptr += count;
26368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			off = 0;
26378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m = SCTP_BUF_NEXT(m);
26388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((m == NULL) && (len > 0))
26408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (NULL);
26418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else
26428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return ((caddr_t)in_ptr);
26438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
26458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_paramhdr *
26498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_get_next_param(struct mbuf *m,
26508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int offset,
26518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_paramhdr *pull,
26528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int pull_limit)
26538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
26548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* This just provides a typed signature to Peter's Pull routine */
26558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return ((struct sctp_paramhdr *)sctp_m_getptr(m, offset, pull_limit,
26568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (uint8_t *) pull));
26578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
26588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2660290e3870bdc4b436f18bfe30e6c243205fc29702tstruct mbuf *
26618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_add_pad_tombuf(struct mbuf *m, int padlen)
26628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
2663290e3870bdc4b436f18bfe30e6c243205fc29702t	struct mbuf *m_last;
2664290e3870bdc4b436f18bfe30e6c243205fc29702t	caddr_t dp;
26658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (padlen > 3) {
2667290e3870bdc4b436f18bfe30e6c243205fc29702t		return (NULL);
26688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (padlen <= M_TRAILINGSPACE(m)) {
26708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
26718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * The easy way. We hope the majority of the time we hit
26728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * here :)
26738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
2674290e3870bdc4b436f18bfe30e6c243205fc29702t		m_last = m;
26758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
2676290e3870bdc4b436f18bfe30e6c243205fc29702t		/* Hard way we must grow the mbuf chain */
2677290e3870bdc4b436f18bfe30e6c243205fc29702t		m_last = sctp_get_mbuf_for_msg(padlen, 0, M_NOWAIT, 1, MT_DATA);
2678290e3870bdc4b436f18bfe30e6c243205fc29702t		if (m_last == NULL) {
2679290e3870bdc4b436f18bfe30e6c243205fc29702t			return (NULL);
2680290e3870bdc4b436f18bfe30e6c243205fc29702t		}
2681290e3870bdc4b436f18bfe30e6c243205fc29702t		SCTP_BUF_LEN(m_last) = 0;
2682290e3870bdc4b436f18bfe30e6c243205fc29702t		SCTP_BUF_NEXT(m_last) = NULL;
2683290e3870bdc4b436f18bfe30e6c243205fc29702t		SCTP_BUF_NEXT(m) = m_last;
26848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2685290e3870bdc4b436f18bfe30e6c243205fc29702t	dp = mtod(m_last, caddr_t) + SCTP_BUF_LEN(m_last);
2686290e3870bdc4b436f18bfe30e6c243205fc29702t	SCTP_BUF_LEN(m_last) += padlen;
2687290e3870bdc4b436f18bfe30e6c243205fc29702t	memset(dp, 0, padlen);
2688290e3870bdc4b436f18bfe30e6c243205fc29702t	return (m_last);
26898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
26908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2691290e3870bdc4b436f18bfe30e6c243205fc29702tstruct mbuf *
26928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf)
26938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
26948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* find the last mbuf in chain and pad it */
26958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_at;
26968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2697290e3870bdc4b436f18bfe30e6c243205fc29702t	if (last_mbuf != NULL) {
26988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (sctp_add_pad_tombuf(last_mbuf, padval));
26998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
27008f27eafd6937cbc8473a4b55a9c6fe8273d46523tuexen		for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
27018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BUF_NEXT(m_at) == NULL) {
27028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (sctp_add_pad_tombuf(m_at, padval));
27038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
27048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
27058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2706290e3870bdc4b436f18bfe30e6c243205fc29702t	return (NULL);
27078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
27088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
271047674b651417d493ff4e0318113fd7beeef119dbtuexensctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
271147674b651417d493ff4e0318113fd7beeef119dbtuexen    uint16_t error, struct sctp_abort_chunk *abort, uint8_t from_peer, int so_locked
27128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
27138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    SCTP_UNUSED
27148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
27158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    )
27168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
27178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_notify;
27188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_assoc_change *sac;
27198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
272047674b651417d493ff4e0318113fd7beeef119dbtuexen	size_t notif_len, abort_len;
272127c6a23c9dbbbe331f7a6b1ace5ffcb4055e2584tuexen	unsigned int i;
27220612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
27238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct socket *so;
27248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
27258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
272647674b651417d493ff4e0318113fd7beeef119dbtuexen	if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
272747674b651417d493ff4e0318113fd7beeef119dbtuexen		notif_len = sizeof(struct sctp_assoc_change);
272847674b651417d493ff4e0318113fd7beeef119dbtuexen		if (abort != NULL) {
27295310a647a74c51d125d106f350ff224bb017b0a5t			abort_len = ntohs(abort->ch.chunk_length);
27308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
273147674b651417d493ff4e0318113fd7beeef119dbtuexen			abort_len = 0;
273247674b651417d493ff4e0318113fd7beeef119dbtuexen		}
273347674b651417d493ff4e0318113fd7beeef119dbtuexen		if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
273447674b651417d493ff4e0318113fd7beeef119dbtuexen			notif_len += SCTP_ASSOC_SUPPORTS_MAX;
273547674b651417d493ff4e0318113fd7beeef119dbtuexen		} else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) {
273647674b651417d493ff4e0318113fd7beeef119dbtuexen			notif_len += abort_len;
273747674b651417d493ff4e0318113fd7beeef119dbtuexen		}
273868beeca578347438d9c434680197647ed551935ft		m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
273947674b651417d493ff4e0318113fd7beeef119dbtuexen		if (m_notify == NULL) {
274047674b651417d493ff4e0318113fd7beeef119dbtuexen			/* Retry with smaller value. */
274147674b651417d493ff4e0318113fd7beeef119dbtuexen			notif_len = sizeof(struct sctp_assoc_change);
274268beeca578347438d9c434680197647ed551935ft			m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
274347674b651417d493ff4e0318113fd7beeef119dbtuexen			if (m_notify == NULL) {
274447674b651417d493ff4e0318113fd7beeef119dbtuexen				goto set_error;
274547674b651417d493ff4e0318113fd7beeef119dbtuexen			}
27468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
274747674b651417d493ff4e0318113fd7beeef119dbtuexen		SCTP_BUF_NEXT(m_notify) = NULL;
274847674b651417d493ff4e0318113fd7beeef119dbtuexen		sac = mtod(m_notify, struct sctp_assoc_change *);
2749f496fe99adbad377f85add3a45e17f21a4702b41t		memset(sac, 0, notif_len);
275047674b651417d493ff4e0318113fd7beeef119dbtuexen		sac->sac_type = SCTP_ASSOC_CHANGE;
275147674b651417d493ff4e0318113fd7beeef119dbtuexen		sac->sac_flags = 0;
275247674b651417d493ff4e0318113fd7beeef119dbtuexen		sac->sac_length = sizeof(struct sctp_assoc_change);
275347674b651417d493ff4e0318113fd7beeef119dbtuexen		sac->sac_state = state;
275447674b651417d493ff4e0318113fd7beeef119dbtuexen		sac->sac_error = error;
275547674b651417d493ff4e0318113fd7beeef119dbtuexen		/* XXX verify these stream counts */
275647674b651417d493ff4e0318113fd7beeef119dbtuexen		sac->sac_outbound_streams = stcb->asoc.streamoutcnt;
275747674b651417d493ff4e0318113fd7beeef119dbtuexen		sac->sac_inbound_streams = stcb->asoc.streamincnt;
275847674b651417d493ff4e0318113fd7beeef119dbtuexen		sac->sac_assoc_id = sctp_get_associd(stcb);
275947674b651417d493ff4e0318113fd7beeef119dbtuexen		if (notif_len > sizeof(struct sctp_assoc_change)) {
276047674b651417d493ff4e0318113fd7beeef119dbtuexen			if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
276147674b651417d493ff4e0318113fd7beeef119dbtuexen				i = 0;
2762fb3816eaffe5878bb1286adb120fd160da178a05t				if (stcb->asoc.prsctp_supported == 1) {
276347674b651417d493ff4e0318113fd7beeef119dbtuexen					sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR;
276447674b651417d493ff4e0318113fd7beeef119dbtuexen				}
2765fb3816eaffe5878bb1286adb120fd160da178a05t				if (stcb->asoc.auth_supported == 1) {
276647674b651417d493ff4e0318113fd7beeef119dbtuexen					sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH;
276747674b651417d493ff4e0318113fd7beeef119dbtuexen				}
2768fb3816eaffe5878bb1286adb120fd160da178a05t				if (stcb->asoc.asconf_supported == 1) {
276947674b651417d493ff4e0318113fd7beeef119dbtuexen					sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF;
277047674b651417d493ff4e0318113fd7beeef119dbtuexen				}
277147674b651417d493ff4e0318113fd7beeef119dbtuexen				sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF;
2772fb3816eaffe5878bb1286adb120fd160da178a05t				if (stcb->asoc.reconfig_supported == 1) {
277347674b651417d493ff4e0318113fd7beeef119dbtuexen					sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG;
277447674b651417d493ff4e0318113fd7beeef119dbtuexen				}
277547674b651417d493ff4e0318113fd7beeef119dbtuexen				sac->sac_length += i;
277647674b651417d493ff4e0318113fd7beeef119dbtuexen			} else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) {
277747674b651417d493ff4e0318113fd7beeef119dbtuexen				memcpy(sac->sac_info, abort, abort_len);
277847674b651417d493ff4e0318113fd7beeef119dbtuexen				sac->sac_length += abort_len;
27798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
27808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
278147674b651417d493ff4e0318113fd7beeef119dbtuexen		SCTP_BUF_LEN(m_notify) = sac->sac_length;
278247674b651417d493ff4e0318113fd7beeef119dbtuexen		control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
2783f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                                 0, 0, stcb->asoc.context, 0, 0, 0,
2784f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                                 m_notify);
278547674b651417d493ff4e0318113fd7beeef119dbtuexen		if (control != NULL) {
278647674b651417d493ff4e0318113fd7beeef119dbtuexen			control->length = SCTP_BUF_LEN(m_notify);
278747674b651417d493ff4e0318113fd7beeef119dbtuexen			/* not that we need this */
278847674b651417d493ff4e0318113fd7beeef119dbtuexen			control->tail_mbuf = m_notify;
278947674b651417d493ff4e0318113fd7beeef119dbtuexen			control->spec_flags = M_NOTIFICATION;
279047674b651417d493ff4e0318113fd7beeef119dbtuexen			sctp_add_to_readq(stcb->sctp_ep, stcb,
2791f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t			                  control,
2792f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t			                  &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD,
2793f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t			                  so_locked);
279447674b651417d493ff4e0318113fd7beeef119dbtuexen		} else {
279547674b651417d493ff4e0318113fd7beeef119dbtuexen			sctp_m_freem(m_notify);
27968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
27978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
279847674b651417d493ff4e0318113fd7beeef119dbtuexen	/*
279947674b651417d493ff4e0318113fd7beeef119dbtuexen	 * For 1-to-1 style sockets, we send up and error when an ABORT
280047674b651417d493ff4e0318113fd7beeef119dbtuexen	 * comes in.
280147674b651417d493ff4e0318113fd7beeef119dbtuexen	 */
280247674b651417d493ff4e0318113fd7beeef119dbtuexenset_error:
280347674b651417d493ff4e0318113fd7beeef119dbtuexen	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
280447674b651417d493ff4e0318113fd7beeef119dbtuexen	     (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
280547674b651417d493ff4e0318113fd7beeef119dbtuexen	    ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
2806ac641287e0df6fd0b0ede6a7bd9d2932c13b5c58t		SOCK_LOCK(stcb->sctp_socket);
280747674b651417d493ff4e0318113fd7beeef119dbtuexen		if (from_peer) {
280847674b651417d493ff4e0318113fd7beeef119dbtuexen			if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
280947674b651417d493ff4e0318113fd7beeef119dbtuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED);
281047674b651417d493ff4e0318113fd7beeef119dbtuexen				stcb->sctp_socket->so_error = ECONNREFUSED;
281147674b651417d493ff4e0318113fd7beeef119dbtuexen			} else {
281247674b651417d493ff4e0318113fd7beeef119dbtuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
281347674b651417d493ff4e0318113fd7beeef119dbtuexen				stcb->sctp_socket->so_error = ECONNRESET;
28148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
281547674b651417d493ff4e0318113fd7beeef119dbtuexen		} else {
2816682e11ee64158de5e65420faf52a7f6eaed92625t			if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) ||
2817682e11ee64158de5e65420faf52a7f6eaed92625t			    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
2818682e11ee64158de5e65420faf52a7f6eaed92625t				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ETIMEDOUT);
2819682e11ee64158de5e65420faf52a7f6eaed92625t				stcb->sctp_socket->so_error = ETIMEDOUT;
2820682e11ee64158de5e65420faf52a7f6eaed92625t			} else {
2821682e11ee64158de5e65420faf52a7f6eaed92625t				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNABORTED);
2822682e11ee64158de5e65420faf52a7f6eaed92625t				stcb->sctp_socket->so_error = ECONNABORTED;
2823682e11ee64158de5e65420faf52a7f6eaed92625t			}
28248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
282547674b651417d493ff4e0318113fd7beeef119dbtuexen	}
282647674b651417d493ff4e0318113fd7beeef119dbtuexen	/* Wake ANY sleepers */
28270612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
282847674b651417d493ff4e0318113fd7beeef119dbtuexen	so = SCTP_INP_SO(stcb->sctp_ep);
282947674b651417d493ff4e0318113fd7beeef119dbtuexen	if (!so_locked) {
283047674b651417d493ff4e0318113fd7beeef119dbtuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
283147674b651417d493ff4e0318113fd7beeef119dbtuexen		SCTP_TCB_UNLOCK(stcb);
283247674b651417d493ff4e0318113fd7beeef119dbtuexen		SCTP_SOCKET_LOCK(so, 1);
283347674b651417d493ff4e0318113fd7beeef119dbtuexen		SCTP_TCB_LOCK(stcb);
283447674b651417d493ff4e0318113fd7beeef119dbtuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
283547674b651417d493ff4e0318113fd7beeef119dbtuexen		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
28368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_UNLOCK(so, 1);
283747674b651417d493ff4e0318113fd7beeef119dbtuexen			return;
28388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
283947674b651417d493ff4e0318113fd7beeef119dbtuexen	}
28408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
284147674b651417d493ff4e0318113fd7beeef119dbtuexen	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
284247674b651417d493ff4e0318113fd7beeef119dbtuexen	     (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
284347674b651417d493ff4e0318113fd7beeef119dbtuexen	    ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
2844ac641287e0df6fd0b0ede6a7bd9d2932c13b5c58t#if defined(__APPLE__)
284547674b651417d493ff4e0318113fd7beeef119dbtuexen		socantrcvmore(stcb->sctp_socket);
2846ac641287e0df6fd0b0ede6a7bd9d2932c13b5c58t#else
2847ac641287e0df6fd0b0ede6a7bd9d2932c13b5c58t		socantrcvmore_locked(stcb->sctp_socket);
2848ac641287e0df6fd0b0ede6a7bd9d2932c13b5c58t#endif
28498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
285047674b651417d493ff4e0318113fd7beeef119dbtuexen	sorwakeup(stcb->sctp_socket);
285147674b651417d493ff4e0318113fd7beeef119dbtuexen	sowwakeup(stcb->sctp_socket);
28520612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
285347674b651417d493ff4e0318113fd7beeef119dbtuexen	if (!so_locked) {
285447674b651417d493ff4e0318113fd7beeef119dbtuexen		SCTP_SOCKET_UNLOCK(so, 1);
285547674b651417d493ff4e0318113fd7beeef119dbtuexen	}
285647674b651417d493ff4e0318113fd7beeef119dbtuexen#endif
28578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
28588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
28608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
28618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sockaddr *sa, uint32_t error)
28628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
28638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_notify;
28648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_paddr_change *spc;
28658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
28668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2867b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if ((stcb == NULL) ||
2868b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) {
28698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* event not enabled */
28708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
28718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
287268beeca578347438d9c434680197647ed551935ft	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_paddr_change), 0, M_NOWAIT, 1, MT_DATA);
28738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_notify == NULL)
28748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
28758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = 0;
28768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	spc = mtod(m_notify, struct sctp_paddr_change *);
28771fb710c36aa9c19e470ebc5c5974879871f7e221t	memset(spc, 0, sizeof(struct sctp_paddr_change));
28788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	spc->spc_type = SCTP_PEER_ADDR_CHANGE;
28798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	spc->spc_flags = 0;
28808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	spc->spc_length = sizeof(struct sctp_paddr_change);
28818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (sa->sa_family) {
28828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
28838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
28848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
28858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
28868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
28878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
28888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
28898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
28908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_EMBEDDED_V6_SCOPE
28918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6;
28928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
28938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6));
28948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_EMBEDDED_V6_SCOPE
28968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
28978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
28988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sin6->sin6_scope_id == 0) {
28998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* recover scope_id for user */
29008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME
2901e2828360ea9cf8951730d46f5c14626c9425cb30t				(void)sa6_recoverscope(sin6);
29028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
29038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)in6_recoverscope(sin6, &sin6->sin6_addr,
29048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						       NULL);
29058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
29078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* clear embedded scope_id for user */
29088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				in6_clearscope(&sin6->sin6_addr);
29098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
29108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
29128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
29138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
291566e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__)
291666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen	case AF_CONN:
291766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_conn));
291866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		break;
291966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif
29208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
29218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* TSNH */
29228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
29238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	spc->spc_state = state;
29258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	spc->spc_error = error;
29268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	spc->spc_assoc_id = sctp_get_associd(stcb);
29278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_paddr_change);
29298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_NEXT(m_notify) = NULL;
29308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* append to socket */
29328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
29330ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 0, 0, stcb->asoc.context, 0, 0, 0,
29340ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 m_notify);
29358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
29368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no memory */
29378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
29388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
29398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->length = SCTP_BUF_LEN(m_notify);
29418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->spec_flags = M_NOTIFICATION;
29428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* not that we need this */
29438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->tail_mbuf = m_notify;
29448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_add_to_readq(stcb->sctp_ep, stcb,
2945f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t	                  control,
2946f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t	                  &stcb->sctp_socket->so_rcv, 1,
2947f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t	                  SCTP_READ_LOCK_NOT_HELD,
2948f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t	                  SCTP_SO_NOT_LOCKED);
29498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
29508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
295347674b651417d493ff4e0318113fd7beeef119dbtuexensctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
29548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_tmit_chunk *chk, int so_locked
29558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
29568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    SCTP_UNUSED
29578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    )
29598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
29608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_notify;
29618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_send_failed *ssf;
29625741e159bdf238ef4b61085d6fbfea2947386238tuexen	struct sctp_send_failed_event *ssfe;
29638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
29648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int length;
29658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2966b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if ((stcb == NULL) ||
29675741e159bdf238ef4b61085d6fbfea2947386238tuexen	    (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
29685741e159bdf238ef4b61085d6fbfea2947386238tuexen	     sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
29698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* event not enabled */
29708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
29718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29735741e159bdf238ef4b61085d6fbfea2947386238tuexen	if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
29745741e159bdf238ef4b61085d6fbfea2947386238tuexen		length = sizeof(struct sctp_send_failed_event);
29755741e159bdf238ef4b61085d6fbfea2947386238tuexen	} else {
29765741e159bdf238ef4b61085d6fbfea2947386238tuexen		length = sizeof(struct sctp_send_failed);
29775741e159bdf238ef4b61085d6fbfea2947386238tuexen	}
297868beeca578347438d9c434680197647ed551935ft	m_notify = sctp_get_mbuf_for_msg(length, 0, M_NOWAIT, 1, MT_DATA);
29798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_notify == NULL)
29808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no space left */
29818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
29828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = 0;
29835741e159bdf238ef4b61085d6fbfea2947386238tuexen	if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
29845741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe = mtod(m_notify, struct sctp_send_failed_event *);
2985f496fe99adbad377f85add3a45e17f21a4702b41t		memset(ssfe, 0, length);
29865741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
298747674b651417d493ff4e0318113fd7beeef119dbtuexen		if (sent) {
29885741e159bdf238ef4b61085d6fbfea2947386238tuexen			ssfe->ssfe_flags = SCTP_DATA_SENT;
298947674b651417d493ff4e0318113fd7beeef119dbtuexen		} else {
299047674b651417d493ff4e0318113fd7beeef119dbtuexen			ssfe->ssfe_flags = SCTP_DATA_UNSENT;
299147674b651417d493ff4e0318113fd7beeef119dbtuexen		}
2992f496fe99adbad377f85add3a45e17f21a4702b41t		length += chk->send_size;
2993f496fe99adbad377f85add3a45e17f21a4702b41t		length -= sizeof(struct sctp_data_chunk);
29945741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_length = length;
29955741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_error = error;
29965741e159bdf238ef4b61085d6fbfea2947386238tuexen		/* not exactly what the user sent in, but should be close :) */
29975741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number;
29985741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags;
29995741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype;
30005741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_info.snd_context = chk->rec.data.context;
30015741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
30025741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
30035741e159bdf238ef4b61085d6fbfea2947386238tuexen		SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
30045741e159bdf238ef4b61085d6fbfea2947386238tuexen	} else {
30055741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf = mtod(m_notify, struct sctp_send_failed *);
3006f496fe99adbad377f85add3a45e17f21a4702b41t		memset(ssf, 0, length);
30075741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_type = SCTP_SEND_FAILED;
300847674b651417d493ff4e0318113fd7beeef119dbtuexen		if (sent) {
30095741e159bdf238ef4b61085d6fbfea2947386238tuexen			ssf->ssf_flags = SCTP_DATA_SENT;
301047674b651417d493ff4e0318113fd7beeef119dbtuexen		} else {
301147674b651417d493ff4e0318113fd7beeef119dbtuexen			ssf->ssf_flags = SCTP_DATA_UNSENT;
301247674b651417d493ff4e0318113fd7beeef119dbtuexen		}
3013f496fe99adbad377f85add3a45e17f21a4702b41t		length += chk->send_size;
3014f496fe99adbad377f85add3a45e17f21a4702b41t		length -= sizeof(struct sctp_data_chunk);
30155741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_length = length;
30165741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_error = error;
30175741e159bdf238ef4b61085d6fbfea2947386238tuexen		/* not exactly what the user sent in, but should be close :) */
30185741e159bdf238ef4b61085d6fbfea2947386238tuexen		bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
30195741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
30205741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
30215741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
30225741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
30235741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_info.sinfo_context = chk->rec.data.context;
30245741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
30255741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_assoc_id = sctp_get_associd(stcb);
30265741e159bdf238ef4b61085d6fbfea2947386238tuexen		SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
30275741e159bdf238ef4b61085d6fbfea2947386238tuexen	}
30288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (chk->data) {
30298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
30308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * trim off the sctp chunk header(it should
30318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * be there)
30328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
30338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->send_size >= sizeof(struct sctp_data_chunk)) {
30348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m_adj(chk->data, sizeof(struct sctp_data_chunk));
30358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_mbuf_crush(chk->data);
30368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chk->send_size -= sizeof(struct sctp_data_chunk);
30378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
30398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_NEXT(m_notify) = chk->data;
30408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Steal off the mbuf */
30418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	chk->data = NULL;
30428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
30438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * For this case, we check the actual socket buffer, since the assoc
30448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * is going away we don't want to overfill the socket buffer for a
30458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * non-reader
30468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
30478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
30488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
30498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
30508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
30518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* append to socket */
30528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
30530ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 0, 0, stcb->asoc.context, 0, 0, 0,
30548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                                 m_notify);
30558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
30568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no memory */
30578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
30588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
30598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
30608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->spec_flags = M_NOTIFICATION;
30618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_add_to_readq(stcb->sctp_ep, stcb,
30628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                  control,
30638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                  &stcb->sctp_socket->so_rcv, 1,
30648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                  SCTP_READ_LOCK_NOT_HELD,
30658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                  so_locked);
30668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
30678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
30708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
30718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 struct sctp_stream_queue_pending *sp, int so_locked
30728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
30738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                         SCTP_UNUSED
30748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
30758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                         )
30768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
30778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_notify;
30788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_send_failed *ssf;
30795741e159bdf238ef4b61085d6fbfea2947386238tuexen	struct sctp_send_failed_event *ssfe;
30808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
30818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int length;
30828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3083b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if ((stcb == NULL) ||
30845741e159bdf238ef4b61085d6fbfea2947386238tuexen	    (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
30855741e159bdf238ef4b61085d6fbfea2947386238tuexen	     sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
30868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* event not enabled */
30878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
30888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
30895741e159bdf238ef4b61085d6fbfea2947386238tuexen	if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
30905741e159bdf238ef4b61085d6fbfea2947386238tuexen		length = sizeof(struct sctp_send_failed_event);
30915741e159bdf238ef4b61085d6fbfea2947386238tuexen	} else {
30925741e159bdf238ef4b61085d6fbfea2947386238tuexen		length = sizeof(struct sctp_send_failed);
30935741e159bdf238ef4b61085d6fbfea2947386238tuexen	}
309468beeca578347438d9c434680197647ed551935ft	m_notify = sctp_get_mbuf_for_msg(length, 0, M_NOWAIT, 1, MT_DATA);
30955741e159bdf238ef4b61085d6fbfea2947386238tuexen	if (m_notify == NULL) {
30968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no space left */
30978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
30985741e159bdf238ef4b61085d6fbfea2947386238tuexen	}
30998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = 0;
31005741e159bdf238ef4b61085d6fbfea2947386238tuexen	if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
31015741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe = mtod(m_notify, struct sctp_send_failed_event *);
3102f496fe99adbad377f85add3a45e17f21a4702b41t		memset(ssfe, 0, length);
3103f869e438447cc860e3c4bb11795ed58f30f30c36tuexen		ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
310447674b651417d493ff4e0318113fd7beeef119dbtuexen		ssfe->ssfe_flags = SCTP_DATA_UNSENT;
3105f496fe99adbad377f85add3a45e17f21a4702b41t		length += sp->length;
31065741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_length = length;
31075741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_error = error;
31085741e159bdf238ef4b61085d6fbfea2947386238tuexen		/* not exactly what the user sent in, but should be close :) */
31095741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_info.snd_sid = sp->stream;
31105741e159bdf238ef4b61085d6fbfea2947386238tuexen		if (sp->some_taken) {
31115741e159bdf238ef4b61085d6fbfea2947386238tuexen			ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG;
31125741e159bdf238ef4b61085d6fbfea2947386238tuexen		} else {
31135741e159bdf238ef4b61085d6fbfea2947386238tuexen			ssfe->ssfe_info.snd_flags = SCTP_DATA_NOT_FRAG;
31145741e159bdf238ef4b61085d6fbfea2947386238tuexen		}
31155741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_info.snd_ppid = sp->ppid;
31165741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_info.snd_context = sp->context;
31175741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
31185741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
31195741e159bdf238ef4b61085d6fbfea2947386238tuexen		SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
31208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
31215741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf = mtod(m_notify, struct sctp_send_failed *);
3122f496fe99adbad377f85add3a45e17f21a4702b41t		memset(ssf, 0, length);
31235741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_type = SCTP_SEND_FAILED;
312447674b651417d493ff4e0318113fd7beeef119dbtuexen		ssf->ssf_flags = SCTP_DATA_UNSENT;
3125f496fe99adbad377f85add3a45e17f21a4702b41t		length += sp->length;
31265741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_length = length;
31275741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_error = error;
31285741e159bdf238ef4b61085d6fbfea2947386238tuexen		/* not exactly what the user sent in, but should be close :) */
31295741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_info.sinfo_stream = sp->stream;
3130e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t		ssf->ssf_info.sinfo_ssn = 0;
31315741e159bdf238ef4b61085d6fbfea2947386238tuexen		if (sp->some_taken) {
31325741e159bdf238ef4b61085d6fbfea2947386238tuexen			ssf->ssf_info.sinfo_flags = SCTP_DATA_LAST_FRAG;
31335741e159bdf238ef4b61085d6fbfea2947386238tuexen		} else {
31345741e159bdf238ef4b61085d6fbfea2947386238tuexen			ssf->ssf_info.sinfo_flags = SCTP_DATA_NOT_FRAG;
31355741e159bdf238ef4b61085d6fbfea2947386238tuexen		}
31365741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_info.sinfo_ppid = sp->ppid;
31375741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_info.sinfo_context = sp->context;
31385741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
31395741e159bdf238ef4b61085d6fbfea2947386238tuexen		ssf->ssf_assoc_id = sctp_get_associd(stcb);
31405741e159bdf238ef4b61085d6fbfea2947386238tuexen		SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
31418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
31428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_NEXT(m_notify) = sp->data;
31438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Steal off the mbuf */
31458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sp->data = NULL;
31468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
31478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * For this case, we check the actual socket buffer, since the assoc
31488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * is going away we don't want to overfill the socket buffer for a
31498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * non-reader
31508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
31518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
31528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
31538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
31548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
31558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* append to socket */
31568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
31570ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 0, 0, stcb->asoc.context, 0, 0, 0,
31580ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 m_notify);
31598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
31608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no memory */
31618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
31628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
31638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
31648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->spec_flags = M_NOTIFICATION;
31658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_add_to_readq(stcb->sctp_ep, stcb,
31668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    control,
31678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked);
31688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
31698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
31730ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_notify_adaptation_layer(struct sctp_tcb *stcb)
31748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
31758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_notify;
31768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_adaptation_event *sai;
31778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
31788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3179b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if ((stcb == NULL) ||
3180b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) {
31818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* event not enabled */
31828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
31838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3184000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
318568beeca578347438d9c434680197647ed551935ft	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 0, M_NOWAIT, 1, MT_DATA);
31868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_notify == NULL)
31878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no space left */
31888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
31898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = 0;
31908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sai = mtod(m_notify, struct sctp_adaptation_event *);
3191f496fe99adbad377f85add3a45e17f21a4702b41t	memset(sai, 0, sizeof(struct sctp_adaptation_event));
31928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sai->sai_type = SCTP_ADAPTATION_INDICATION;
31938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sai->sai_flags = 0;
31948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sai->sai_length = sizeof(struct sctp_adaptation_event);
31958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sai->sai_adaptation_ind = stcb->asoc.peers_adaptation;
31968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sai->sai_assoc_id = sctp_get_associd(stcb);
31978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_adaptation_event);
31998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_NEXT(m_notify) = NULL;
32008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* append to socket */
32028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
32030ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 0, 0, stcb->asoc.context, 0, 0, 0,
32040ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 m_notify);
32058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
32068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no memory */
32078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
32088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
32098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->length = SCTP_BUF_LEN(m_notify);
32118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->spec_flags = M_NOTIFICATION;
32128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* not that we need this */
32138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->tail_mbuf = m_notify;
32148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_add_to_readq(stcb->sctp_ep, stcb,
32158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    control,
32168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
32178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
32188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* This always must be called with the read-queue LOCKED in the INP */
32208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
32218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
32228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					uint32_t val, int so_locked
32238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
32248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                             SCTP_UNUSED
32258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
32268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                                        )
32278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
32288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_notify;
32298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_pdapi_event *pdapi;
32308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
32318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockbuf *sb;
32328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3233b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if ((stcb == NULL) ||
3234b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_PDAPIEVNT)) {
32358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* event not enabled */
32368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
32378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) {
32398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
32408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3241000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
324268beeca578347438d9c434680197647ed551935ft	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 0, M_NOWAIT, 1, MT_DATA);
32438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_notify == NULL)
32448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no space left */
32458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
32468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = 0;
32478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pdapi = mtod(m_notify, struct sctp_pdapi_event *);
3248f496fe99adbad377f85add3a45e17f21a4702b41t	memset(pdapi, 0, sizeof(struct sctp_pdapi_event));
32498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT;
32508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pdapi->pdapi_flags = 0;
32518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pdapi->pdapi_length = sizeof(struct sctp_pdapi_event);
32528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pdapi->pdapi_indication = error;
32538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pdapi->pdapi_stream = (val >> 16);
32548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pdapi->pdapi_seq = (val & 0x0000ffff);
32558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	pdapi->pdapi_assoc_id = sctp_get_associd(stcb);
32568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_pdapi_event);
32588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_NEXT(m_notify) = NULL;
32598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
32600ac02f34d6041cd0018437596a5a9a94685e6919tuexen					 0, 0, stcb->asoc.context, 0, 0, 0,
32618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 m_notify);
32628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
32638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no memory */
32648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
32658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
32668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->spec_flags = M_NOTIFICATION;
32688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->length = SCTP_BUF_LEN(m_notify);
32698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* not that we need this */
32708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->tail_mbuf = m_notify;
32718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->held_length = 0;
32728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->length = 0;
32738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sb = &stcb->sctp_socket->so_rcv;
32748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
32758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify));
32768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_sballoc(stcb, sb, m_notify);
32788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
32798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
32808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&control->length, SCTP_BUF_LEN(m_notify));
32828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->end_added = 1;
32838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.control_pdapi)
32848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_INSERT_AFTER(&stcb->sctp_ep->read_queue, stcb->asoc.control_pdapi,  control, next);
32858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else {
32868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we really should not see this case */
32878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_INSERT_TAIL(&stcb->sctp_ep->read_queue, control, next);
32888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep && stcb->sctp_socket) {
32908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* This should always be the case */
32910612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
32928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct socket *so;
32938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so = SCTP_INP_SO(stcb->sctp_ep);
32958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!so_locked) {
32968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_add_int(&stcb->asoc.refcnt, 1);
32978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
32988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_LOCK(so, 1);
32998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_LOCK(stcb);
33008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_subtract_int(&stcb->asoc.refcnt, 1);
33018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
33028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_SOCKET_UNLOCK(so, 1);
33038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
33048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
33058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
33078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
33080612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
33098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!so_locked) {
33108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_UNLOCK(so, 1);
33118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
33138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
33158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
33178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_notify_shutdown_event(struct sctp_tcb *stcb)
33188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
33198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_notify;
33208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_shutdown_event *sse;
33218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
33228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
33248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * For TCP model AND UDP connected sockets we will send an error up
33258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * when an SHUTDOWN completes
33268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
33278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
33288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
33298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* mark socket closed for read/write and wakeup! */
33300612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
33318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct socket *so;
3332000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
33338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so = SCTP_INP_SO(stcb->sctp_ep);
33348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
33358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
33368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_LOCK(so, 1);
33378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
33388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
33398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
33408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_UNLOCK(so, 1);
33418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
3342000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		}
33438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
33448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		socantsendmore(stcb->sctp_socket);
33450612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
33468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_UNLOCK(so, 1);
33478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
33488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)) {
33508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* event not enabled */
33518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
33528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3353000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
335468beeca578347438d9c434680197647ed551935ft	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_event), 0, M_NOWAIT, 1, MT_DATA);
33558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_notify == NULL)
33568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no space left */
33578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
33588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sse = mtod(m_notify, struct sctp_shutdown_event *);
3359f496fe99adbad377f85add3a45e17f21a4702b41t	memset(sse, 0, sizeof(struct sctp_shutdown_event));
33608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sse->sse_type = SCTP_SHUTDOWN_EVENT;
33618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sse->sse_flags = 0;
33628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sse->sse_length = sizeof(struct sctp_shutdown_event);
33638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sse->sse_assoc_id = sctp_get_associd(stcb);
33648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_shutdown_event);
33668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_NEXT(m_notify) = NULL;
33678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* append to socket */
33698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
33700ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 0, 0, stcb->asoc.context, 0, 0, 0,
33710ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 m_notify);
33728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
33738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no memory */
33748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
33758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
33768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->spec_flags = M_NOTIFICATION;
33788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->length = SCTP_BUF_LEN(m_notify);
33798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* not that we need this */
33808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->tail_mbuf = m_notify;
33818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_add_to_readq(stcb->sctp_ep, stcb,
33828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    control,
33838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
33848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
33858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
33878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_notify_sender_dry_event(struct sctp_tcb *stcb,
33888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                             int so_locked
33898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
33908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                             SCTP_UNUSED
33918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
33928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                             )
33938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
33948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_notify;
33958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_sender_dry_event *event;
33968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
33978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3398b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	if ((stcb == NULL) ||
3399b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DRYEVNT)) {
34008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* event not enabled */
34018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
34028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3403000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
340468beeca578347438d9c434680197647ed551935ft	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_sender_dry_event), 0, M_NOWAIT, 1, MT_DATA);
34058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_notify == NULL) {
34068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no space left */
34078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
34088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
34098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = 0;
34108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	event = mtod(m_notify, struct sctp_sender_dry_event *);
3411f496fe99adbad377f85add3a45e17f21a4702b41t	memset(event, 0, sizeof(struct sctp_sender_dry_event));
34128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	event->sender_dry_type = SCTP_SENDER_DRY_EVENT;
34138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	event->sender_dry_flags = 0;
34148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	event->sender_dry_length = sizeof(struct sctp_sender_dry_event);
34158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	event->sender_dry_assoc_id = sctp_get_associd(stcb);
34168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_sender_dry_event);
34188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_NEXT(m_notify) = NULL;
34198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* append to socket */
34218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
34220ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 0, 0, stcb->asoc.context, 0, 0, 0,
34230ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 m_notify);
34248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
34258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no memory */
34268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
34278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
34288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
34298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->length = SCTP_BUF_LEN(m_notify);
34308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->spec_flags = M_NOTIFICATION;
34318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* not that we need this */
34328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->tail_mbuf = m_notify;
34338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_add_to_readq(stcb->sctp_ep, stcb, control,
34348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                  &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked);
34358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
34368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3438c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexenvoid
3439c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexensctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t numberout, int flag)
34408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
34418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_notify;
34428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
3443c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	struct sctp_stream_change_event *stradd;
34448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34458a29867a84996e7ee31a638ab89256ca7d2dc9b0tuexen	if ((stcb == NULL) ||
34468a29867a84996e7ee31a638ab89256ca7d2dc9b0tuexen	    (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) {
34478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* event not enabled */
34488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
34498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3450c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	if ((stcb->asoc.peer_req_out) && flag) {
3451c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		/* Peer made the request, don't tell the local user */
3452c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		stcb->asoc.peer_req_out = 0;
3453c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		return;
3454c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	}
3455c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	stcb->asoc.peer_req_out = 0;
3456f496fe99adbad377f85add3a45e17f21a4702b41t	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_stream_change_event), 0, M_NOWAIT, 1, MT_DATA);
34578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_notify == NULL)
34588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no space left */
34598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
34608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = 0;
3461c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	stradd = mtod(m_notify, struct sctp_stream_change_event *);
3462f496fe99adbad377f85add3a45e17f21a4702b41t	memset(stradd, 0, sizeof(struct sctp_stream_change_event));
3463c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	stradd->strchange_type = SCTP_STREAM_CHANGE_EVENT;
3464c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	stradd->strchange_flags = flag;
3465f496fe99adbad377f85add3a45e17f21a4702b41t	stradd->strchange_length = sizeof(struct sctp_stream_change_event);
3466c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	stradd->strchange_assoc_id = sctp_get_associd(stcb);
3467c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	stradd->strchange_instrms = numberin;
3468c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	stradd->strchange_outstrms = numberout;
3469f496fe99adbad377f85add3a45e17f21a4702b41t	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_stream_change_event);
3470c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	SCTP_BUF_NEXT(m_notify) = NULL;
3471c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
3472c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		/* no space */
3473c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		sctp_m_freem(m_notify);
3474c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		return;
3475c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	}
3476c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	/* append to socket */
3477c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
3478c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	                                 0, 0, stcb->asoc.context, 0, 0, 0,
3479c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	                                 m_notify);
3480c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	if (control == NULL) {
3481c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		/* no memory */
3482c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		sctp_m_freem(m_notify);
3483c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		return;
3484c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	}
3485c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	control->spec_flags = M_NOTIFICATION;
3486c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	control->length = SCTP_BUF_LEN(m_notify);
3487c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	/* not that we need this */
3488c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	control->tail_mbuf = m_notify;
3489c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	sctp_add_to_readq(stcb->sctp_ep, stcb,
3490c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	    control,
3491c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
3492c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen}
3493c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen
3494c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexenvoid
3495c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexensctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32_t recv_tsn, int flag)
3496c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen{
3497c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	struct mbuf *m_notify;
3498c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	struct sctp_queued_to_read *control;
3499c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	struct sctp_assoc_reset_event *strasoc;
35008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35018a29867a84996e7ee31a638ab89256ca7d2dc9b0tuexen	if ((stcb == NULL) ||
35028a29867a84996e7ee31a638ab89256ca7d2dc9b0tuexen	    (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) {
3503c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		/* event not enabled */
3504c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		return;
3505c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	}
3506f496fe99adbad377f85add3a45e17f21a4702b41t	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_reset_event), 0, M_NOWAIT, 1, MT_DATA);
3507c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	if (m_notify == NULL)
3508c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		/* no space left */
3509c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen		return;
3510c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	SCTP_BUF_LEN(m_notify) = 0;
3511c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	strasoc = mtod(m_notify, struct sctp_assoc_reset_event  *);
3512f496fe99adbad377f85add3a45e17f21a4702b41t	memset(strasoc, 0, sizeof(struct sctp_assoc_reset_event));
3513c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	strasoc->assocreset_type = SCTP_ASSOC_RESET_EVENT;
3514c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	strasoc->assocreset_flags = flag;
3515f496fe99adbad377f85add3a45e17f21a4702b41t	strasoc->assocreset_length = sizeof(struct sctp_assoc_reset_event);
3516c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	strasoc->assocreset_assoc_id= sctp_get_associd(stcb);
3517c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	strasoc->assocreset_local_tsn = sending_tsn;
3518c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	strasoc->assocreset_remote_tsn = recv_tsn;
3519f496fe99adbad377f85add3a45e17f21a4702b41t	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_assoc_reset_event);
35208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_NEXT(m_notify) = NULL;
35218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
35228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no space */
35238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
35248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
35258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* append to socket */
35278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
35280ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 0, 0, stcb->asoc.context, 0, 0, 0,
35290ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 m_notify);
35308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
35318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no memory */
35328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
35338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
35348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->spec_flags = M_NOTIFICATION;
35368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->length = SCTP_BUF_LEN(m_notify);
35378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* not that we need this */
35388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->tail_mbuf = m_notify;
35398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_add_to_readq(stcb->sctp_ep, stcb,
35408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    control,
35418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
35428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
35438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3545c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen
35468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
35478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_notify_stream_reset(struct sctp_tcb *stcb,
35488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int number_entries, uint16_t * list, int flag)
35498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
35508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_notify;
35518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control;
35528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_stream_reset_event *strreset;
35538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int len;
3554a067b45afc762b4afd08065d3f61ee251f53f018tuexen
35558a29867a84996e7ee31a638ab89256ca7d2dc9b0tuexen	if ((stcb == NULL) ||
35568a29867a84996e7ee31a638ab89256ca7d2dc9b0tuexen	    (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT))) {
35578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* event not enabled */
35588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
35598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3560000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
356168beeca578347438d9c434680197647ed551935ft	m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
35628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_notify == NULL)
35638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no space left */
35648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
35658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = 0;
35668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t));
35678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (len > M_TRAILINGSPACE(m_notify)) {
35688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* never enough room */
35698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
35708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
35718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strreset = mtod(m_notify, struct sctp_stream_reset_event *);
3573f496fe99adbad377f85add3a45e17f21a4702b41t	memset(strreset, 0, len);
35748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strreset->strreset_type = SCTP_STREAM_RESET_EVENT;
3575c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen	strreset->strreset_flags = flag;
35768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strreset->strreset_length = len;
35778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	strreset->strreset_assoc_id = sctp_get_associd(stcb);
35788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (number_entries) {
35798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int i;
35808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
35818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		for (i = 0; i < number_entries; i++) {
3582c2352ecab1d9ed208f1d33f5dc0088689b2f210etuexen			strreset->strreset_stream_list[i] = ntohs(list[i]);
35838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_notify) = len;
35868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_NEXT(m_notify) = NULL;
35878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
35888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no space */
35898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
35908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
35918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* append to socket */
35938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
35940ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 0, 0, stcb->asoc.context, 0, 0, 0,
35950ac02f34d6041cd0018437596a5a9a94685e6919tuexen	                                 m_notify);
35968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
35978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no memory */
35988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_notify);
35998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
36008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
36018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->spec_flags = M_NOTIFICATION;
36028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->length = SCTP_BUF_LEN(m_notify);
36038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* not that we need this */
36048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->tail_mbuf = m_notify;
36058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_add_to_readq(stcb->sctp_ep, stcb,
36068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                  control,
36078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                  &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
36088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
36098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
36108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
361147674b651417d493ff4e0318113fd7beeef119dbtuexenstatic void
361247674b651417d493ff4e0318113fd7beeef119dbtuexensctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_error_chunk *chunk)
361347674b651417d493ff4e0318113fd7beeef119dbtuexen{
361447674b651417d493ff4e0318113fd7beeef119dbtuexen	struct mbuf *m_notify;
361547674b651417d493ff4e0318113fd7beeef119dbtuexen	struct sctp_remote_error *sre;
361647674b651417d493ff4e0318113fd7beeef119dbtuexen	struct sctp_queued_to_read *control;
361747674b651417d493ff4e0318113fd7beeef119dbtuexen	size_t notif_len, chunk_len;
361847674b651417d493ff4e0318113fd7beeef119dbtuexen
361947674b651417d493ff4e0318113fd7beeef119dbtuexen	if ((stcb == NULL) ||
362047674b651417d493ff4e0318113fd7beeef119dbtuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) {
362147674b651417d493ff4e0318113fd7beeef119dbtuexen		return;
362247674b651417d493ff4e0318113fd7beeef119dbtuexen	}
362347674b651417d493ff4e0318113fd7beeef119dbtuexen	if (chunk != NULL) {
36245310a647a74c51d125d106f350ff224bb017b0a5t		chunk_len = ntohs(chunk->ch.chunk_length);
362547674b651417d493ff4e0318113fd7beeef119dbtuexen	} else {
362647674b651417d493ff4e0318113fd7beeef119dbtuexen		chunk_len = 0;
362747674b651417d493ff4e0318113fd7beeef119dbtuexen	}
362847674b651417d493ff4e0318113fd7beeef119dbtuexen	notif_len = sizeof(struct sctp_remote_error) + chunk_len;
362968beeca578347438d9c434680197647ed551935ft	m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
363047674b651417d493ff4e0318113fd7beeef119dbtuexen	if (m_notify == NULL) {
363147674b651417d493ff4e0318113fd7beeef119dbtuexen		/* Retry with smaller value. */
363247674b651417d493ff4e0318113fd7beeef119dbtuexen		notif_len = sizeof(struct sctp_remote_error);
363368beeca578347438d9c434680197647ed551935ft		m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_NOWAIT, 1, MT_DATA);
363447674b651417d493ff4e0318113fd7beeef119dbtuexen		if (m_notify == NULL) {
363547674b651417d493ff4e0318113fd7beeef119dbtuexen			return;
363647674b651417d493ff4e0318113fd7beeef119dbtuexen		}
363747674b651417d493ff4e0318113fd7beeef119dbtuexen	}
363847674b651417d493ff4e0318113fd7beeef119dbtuexen	SCTP_BUF_NEXT(m_notify) = NULL;
363947674b651417d493ff4e0318113fd7beeef119dbtuexen	sre = mtod(m_notify, struct sctp_remote_error *);
36401fb710c36aa9c19e470ebc5c5974879871f7e221t	memset(sre, 0, notif_len);
364147674b651417d493ff4e0318113fd7beeef119dbtuexen	sre->sre_type = SCTP_REMOTE_ERROR;
364247674b651417d493ff4e0318113fd7beeef119dbtuexen	sre->sre_flags = 0;
364347674b651417d493ff4e0318113fd7beeef119dbtuexen	sre->sre_length = sizeof(struct sctp_remote_error);
364447674b651417d493ff4e0318113fd7beeef119dbtuexen	sre->sre_error = error;
364547674b651417d493ff4e0318113fd7beeef119dbtuexen	sre->sre_assoc_id = sctp_get_associd(stcb);
364647674b651417d493ff4e0318113fd7beeef119dbtuexen	if (notif_len > sizeof(struct sctp_remote_error)) {
364747674b651417d493ff4e0318113fd7beeef119dbtuexen		memcpy(sre->sre_data, chunk, chunk_len);
364847674b651417d493ff4e0318113fd7beeef119dbtuexen		sre->sre_length += chunk_len;
364947674b651417d493ff4e0318113fd7beeef119dbtuexen	}
365047674b651417d493ff4e0318113fd7beeef119dbtuexen	SCTP_BUF_LEN(m_notify) = sre->sre_length;
365147674b651417d493ff4e0318113fd7beeef119dbtuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
365247674b651417d493ff4e0318113fd7beeef119dbtuexen	                                 0, 0, stcb->asoc.context, 0, 0, 0,
365347674b651417d493ff4e0318113fd7beeef119dbtuexen	                                 m_notify);
365447674b651417d493ff4e0318113fd7beeef119dbtuexen	if (control != NULL) {
365547674b651417d493ff4e0318113fd7beeef119dbtuexen		control->length = SCTP_BUF_LEN(m_notify);
365647674b651417d493ff4e0318113fd7beeef119dbtuexen		/* not that we need this */
365747674b651417d493ff4e0318113fd7beeef119dbtuexen		control->tail_mbuf = m_notify;
365847674b651417d493ff4e0318113fd7beeef119dbtuexen		control->spec_flags = M_NOTIFICATION;
365947674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_add_to_readq(stcb->sctp_ep, stcb,
366047674b651417d493ff4e0318113fd7beeef119dbtuexen		                  control,
366147674b651417d493ff4e0318113fd7beeef119dbtuexen		                  &stcb->sctp_socket->so_rcv, 1,
366247674b651417d493ff4e0318113fd7beeef119dbtuexen				  SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
366347674b651417d493ff4e0318113fd7beeef119dbtuexen	} else {
366447674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_m_freem(m_notify);
366547674b651417d493ff4e0318113fd7beeef119dbtuexen	}
366647674b651417d493ff4e0318113fd7beeef119dbtuexen}
366747674b651417d493ff4e0318113fd7beeef119dbtuexen
366847674b651417d493ff4e0318113fd7beeef119dbtuexen
36698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
36708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
36718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint32_t error, void *data, int so_locked
36728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
36738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    SCTP_UNUSED
36748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
36758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    )
36768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
36778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb == NULL) ||
36788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
36798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
36808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
36818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* If the socket is gone we are out of here */
36828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
36838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
36848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__)
36858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_socket->so_rcv.sb_state & SBS_CANTRCVMORE) {
36868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
36878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_socket->so_state & SS_CANTRCVMORE) {
36888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
36898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
36908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
36918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
36928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (so_locked) {
36938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep));
36948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
36958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep));
36968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
36978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3698f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t	if ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) ||
3699f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t	    (stcb->asoc.state &  SCTP_STATE_COOKIE_ECHOED)) {
37008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((notification == SCTP_NOTIFY_INTERFACE_DOWN) ||
37018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (notification == SCTP_NOTIFY_INTERFACE_UP) ||
37028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (notification == SCTP_NOTIFY_INTERFACE_CONFIRMED)) {
37038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Don't report these in front states */
37048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
37058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
37078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (notification) {
37088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_ASSOC_UP:
37098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.assoc_up_sent == 0) {
371047674b651417d493ff4e0318113fd7beeef119dbtuexen			sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, NULL, 0, so_locked);
37118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.assoc_up_sent = 1;
37128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent == 0)) {
37140ac02f34d6041cd0018437596a5a9a94685e6919tuexen			sctp_notify_adaptation_layer(stcb);
37158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3716fb3816eaffe5878bb1286adb120fd160da178a05t		if (stcb->asoc.auth_supported == 0) {
37178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
3718f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t			                NULL, so_locked);
37198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
37218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_ASSOC_DOWN:
372247674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, 0, so_locked);
37230612043f643c9b26245564c05defca64d472060etuexen#if defined(__Userspace__)
37240ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen		if (stcb->sctp_ep->recv_callback) {
3725000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			if (stcb->sctp_socket) {
372673e265d74b8dddf404a3200cc2a4b593025158e7tuexen				union sctp_sockstore addr;
372773e265d74b8dddf404a3200cc2a4b593025158e7tuexen				struct sctp_rcvinfo rcv;
372873e265d74b8dddf404a3200cc2a4b593025158e7tuexen
372973e265d74b8dddf404a3200cc2a4b593025158e7tuexen				memset(&addr, 0, sizeof(union sctp_sockstore));
373073e265d74b8dddf404a3200cc2a4b593025158e7tuexen				memset(&rcv, 0, sizeof(struct sctp_rcvinfo));
37310ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				atomic_add_int(&stcb->asoc.refcnt, 1);
37320ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				SCTP_TCB_UNLOCK(stcb);
3733d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen				stcb->sctp_ep->recv_callback(stcb->sctp_socket, addr, NULL, 0, rcv, 0, stcb->sctp_ep->ulp_info);
37340ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				SCTP_TCB_LOCK(stcb);
37350ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				atomic_subtract_int(&stcb->asoc.refcnt, 1);
37360ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			}
373773c31e0d1075341a12dc84bd5a4c5ab479124f34tuexen		}
373873c31e0d1075341a12dc84bd5a4c5ab479124f34tuexen#endif
37398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
37408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_INTERFACE_DOWN:
37418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
37428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_nets *net;
37438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = (struct sctp_nets *)data;
37458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE,
37468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (struct sockaddr *)&net->ro._l_addr, error);
37478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
37488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_INTERFACE_UP:
37508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
37518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_nets *net;
37528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = (struct sctp_nets *)data;
37548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE,
37558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (struct sockaddr *)&net->ro._l_addr, error);
37568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
37578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_INTERFACE_CONFIRMED:
37598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
37608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_nets *net;
37618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net = (struct sctp_nets *)data;
37638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED,
37648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (struct sockaddr *)&net->ro._l_addr, error);
37658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
37668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_SPECIAL_SP_FAIL:
37688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_notify_send_failed2(stcb, error,
3769f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                         (struct sctp_stream_queue_pending *)data, so_locked);
37708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
377147674b651417d493ff4e0318113fd7beeef119dbtuexen	case SCTP_NOTIFY_SENT_DG_FAIL:
377247674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_notify_send_failed(stcb, 1, error,
37738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (struct sctp_tmit_chunk *)data, so_locked);
37748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
377547674b651417d493ff4e0318113fd7beeef119dbtuexen	case SCTP_NOTIFY_UNSENT_DG_FAIL:
377647674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_notify_send_failed(stcb, 0, error,
3777f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                        (struct sctp_tmit_chunk *)data, so_locked);
377847674b651417d493ff4e0318113fd7beeef119dbtuexen		break;
37798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION:
37808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
37818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint32_t val;
37828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			val = *((uint32_t *)data);
37838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
37848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_notify_partial_delivery_indication(stcb, error, val, so_locked);
37858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
37868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
378747674b651417d493ff4e0318113fd7beeef119dbtuexen	case SCTP_NOTIFY_ASSOC_LOC_ABORTED:
3788f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
3789f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		    ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) {
379047674b651417d493ff4e0318113fd7beeef119dbtuexen			sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 0, so_locked);
37918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
379247674b651417d493ff4e0318113fd7beeef119dbtuexen			sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 0, so_locked);
37938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
37948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
379547674b651417d493ff4e0318113fd7beeef119dbtuexen	case SCTP_NOTIFY_ASSOC_REM_ABORTED:
3796f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
3797f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		    ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) {
379847674b651417d493ff4e0318113fd7beeef119dbtuexen			sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 1, so_locked);
379947674b651417d493ff4e0318113fd7beeef119dbtuexen		} else {
380047674b651417d493ff4e0318113fd7beeef119dbtuexen			sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 1, so_locked);
380147674b651417d493ff4e0318113fd7beeef119dbtuexen		}
38028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_ASSOC_RESTART:
380447674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, so_locked);
3805fb3816eaffe5878bb1286adb120fd160da178a05t		if (stcb->asoc.auth_supported == 0) {
38068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
3807f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t			                NULL, so_locked);
38088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
38098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_STR_RESET_SEND:
38113deb01b1bdee799175510a3e63155882311686f7tuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_OUTGOING_SSN);
38128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_STR_RESET_RECV:
38143deb01b1bdee799175510a3e63155882311686f7tuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_INCOMING);
38158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_STR_RESET_FAILED_OUT:
3817000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
3818f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                         (SCTP_STREAM_RESET_OUTGOING_SSN|SCTP_STREAM_RESET_FAILED));
38198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
3820cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen	case SCTP_NOTIFY_STR_RESET_DENIED_OUT:
3821cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
3822cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen		                         (SCTP_STREAM_RESET_OUTGOING_SSN|SCTP_STREAM_RESET_DENIED));
3823cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen		break;
38248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_STR_RESET_FAILED_IN:
3825000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
3826f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                         (SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_FAILED));
38278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
3828cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen	case SCTP_NOTIFY_STR_RESET_DENIED_IN:
3829cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
3830cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen		                         (SCTP_STREAM_RESET_INCOMING|SCTP_STREAM_RESET_DENIED));
3831cdadd9c6abe95c90cef647c7391c5152a3858eb4tuexen		break;
38328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_ASCONF_ADD_IP:
38338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data,
38348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    error);
38358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_ASCONF_DELETE_IP:
38378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data,
3838f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                             error);
38398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_ASCONF_SET_PRIMARY:
38418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data,
3842f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                             error);
38438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_PEER_SHUTDOWN:
38458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_notify_shutdown_event(stcb);
38468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_AUTH_NEW_KEY:
384808f3696ad42fc22082922592e23297cfaf790dcctuexen		sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY, error,
3849f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                           (uint16_t)(uintptr_t)data,
3850f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                           so_locked);
38518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_AUTH_FREE_KEY:
38538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_notify_authentication(stcb, SCTP_AUTH_FREE_KEY, error,
3854f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                           (uint16_t)(uintptr_t)data,
3855f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                           so_locked);
38568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_NO_PEER_AUTH:
38588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_notify_authentication(stcb, SCTP_AUTH_NO_AUTH, error,
3859f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                           (uint16_t)(uintptr_t)data,
3860f16a3dca2395cee32963ab65a1fecbeaeccaa1b5t		                           so_locked);
38618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_NOTIFY_SENDER_DRY:
38638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_notify_sender_dry_event(stcb, so_locked);
38648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
386547674b651417d493ff4e0318113fd7beeef119dbtuexen	case SCTP_NOTIFY_REMOTE_ERROR:
386647674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_notify_remote_error(stcb, error, data);
386747674b651417d493ff4e0318113fd7beeef119dbtuexen		break;
38688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
38698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_UTIL1, "%s: unknown notification %xh (%u)\n",
38708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			__FUNCTION__, notification, notification);
38718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
38728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}			/* end switch */
38738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
38748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
387647674b651417d493ff4e0318113fd7beeef119dbtuexensctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked
38778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
38788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    SCTP_UNUSED
38798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
38808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    )
38818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
38828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
38838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_stream_out *outs;
38848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk, *nchk;
38858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_stream_queue_pending *sp, *nsp;
38868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
38878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
38888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
38898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
38908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
38918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
38928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
38938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* already being freed */
38948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
38958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
38968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
38978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (so_locked) {
38988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep));
38998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
39008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep));
39018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
39028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
39038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
39048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
39058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (asoc->state & SCTP_STATE_CLOSED_SOCKET)) {
39068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
39078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
39088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now through all the gunk freeing chunks */
39098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (holds_lock == 0) {
39108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_SEND_LOCK(stcb);
39118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
39128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sent queue SHOULD be empty */
39138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
39148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
39158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->sent_queue_cnt--;
391660db5740d3bcc26fd4ebc19b6b0652506994fd14t		if (chk->sent != SCTP_DATAGRAM_NR_ACKED) {
3917446be8e8a472f6e688885674d2430118fc4be5d7t			if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
3918446be8e8a472f6e688885674d2430118fc4be5d7t				asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
3919446be8e8a472f6e688885674d2430118fc4be5d7t#ifdef INVARIANTS
3920446be8e8a472f6e688885674d2430118fc4be5d7t			} else {
3921446be8e8a472f6e688885674d2430118fc4be5d7t				panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
3922446be8e8a472f6e688885674d2430118fc4be5d7t#endif
3923446be8e8a472f6e688885674d2430118fc4be5d7t			}
3924446be8e8a472f6e688885674d2430118fc4be5d7t		}
39258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->data != NULL) {
39268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_bufspace(stcb, asoc, chk, 1);
392747674b651417d493ff4e0318113fd7beeef119dbtuexen			sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb,
392847674b651417d493ff4e0318113fd7beeef119dbtuexen			                error, chk, so_locked);
39298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chk->data) {
39308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(chk->data);
39318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				chk->data = NULL;
39328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
39338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
39348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_a_chunk(stcb, chk, so_locked);
39358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*sa_ignore FREED_MEMORY*/
39368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
39378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* pending send queue SHOULD be empty */
39388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
39398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
39408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->send_queue_cnt--;
3941446be8e8a472f6e688885674d2430118fc4be5d7t		if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
3942446be8e8a472f6e688885674d2430118fc4be5d7t			asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
3943446be8e8a472f6e688885674d2430118fc4be5d7t#ifdef INVARIANTS
3944446be8e8a472f6e688885674d2430118fc4be5d7t		} else {
3945446be8e8a472f6e688885674d2430118fc4be5d7t			panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
3946446be8e8a472f6e688885674d2430118fc4be5d7t#endif
3947446be8e8a472f6e688885674d2430118fc4be5d7t		}
39488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->data != NULL) {
39498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_bufspace(stcb, asoc, chk, 1);
395047674b651417d493ff4e0318113fd7beeef119dbtuexen			sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb,
395147674b651417d493ff4e0318113fd7beeef119dbtuexen			                error, chk, so_locked);
39528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chk->data) {
39538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(chk->data);
39548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				chk->data = NULL;
39558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
39568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
39578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_a_chunk(stcb, chk, so_locked);
39588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*sa_ignore FREED_MEMORY*/
39598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
39608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < asoc->streamoutcnt; i++) {
39618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* For each stream */
39628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		outs = &asoc->strmout[i];
39638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* clean up any sends there */
39648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->locked_on_sending = NULL;
39658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
39668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asoc->stream_queue_cnt--;
39678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&outs->outqueue, sp, next);
39688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_spbufspace(stcb, asoc, sp);
39698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sp->data) {
39708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb,
397147674b651417d493ff4e0318113fd7beeef119dbtuexen						error, (void *)sp, so_locked);
39728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sp->data) {
39738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_m_freem(sp->data);
39748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sp->data = NULL;
3975647dfd814628db0cc7cbfecaf4acb44f997eadb2tuexen					sp->tail_mbuf = NULL;
3976647dfd814628db0cc7cbfecaf4acb44f997eadb2tuexen					sp->length = 0;
39778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
39788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
39798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sp->net) {
39808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_remote_addr(sp->net);
39818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sp->net = NULL;
39828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
39838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Free the chunk */
39848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_a_strmoq(stcb, sp, so_locked);
39858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*sa_ignore FREED_MEMORY*/
39868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
39878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
39888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
39898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (holds_lock == 0) {
39908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_SEND_UNLOCK(stcb);
39918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
39928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
39938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
39948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
399547674b651417d493ff4e0318113fd7beeef119dbtuexensctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t error,
399647674b651417d493ff4e0318113fd7beeef119dbtuexen			struct sctp_abort_chunk *abort, int so_locked
39978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
39988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    SCTP_UNUSED
39998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
40008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    )
40018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
40028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
40038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
40048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
40068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (so_locked) {
40078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep));
40088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
40098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep));
40108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
40128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
40138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
40148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
40158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED;
40168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
40188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
40198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
40208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
40218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Tell them we lost the asoc */
402347674b651417d493ff4e0318113fd7beeef119dbtuexen	sctp_report_all_outbound(stcb, error, 1, so_locked);
402447674b651417d493ff4e0318113fd7beeef119dbtuexen	if (from_peer) {
402547674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked);
402647674b651417d493ff4e0318113fd7beeef119dbtuexen	} else {
402747674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_LOC_ABORTED, stcb, error, abort, so_locked);
402847674b651417d493ff4e0318113fd7beeef119dbtuexen	}
40298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
40308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
40318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
40328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
4033e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen                       struct mbuf *m, int iphlen,
4034e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen                       struct sockaddr *src, struct sockaddr *dst,
4035e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen                       struct sctphdr *sh, struct mbuf *op_err,
40366a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#if defined(__FreeBSD__)
40376a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen                       uint8_t use_mflowid, uint32_t mflowid,
40386a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#endif
40396a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen                       uint32_t vrf_id, uint16_t port)
40408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
40418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vtag;
40420612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
40438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct socket *so;
40448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
40458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
40468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vtag = 0;
40478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb != NULL) {
40488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* We have a TCB to abort, send notification too */
40498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		vtag = stcb->asoc.peer_vtag;
405047674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
40518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* get the assoc vrf id and table id */
40528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		vrf_id = stcb->asoc.vrf_id;
40538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
40548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4055e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err,
40566a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#if defined(__FreeBSD__)
40576a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen	                use_mflowid, mflowid,
40586a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#endif
40596a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen	                vrf_id, port);
40608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb != NULL) {
40618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Ok, now lets free it */
40620612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
40638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so = SCTP_INP_SO(inp);
40648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
40658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
40668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_LOCK(so, 1);
40678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
40688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
40698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
40708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR_COUNTER32(sctps_aborted);
40718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
40728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
40738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_DECR_GAUGE32(sctps_currestab);
40748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
40758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_4);
40760612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
40778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_UNLOCK(so, 1);
40788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
40798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
40818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_ASOCLOG_OF_TSNS
40828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
40838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_print_out_track_log(struct sctp_tcb *stcb)
40848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
40858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef NOSIY_PRINTS
40868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
40878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_PRINTF("Last ep reason:%x\n", stcb->sctp_ep->last_abort_code);
40888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_PRINTF("IN bound TSN log-aaa\n");
40898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->asoc.tsn_in_at == 0) && (stcb->asoc.tsn_in_wrapped == 0)) {
40908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("None rcvd\n");
40918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto none_in;
40928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
40938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.tsn_in_wrapped) {
4094b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		for (i = stcb->asoc.tsn_in_at; i < SCTP_TSN_LOG_SIZE; i++) {
40958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
40968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.in_tsnlog[i].tsn,
40978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.in_tsnlog[i].strm,
40988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.in_tsnlog[i].seq,
40998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.in_tsnlog[i].flgs,
41008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.in_tsnlog[i].sz);
41018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
41028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.tsn_in_at) {
4104b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		for (i = 0; i < stcb->asoc.tsn_in_at; i++) {
41058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
41068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.in_tsnlog[i].tsn,
41078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.in_tsnlog[i].strm,
41088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.in_tsnlog[i].seq,
41098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.in_tsnlog[i].flgs,
41108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.in_tsnlog[i].sz);
41118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
41128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen none_in:
41148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_PRINTF("OUT bound TSN log-aaa\n");
41158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->asoc.tsn_out_at == 0) &&
41168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->asoc.tsn_out_wrapped == 0)) {
41178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("None sent\n");
41188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.tsn_out_wrapped) {
4120b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		for (i = stcb->asoc.tsn_out_at; i < SCTP_TSN_LOG_SIZE; i++) {
41218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
41228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.out_tsnlog[i].tsn,
41238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.out_tsnlog[i].strm,
41248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.out_tsnlog[i].seq,
41258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.out_tsnlog[i].flgs,
41268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.out_tsnlog[i].sz);
41278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
41288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.tsn_out_at) {
4130b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		for (i = 0; i < stcb->asoc.tsn_out_at; i++) {
41318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
41328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.out_tsnlog[i].tsn,
41338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.out_tsnlog[i].strm,
41348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.out_tsnlog[i].seq,
41358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.out_tsnlog[i].flgs,
41368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb->asoc.out_tsnlog[i].sz);
41378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
41388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
41408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
41418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
41428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
41448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
414547674b651417d493ff4e0318113fd7beeef119dbtuexen                          struct mbuf *op_err,
414647674b651417d493ff4e0318113fd7beeef119dbtuexen                          int so_locked
41478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
41488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                          SCTP_UNUSED
41498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
41508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen)
41518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
41520612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
41538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct socket *so;
41548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
41558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
41560612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
41578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	so = SCTP_INP_SO(inp);
41588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
41598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
41608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (so_locked) {
41618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_lock_assert(SCTP_INP_SO(inp));
41628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
41638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_unlock_assert(SCTP_INP_SO(inp));
41648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
41668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
41678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Got to have a TCB */
41688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
41696c1813d4ac9e00b805e1a400f004f2994b2297e5t			if (LIST_EMPTY(&inp->sctp_asoc_list)) {
41708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
41718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!so_locked) {
41728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_SOCKET_LOCK(so, 1);
41738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
41748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
41758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
41768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_CALLED_DIRECTLY_NOCMPSET);
41778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
41788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!so_locked) {
41798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_SOCKET_UNLOCK(so, 1);
41808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
41818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
41828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
41838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
41848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
41858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
41868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
41878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* notify the ulp */
418947674b651417d493ff4e0318113fd7beeef119dbtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
419047674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_abort_notification(stcb, 0, 0, NULL, so_locked);
419147674b651417d493ff4e0318113fd7beeef119dbtuexen	}
41928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* notify the peer */
41938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_send_abort_tcb(stcb, op_err, so_locked);
41948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_STAT_INCR_COUNTER32(sctps_aborted);
41958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
41968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
41978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_DECR_GAUGE32(sctps_currestab);
41988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
41998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now free the asoc */
42008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_ASOCLOG_OF_TSNS
42018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_print_out_track_log(stcb);
42028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
42030612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
42048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!so_locked) {
42058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
42068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
42078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_LOCK(so, 1);
42088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
42098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
42108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
42118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
42128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL+SCTP_LOC_5);
42130612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
42148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!so_locked) {
42158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_SOCKET_UNLOCK(so, 1);
42168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
42178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
42188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
42198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
42208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
4221e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
4222e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen                 struct sockaddr *src, struct sockaddr *dst,
4223e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen                 struct sctphdr *sh, struct sctp_inpcb *inp,
42248f9e45fea288542b24a6bda01269c6fc184d991at                 struct mbuf *cause,
42256a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#if defined(__FreeBSD__)
42266a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen                 uint8_t use_mflowid, uint32_t mflowid,
42276a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#endif
42286a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen                 uint32_t vrf_id, uint16_t port)
42298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
42308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_chunkhdr *ch, chunk_buf;
42318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	unsigned int chk_length;
423223273859c39742f09cc5ec7c9bf32ff225661e82tuexen	int contains_init_chunk;
42338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
42348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_STAT_INCR_COUNTER32(sctps_outoftheblue);
42358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Generate a TO address for future reference */
42368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
42376c1813d4ac9e00b805e1a400f004f2994b2297e5t		if (LIST_EMPTY(&inp->sctp_asoc_list)) {
42388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
42398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_LOCK(SCTP_INP_SO(inp), 1);
42408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
42418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
42428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_CALLED_DIRECTLY_NOCMPSET);
42438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
42448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_UNLOCK(SCTP_INP_SO(inp), 1);
42458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
42468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
424823273859c39742f09cc5ec7c9bf32ff225661e82tuexen	contains_init_chunk = 0;
42498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
42508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sizeof(*ch), (uint8_t *) & chunk_buf);
42518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (ch != NULL) {
42528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk_length = ntohs(ch->chunk_length);
42538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk_length < sizeof(*ch)) {
42548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* break to abort land */
42558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
42568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (ch->chunk_type) {
425823273859c39742f09cc5ec7c9bf32ff225661e82tuexen		case SCTP_INIT:
425923273859c39742f09cc5ec7c9bf32ff225661e82tuexen			contains_init_chunk = 1;
426023273859c39742f09cc5ec7c9bf32ff225661e82tuexen			break;
42618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_PACKET_DROPPED:
42628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* we don't respond to pkt-dropped */
42638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
42648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ABORT_ASSOCIATION:
42658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* we don't respond with an ABORT to an ABORT */
42668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
42678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SHUTDOWN_COMPLETE:
42688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
42698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * we ignore it since we are not waiting for it and
42708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * peer is gone
42718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
42728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
42738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SHUTDOWN_ACK:
4274e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen			sctp_send_shutdown_complete2(src, dst, sh,
42756a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#if defined(__FreeBSD__)
42766a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen			                             use_mflowid, mflowid,
42776a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#endif
42786a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen			                             vrf_id, port);
42798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
42808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
42818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
42828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
42838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset += SCTP_SIZE32(chk_length);
42848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
42858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(*ch), (uint8_t *) & chunk_buf);
42868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
428723273859c39742f09cc5ec7c9bf32ff225661e82tuexen	if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
428823273859c39742f09cc5ec7c9bf32ff225661e82tuexen	    ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
428923273859c39742f09cc5ec7c9bf32ff225661e82tuexen	     (contains_init_chunk == 0))) {
42908f9e45fea288542b24a6bda01269c6fc184d991at		sctp_send_abort(m, iphlen, src, dst, sh, 0, cause,
42916a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#if defined(__FreeBSD__)
42926a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen		                use_mflowid, mflowid,
42936a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen#endif
42946a646d8ad7f26691125adaa3a40cac21fbc1d81ftuexen		                vrf_id, port);
429523273859c39742f09cc5ec7c9bf32ff225661e82tuexen	}
42968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
42978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
42988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
42998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * check the inbound datagram to make sure there is not an abort inside it,
43008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if there is return 1, else return 0.
43018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
43028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
43038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_is_there_an_abort_here(struct mbuf *m, int iphlen, uint32_t * vtagfill)
43048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
43058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_chunkhdr *ch;
43068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_init_chunk *init_chk, chunk_buf;
43078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int offset;
43088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	unsigned int chk_length;
43098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	offset = iphlen + sizeof(struct sctphdr);
43118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, sizeof(*ch),
43128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (uint8_t *) & chunk_buf);
43138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (ch != NULL) {
43148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		chk_length = ntohs(ch->chunk_length);
43158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk_length < sizeof(*ch)) {
43168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* packet is probably corrupt */
43178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
43188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
43198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we seem to be ok, is it an abort? */
43208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ch->chunk_type == SCTP_ABORT_ASSOCIATION) {
43218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* yep, tell them */
43228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
43238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
43248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ch->chunk_type == SCTP_INITIATION) {
43258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* need to update the Vtag */
43268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
43278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    offset, sizeof(*init_chk), (uint8_t *) & chunk_buf);
43288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (init_chk != NULL) {
43298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*vtagfill = ntohl(init_chk->init.initiate_tag);
43308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
43318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
43328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Nope, move to the next chunk */
43338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset += SCTP_SIZE32(chk_length);
43348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
43358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(*ch), (uint8_t *) & chunk_buf);
43368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
43378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
43388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
43398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
43418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * currently (2/02), ifa_addr embeds scope_id's and don't have sin6_scope_id
43428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * set (i.e. it's 0) so, create this function to compare link local scopes
43438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
43448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
43458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
43468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_is_same_scope(struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2)
43478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
43488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
43498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    /*__Userspace__ Returning 1 here always */
43508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
43518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE)
43528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in6 a, b;
43538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* save copies */
43558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	a = *addr1;
43568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	b = *addr2;
43578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (a.sin6_scope_id == 0)
43598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME
43608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sa6_recoverscope(&a)) {
43618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
43628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (in6_recoverscope(&a, &a.sin6_addr, NULL)) {
43638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* SCTP_KAME */
43648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* can't get scope, so can't match */
43658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
43668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
43678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (b.sin6_scope_id == 0)
43688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME
43698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sa6_recoverscope(&b)) {
43708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
43718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (in6_recoverscope(&b, &b.sin6_addr, NULL)) {
43728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif				/* SCTP_KAME */
43738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* can't get scope, so can't match */
43748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
43758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
43768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (a.sin6_scope_id != b.sin6_scope_id)
43778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
43788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
43798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (addr1->sin6_scope_id != addr2->sin6_scope_id)
43808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
43818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
43828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (1);
43848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
43858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
43868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE)
43878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
43888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns a sockaddr_in6 with embedded scope recovered and removed
43898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
43908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sockaddr_in6 *
43918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store)
43928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
43938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* check and strip embedded scope junk */
43948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (addr->sin6_family == AF_INET6) {
43958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) {
43968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (addr->sin6_scope_id == 0) {
43978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*store = *addr;
43988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME
43998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!sa6_recoverscope(store)) {
44008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
44018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (!in6_recoverscope(store, &store->sin6_addr,
44028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    NULL)) {
44038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_KAME */
44048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* use the recovered scope */
44058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					addr = store;
44068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
44078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
44088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* else, return the original "to" addr */
44098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				in6_clearscope(&addr->sin6_addr);
44108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
44118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
44128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (addr);
44148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
44158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
44168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
44178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
44198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * are the two addresses the same?  currently a "scopeless" check returns: 1
44208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if same, 0 if not
44218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
44228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
44238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2)
44248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
44258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* must be valid */
44278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sa1 == NULL || sa2 == NULL)
44288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
44298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* must be the same family */
44318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sa1->sa_family != sa2->sa_family)
44328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
4433000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
44348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (sa1->sa_family) {
44358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
44368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
44378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
44388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* IPv6 addresses */
44398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6_1, *sin6_2;
44408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6_1 = (struct sockaddr_in6 *)sa1;
44428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6_2 = (struct sockaddr_in6 *)sa2;
44438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (SCTP6_ARE_ADDR_EQUAL(sin6_1,
44448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sin6_2));
44458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
44478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
44488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
44498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
44508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* IPv4 addresses */
44518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sin_1, *sin_2;
44528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin_1 = (struct sockaddr_in *)sa1;
44548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin_2 = (struct sockaddr_in *)sa2;
44558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr);
44568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
445866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__)
445966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen	case AF_CONN:
446066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen	{
446166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		struct sockaddr_conn *sconn_1, *sconn_2;
446266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen
446366e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		sconn_1 = (struct sockaddr_conn *)sa1;
446466e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		sconn_2 = (struct sockaddr_conn *)sa2;
446566e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		return (sconn_1->sconn_addr == sconn_2->sconn_addr);
446666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen	}
446766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif
44688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
44698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we don't do these... */
44708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
44718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
44728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
44738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
44758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_print_address(struct sockaddr *sa)
44768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
44778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
4478c95692c15a6ca05efcd306c21fda119862cd66e0t#if defined(__FreeBSD__) && __FreeBSD_version >= 700000
44798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	char ip6buf[INET6_ADDRSTRLEN];
4480c95692c15a6ca05efcd306c21fda119862cd66e0t#endif
4481000a5bac556b28e74e4e98c540f66b1743e9312dtuexen#endif
4482000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
44838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (sa->sa_family) {
44848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
44858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
44868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
44878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6;
44888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
44898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6 = (struct sockaddr_in6 *)sa;
449023273859c39742f09cc5ec7c9bf32ff225661e82tuexen#if defined(__Userspace__)
449123273859c39742f09cc5ec7c9bf32ff225661e82tuexen		SCTP_PRINTF("IPv6 address: %x:%x:%x:%x:%x:%x:%x:%x:port:%d scope:%u\n",
44921a0a058c2e170a7749bd410bdeff477bbd75a615tuexen			    ntohs(sin6->sin6_addr.s6_addr16[0]),
44931a0a058c2e170a7749bd410bdeff477bbd75a615tuexen			    ntohs(sin6->sin6_addr.s6_addr16[1]),
44941a0a058c2e170a7749bd410bdeff477bbd75a615tuexen			    ntohs(sin6->sin6_addr.s6_addr16[2]),
44951a0a058c2e170a7749bd410bdeff477bbd75a615tuexen			    ntohs(sin6->sin6_addr.s6_addr16[3]),
44961a0a058c2e170a7749bd410bdeff477bbd75a615tuexen			    ntohs(sin6->sin6_addr.s6_addr16[4]),
44971a0a058c2e170a7749bd410bdeff477bbd75a615tuexen			    ntohs(sin6->sin6_addr.s6_addr16[5]),
44981a0a058c2e170a7749bd410bdeff477bbd75a615tuexen			    ntohs(sin6->sin6_addr.s6_addr16[6]),
44991a0a058c2e170a7749bd410bdeff477bbd75a615tuexen			    ntohs(sin6->sin6_addr.s6_addr16[7]),
45008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    ntohs(sin6->sin6_port),
45018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    sin6->sin6_scope_id);
45028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
45038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 700000
45049166fbec1be731c68a575747cbd94bd54fe4692dt		SCTP_PRINTF("IPv6 address: %s:port:%d scope:%u\n",
45058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    ip6_sprintf(ip6buf, &sin6->sin6_addr),
45069166fbec1be731c68a575747cbd94bd54fe4692dt			    ntohs(sin6->sin6_port),
45079166fbec1be731c68a575747cbd94bd54fe4692dt			    sin6->sin6_scope_id);
45088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
45099166fbec1be731c68a575747cbd94bd54fe4692dt		SCTP_PRINTF("IPv6 address: %s:port:%d scope:%u\n",
45108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    ip6_sprintf(&sin6->sin6_addr),
45118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    ntohs(sin6->sin6_port),
45128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    sin6->sin6_scope_id);
45138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
45149166fbec1be731c68a575747cbd94bd54fe4692dt#endif
45158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
45168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
45188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
45198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
45208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
45218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sin;
45228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		unsigned char *p;
45238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
45248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin = (struct sockaddr_in *)sa;
45258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		p = (unsigned char *)&sin->sin_addr;
45268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("IPv4 address: %u.%u.%u.%u:%d\n",
45278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
45288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
45298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
453166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__)
453266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen	case AF_CONN:
453366e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen	{
453466e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		struct sockaddr_conn *sconn;
453566e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen
453666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		sconn = (struct sockaddr_conn *)sa;
453766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		SCTP_PRINTF("AF_CONN address: %p\n", sconn->sconn_addr);
453866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		break;
453966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen	}
454066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif
45418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
45428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("?\n");
45438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
45448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
45468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
45478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
45488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
45498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_inpcb *new_inp,
45508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_tcb *stcb,
45518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int waitflags)
45528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
45538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
45548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * go through our old INP and pull off any control structures that
45558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * belong to stcb and move then to the new inp.
45568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
45578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct socket *old_so, *new_so;
45588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_queued_to_read *control, *nctl;
45598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_readhead tmp_queue;
45608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m;
45618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error = 0;
45628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
45638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	old_so = old_inp->sctp_socket;
45648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	new_so = new_inp->sctp_socket;
45658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INIT(&tmp_queue);
45668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version < 700000
45678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SOCKBUF_LOCK(&(old_so->so_rcv));
45688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
45698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__)
45708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = sblock(&old_so->so_rcv, waitflags);
45718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
45728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version < 700000
45738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SOCKBUF_UNLOCK(&(old_so->so_rcv));
45748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
45758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error) {
45768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Gak, can't get sblock, we have a problem.
45778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * data will be left stranded.. and we
45788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * don't dare look at it since the
45798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * other thread may be reading something.
45808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Oh well, its a screwed up app that does
45818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * a peeloff OR a accept while reading
45828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * from the main socket... actually its
45838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * only the peeloff() case, since I think
45848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * read will fail on a listening socket..
45858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
45868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
45878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
45888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* lock the socket buffers */
45898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_READ_LOCK(old_inp);
45908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(control, &old_inp->read_queue, next, nctl) {
45918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Pull off all for out target stcb */
45928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control->stcb == stcb) {
45938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* remove it we want it */
45948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&old_inp->read_queue, control, next);
45958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_INSERT_TAIL(&tmp_queue, control, next);
45968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m = control->data;
45978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			while (m) {
45988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
45998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE,SCTP_BUF_LEN(m));
46008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_sbfree(control, stcb, &old_so->so_rcv, m);
46028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
46038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
46048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
46058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				m = SCTP_BUF_NEXT(m);
46068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_READ_UNLOCK(old_inp);
46108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Remove the sb-lock on the old socket */
46118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version < 700000
46128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SOCKBUF_LOCK(&(old_so->so_rcv));
46138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
46148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
46158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sbunlock(&old_so->so_rcv, 1);
46168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
46178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__)
46198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sbunlock(&old_so->so_rcv);
46208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
46218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version < 700000
46228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SOCKBUF_UNLOCK(&(old_so->so_rcv));
46238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
46248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now we move them over to the new socket buffer */
46258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_READ_LOCK(new_inp);
46268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(control, &tmp_queue, next, nctl) {
46278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_INSERT_TAIL(&new_inp->read_queue, control, next);
46288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m = control->data;
46298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		while (m) {
46308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
46318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m));
46328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_sballoc(stcb, &new_so->so_rcv, m);
46348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
46358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
46368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
46378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m = SCTP_BUF_NEXT(m);
46388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_READ_UNLOCK(new_inp);
46418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
46428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
46448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_add_to_readq(struct sctp_inpcb *inp,
46458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_tcb *stcb,
46468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_queued_to_read *control,
46478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sockbuf *sb,
46488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int end,
46498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int inp_read_lock_held,
46508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int so_locked
46518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
46528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    SCTP_UNUSED
46538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
46548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    )
46558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
46568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
46578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Here we must place the control on the end of the socket read
46588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * queue AND increment sb_cc so that select will work properly on
46598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * read.
46608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
4661b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	struct mbuf *m, *prev = NULL;
46628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
46638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL) {
46648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Gak, TSNH!! */
46658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
46668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		panic("Gak, inp NULL on add_to_readq");
46678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
46688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
46698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
46718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (so_locked) {
46728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_lock_assert(SCTP_INP_SO(inp));
46738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
46748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_unlock_assert(SCTP_INP_SO(inp));
46758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
46778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp_read_lock_held == 0)
46788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_LOCK(inp);
46798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) {
46808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_remote_addr(control->whoFrom);
46818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control->data) {
46828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(control->data);
46838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			control->data = NULL;
46848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
46868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp_read_lock_held == 0)
46878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_UNLOCK(inp);
46888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
46898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!(control->spec_flags & M_NOTIFICATION)) {
46918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&inp->total_recvs, 1);
46928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!control->do_not_ref_stcb) {
46938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_add_int(&stcb->total_recvs, 1);
46948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
46958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
46968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m = control->data;
46978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->held_length = 0;
46988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->length = 0;
46998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (m) {
47008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BUF_LEN(m) == 0) {
47018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Skip mbufs with NO length */
47028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (prev == NULL) {
47038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* First one */
47048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				control->data = sctp_m_free(m);
47058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				m = control->data;
47068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
47078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_BUF_NEXT(prev) = sctp_m_free(m);
47088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				m = SCTP_BUF_NEXT(prev);
47098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
47108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (m == NULL) {
47118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				control->tail_mbuf = prev;
47128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
47138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
47148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		prev = m;
47168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
47178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m));
47188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_sballoc(stcb, sb, m);
47208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
47218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
47228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
47238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&control->length, SCTP_BUF_LEN(m));
47248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m = SCTP_BUF_NEXT(m);
47258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
47268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (prev != NULL) {
47278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->tail_mbuf = prev;
47288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
47298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Everything got collapsed out?? */
47308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_remote_addr(control->whoFrom);
47318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
47328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp_read_lock_held == 0)
47338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_UNLOCK(inp);
47348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
47358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
47368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (end) {
47378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->end_added = 1;
47388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
47390ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#if defined(__Userspace__)
47400ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen	if (inp->recv_callback) {
47410ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen		if (inp_read_lock_held == 0)
47420ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			SCTP_INP_READ_UNLOCK(inp);
47430ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen		if (control->end_added == 1) {
47440ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			struct socket *so;
47450ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			struct mbuf *m;
474673e265d74b8dddf404a3200cc2a4b593025158e7tuexen			char *buffer;
474773e265d74b8dddf404a3200cc2a4b593025158e7tuexen			struct sctp_rcvinfo rcv;
474873e265d74b8dddf404a3200cc2a4b593025158e7tuexen			union sctp_sockstore addr;
4749f134d2564b9f6f3dc2ec8bd5390ef7687553c5cbt			int flags;
475073c31e0d1075341a12dc84bd5a4c5ab479124f34tuexen
475173e265d74b8dddf404a3200cc2a4b593025158e7tuexen			if ((buffer = malloc(control->length)) == NULL) {
475273e265d74b8dddf404a3200cc2a4b593025158e7tuexen				return;
475373e265d74b8dddf404a3200cc2a4b593025158e7tuexen			}
4754498b53d78c906df68d1ae863d55f59359ad458b2t			so = stcb->sctp_socket;
47550ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			for (m = control->data; m; m = SCTP_BUF_NEXT(m)) {
47560ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				sctp_sbfree(control, control->stcb, &so->so_rcv, m);
47570ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			}
47580ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			atomic_add_int(&stcb->asoc.refcnt, 1);
47590ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			SCTP_TCB_UNLOCK(stcb);
476073e265d74b8dddf404a3200cc2a4b593025158e7tuexen			m_copydata(control->data, 0, control->length, buffer);
476173e265d74b8dddf404a3200cc2a4b593025158e7tuexen			memset(&rcv, 0, sizeof(struct sctp_rcvinfo));
476273e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_sid = control->sinfo_stream;
476373e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_ssn = control->sinfo_ssn;
476473e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_flags = control->sinfo_flags;
476573e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_ppid = control->sinfo_ppid;
476673e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_tsn = control->sinfo_tsn;
476773e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_cumtsn = control->sinfo_cumtsn;
476873e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_context = control->sinfo_context;
476973e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_assoc_id = control->sinfo_assoc_id;
477073e265d74b8dddf404a3200cc2a4b593025158e7tuexen			memset(&addr, 0, sizeof(union sctp_sockstore));
477173e265d74b8dddf404a3200cc2a4b593025158e7tuexen			switch (control->whoFrom->ro._l_addr.sa.sa_family) {
477273e265d74b8dddf404a3200cc2a4b593025158e7tuexen#ifdef INET
477373e265d74b8dddf404a3200cc2a4b593025158e7tuexen			case AF_INET:
477473e265d74b8dddf404a3200cc2a4b593025158e7tuexen				addr.sin = control->whoFrom->ro._l_addr.sin;
477573e265d74b8dddf404a3200cc2a4b593025158e7tuexen				break;
477673e265d74b8dddf404a3200cc2a4b593025158e7tuexen#endif
477773e265d74b8dddf404a3200cc2a4b593025158e7tuexen#ifdef INET6
477873e265d74b8dddf404a3200cc2a4b593025158e7tuexen			case AF_INET6:
477973e265d74b8dddf404a3200cc2a4b593025158e7tuexen				addr.sin6 = control->whoFrom->ro._l_addr.sin6;
478073e265d74b8dddf404a3200cc2a4b593025158e7tuexen				break;
478173e265d74b8dddf404a3200cc2a4b593025158e7tuexen#endif
478266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			case AF_CONN:
478366e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				addr.sconn = control->whoFrom->ro._l_addr.sconn;
478466e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				break;
478573e265d74b8dddf404a3200cc2a4b593025158e7tuexen			default:
478673e265d74b8dddf404a3200cc2a4b593025158e7tuexen				addr.sa = control->whoFrom->ro._l_addr.sa;
478773e265d74b8dddf404a3200cc2a4b593025158e7tuexen				break;
478873e265d74b8dddf404a3200cc2a4b593025158e7tuexen			}
4789f134d2564b9f6f3dc2ec8bd5390ef7687553c5cbt			flags = MSG_EOR;
479073e265d74b8dddf404a3200cc2a4b593025158e7tuexen			if (control->spec_flags & M_NOTIFICATION) {
479173e265d74b8dddf404a3200cc2a4b593025158e7tuexen				flags |= MSG_NOTIFICATION;
479273e265d74b8dddf404a3200cc2a4b593025158e7tuexen			}
4793d47a4475eeacc9978923e35a6c44a6c5cb6c2227tuexen			inp->recv_callback(so, addr, buffer, control->length, rcv, flags, inp->ulp_info);
47940ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			SCTP_TCB_LOCK(stcb);
47950ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			atomic_subtract_int(&stcb->asoc.refcnt, 1);
4796e863c174caf47be9814fa7b3fdfae2db0c3a8383t			sctp_free_remote_addr(control->whoFrom);
4797e863c174caf47be9814fa7b3fdfae2db0c3a8383t			control->whoFrom = NULL;
479873e265d74b8dddf404a3200cc2a4b593025158e7tuexen			sctp_m_freem(control->data);
47990ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			control->data = NULL;
48000ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			control->length = 0;
48010ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			sctp_free_a_readq(stcb, control);
480273c31e0d1075341a12dc84bd5a4c5ab479124f34tuexen		}
48030ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen		return;
480473c31e0d1075341a12dc84bd5a4c5ab479124f34tuexen	}
48050ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#endif
48068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INSERT_TAIL(&inp->read_queue, control, next);
48078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp_read_lock_held == 0)
48088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_UNLOCK(inp);
48098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp && inp->sctp_socket) {
48108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
48118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
48128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
48130612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
48148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct socket *so;
481573c31e0d1075341a12dc84bd5a4c5ab479124f34tuexen
48168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			so = SCTP_INP_SO(inp);
48178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (!so_locked) {
4818b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				if (stcb) {
4819b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen					atomic_add_int(&stcb->asoc.refcnt, 1);
4820b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen					SCTP_TCB_UNLOCK(stcb);
4821b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				}
48228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_SOCKET_LOCK(so, 1);
4823b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				if (stcb) {
4824b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen					SCTP_TCB_LOCK(stcb);
4825b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen					atomic_subtract_int(&stcb->asoc.refcnt, 1);
4826b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				}
48278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
48288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_SOCKET_UNLOCK(so, 1);
48298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
48308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
48318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
48338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_sorwakeup(inp, inp->sctp_socket);
48340612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
48358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (!so_locked) {
48368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_SOCKET_UNLOCK(so, 1);
48378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
48398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
48428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
48458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_append_to_readq(struct sctp_inpcb *inp,
48468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_tcb *stcb,
48478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_queued_to_read *control,
48488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct mbuf *m,
48498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int end,
48508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int ctls_cumack,
48518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sockbuf *sb)
48528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
48538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
48548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * A partial delivery API event is underway. OR we are appending on
48558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * the reassembly queue.
48568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *
48578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * If PDAPI this means we need to add m to the end of the data.
48588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Increase the length in the control AND increment the sb_cc.
48598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Otherwise sb is NULL and all we need to do is put it at the end
48608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * of the mbuf chain.
48618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
4862b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int len = 0;
48638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *mm, *tail = NULL, *prev = NULL;
48648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp) {
48668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_LOCK(inp);
48678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
48698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	get_out:
48708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp) {
48718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_UNLOCK(inp);
48728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
48738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
48748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ)) {
48768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_UNLOCK(inp);
4877b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (0);
48788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control->end_added) {
48808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* huh this one is complete? */
48818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto get_out;
48828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	mm = m;
48848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (mm == NULL) {
48858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto get_out;
48868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
48878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
48888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (mm) {
48898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BUF_LEN(mm) == 0) {
48908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Skip mbufs with NO lenght */
48918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (prev == NULL) {
48928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* First one */
48938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				m = sctp_m_free(mm);
48948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				mm = m;
48958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
48968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_BUF_NEXT(prev) = sctp_m_free(mm);
48978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				mm = SCTP_BUF_NEXT(prev);
48988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
48998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
49008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		prev = mm;
49028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		len += SCTP_BUF_LEN(mm);
49038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sb) {
49048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
49058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(mm));
49068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_sballoc(stcb, sb, mm);
49088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
49098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_sblog(sb, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
49108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
49118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		mm = SCTP_BUF_NEXT(mm);
49138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
49148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (prev) {
49158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tail = prev;
49168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
49178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Really there should always be a prev */
49188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (m == NULL) {
49198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Huh nothing left? */
49208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
49218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			panic("Nothing left to add?");
49228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
49238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto get_out;
49248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
49258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tail = m;
49278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
49288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control->tail_mbuf) {
49298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* append */
49308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_BUF_NEXT(control->tail_mbuf) = m;
49318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->tail_mbuf = tail;
49328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
49338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* nothing there */
49348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
49358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control->data != NULL) {
49368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			panic("This should NOT happen");
49378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
49398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->data = m;
49408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->tail_mbuf = tail;
49418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
49428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&control->length, len);
49438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (end) {
49448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* message is complete */
49458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb && (control == stcb->asoc.control_pdapi)) {
49468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.control_pdapi = NULL;
49478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
49488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->held_length = 0;
49498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->end_added = 1;
49508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
49518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
49528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->do_not_ref_stcb = 1;
49538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
49548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
49558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * When we are appending in partial delivery, the cum-ack is used
49568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * for the actual pd-api highest tsn on this mbuf. The true cum-ack
49578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * is populated in the outbound sinfo structure from the true cumack
49588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * if the association exists...
49598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
49604be9124eddeed30d7df8dfc5168c77e95979ee0dt	control->sinfo_tsn = control->sinfo_cumtsn = ctls_cumack;
49610ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#if defined(__Userspace__)
49620ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen	if (inp->recv_callback) {
49634be9124eddeed30d7df8dfc5168c77e95979ee0dt		uint32_t pd_point, length;
49644be9124eddeed30d7df8dfc5168c77e95979ee0dt
49654be9124eddeed30d7df8dfc5168c77e95979ee0dt		length = control->length;
49664be9124eddeed30d7df8dfc5168c77e95979ee0dt		if (stcb != NULL && stcb->sctp_socket != NULL) {
49674be9124eddeed30d7df8dfc5168c77e95979ee0dt			pd_point = min(SCTP_SB_LIMIT_RCV(stcb->sctp_socket) >> SCTP_PARTIAL_DELIVERY_SHIFT,
49684be9124eddeed30d7df8dfc5168c77e95979ee0dt			               stcb->sctp_ep->partial_delivery_point);
49694be9124eddeed30d7df8dfc5168c77e95979ee0dt		} else {
49704be9124eddeed30d7df8dfc5168c77e95979ee0dt			pd_point = inp->partial_delivery_point;
49714be9124eddeed30d7df8dfc5168c77e95979ee0dt		}
49724be9124eddeed30d7df8dfc5168c77e95979ee0dt		if ((control->end_added == 1) || (length >= pd_point)) {
49730ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			struct socket *so;
497473e265d74b8dddf404a3200cc2a4b593025158e7tuexen			char *buffer;
497573e265d74b8dddf404a3200cc2a4b593025158e7tuexen			struct sctp_rcvinfo rcv;
497673e265d74b8dddf404a3200cc2a4b593025158e7tuexen			union sctp_sockstore addr;
4977f134d2564b9f6f3dc2ec8bd5390ef7687553c5cbt			int flags;
497873c31e0d1075341a12dc84bd5a4c5ab479124f34tuexen
497973e265d74b8dddf404a3200cc2a4b593025158e7tuexen			if ((buffer = malloc(control->length)) == NULL) {
498073e265d74b8dddf404a3200cc2a4b593025158e7tuexen				return (-1);
498173e265d74b8dddf404a3200cc2a4b593025158e7tuexen			}
49826c1813d4ac9e00b805e1a400f004f2994b2297e5t			so = stcb->sctp_socket;
49830ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			for (m = control->data; m; m = SCTP_BUF_NEXT(m)) {
49840ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen				sctp_sbfree(control, control->stcb, &so->so_rcv, m);
49850ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			}
498673e265d74b8dddf404a3200cc2a4b593025158e7tuexen			m_copydata(control->data, 0, control->length, buffer);
498773e265d74b8dddf404a3200cc2a4b593025158e7tuexen			memset(&rcv, 0, sizeof(struct sctp_rcvinfo));
498873e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_sid = control->sinfo_stream;
498973e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_ssn = control->sinfo_ssn;
499073e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_flags = control->sinfo_flags;
499173e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_ppid = control->sinfo_ppid;
499273e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_tsn = control->sinfo_tsn;
499373e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_cumtsn = control->sinfo_cumtsn;
499473e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_context = control->sinfo_context;
499573e265d74b8dddf404a3200cc2a4b593025158e7tuexen			rcv.rcv_assoc_id = control->sinfo_assoc_id;
499673e265d74b8dddf404a3200cc2a4b593025158e7tuexen			memset(&addr, 0, sizeof(union sctp_sockstore));
499773e265d74b8dddf404a3200cc2a4b593025158e7tuexen			switch (control->whoFrom->ro._l_addr.sa.sa_family) {
499873e265d74b8dddf404a3200cc2a4b593025158e7tuexen#ifdef INET
499973e265d74b8dddf404a3200cc2a4b593025158e7tuexen			case AF_INET:
500073e265d74b8dddf404a3200cc2a4b593025158e7tuexen				addr.sin = control->whoFrom->ro._l_addr.sin;
500173e265d74b8dddf404a3200cc2a4b593025158e7tuexen				break;
500273e265d74b8dddf404a3200cc2a4b593025158e7tuexen#endif
500373e265d74b8dddf404a3200cc2a4b593025158e7tuexen#ifdef INET6
500473e265d74b8dddf404a3200cc2a4b593025158e7tuexen			case AF_INET6:
500573e265d74b8dddf404a3200cc2a4b593025158e7tuexen				addr.sin6 = control->whoFrom->ro._l_addr.sin6;
500673e265d74b8dddf404a3200cc2a4b593025158e7tuexen				break;
500773e265d74b8dddf404a3200cc2a4b593025158e7tuexen#endif
500866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			case AF_CONN:
500966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				addr.sconn = control->whoFrom->ro._l_addr.sconn;
501066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				break;
501173e265d74b8dddf404a3200cc2a4b593025158e7tuexen			default:
501273e265d74b8dddf404a3200cc2a4b593025158e7tuexen				addr.sa = control->whoFrom->ro._l_addr.sa;
501373e265d74b8dddf404a3200cc2a4b593025158e7tuexen				break;
501473e265d74b8dddf404a3200cc2a4b593025158e7tuexen			}
5015f134d2564b9f6f3dc2ec8bd5390ef7687553c5cbt			flags = 0;
50164be9124eddeed30d7df8dfc5168c77e95979ee0dt			if (control->end_added == 1) {
50174be9124eddeed30d7df8dfc5168c77e95979ee0dt				flags |= MSG_EOR;
50184be9124eddeed30d7df8dfc5168c77e95979ee0dt			}
501973e265d74b8dddf404a3200cc2a4b593025158e7tuexen			if (control->spec_flags & M_NOTIFICATION) {
502073e265d74b8dddf404a3200cc2a4b593025158e7tuexen				flags |= MSG_NOTIFICATION;
502173e265d74b8dddf404a3200cc2a4b593025158e7tuexen			}
502273e265d74b8dddf404a3200cc2a4b593025158e7tuexen			sctp_m_freem(control->data);
50230ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			control->data = NULL;
50244be9124eddeed30d7df8dfc5168c77e95979ee0dt			control->tail_mbuf = NULL;
50250ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			control->length = 0;
50264be9124eddeed30d7df8dfc5168c77e95979ee0dt			if (control->end_added) {
5027e863c174caf47be9814fa7b3fdfae2db0c3a8383t				sctp_free_remote_addr(control->whoFrom);
5028e863c174caf47be9814fa7b3fdfae2db0c3a8383t				control->whoFrom = NULL;
50294be9124eddeed30d7df8dfc5168c77e95979ee0dt				sctp_free_a_readq(stcb, control);
50304be9124eddeed30d7df8dfc5168c77e95979ee0dt			} else {
50314be9124eddeed30d7df8dfc5168c77e95979ee0dt				control->some_taken = 1;
50324be9124eddeed30d7df8dfc5168c77e95979ee0dt			}
50334be9124eddeed30d7df8dfc5168c77e95979ee0dt			atomic_add_int(&stcb->asoc.refcnt, 1);
50344be9124eddeed30d7df8dfc5168c77e95979ee0dt			SCTP_TCB_UNLOCK(stcb);
50354be9124eddeed30d7df8dfc5168c77e95979ee0dt			inp->recv_callback(so, addr, buffer, length, rcv, flags, inp->ulp_info);
50364be9124eddeed30d7df8dfc5168c77e95979ee0dt			SCTP_TCB_LOCK(stcb);
50374be9124eddeed30d7df8dfc5168c77e95979ee0dt			atomic_subtract_int(&stcb->asoc.refcnt, 1);
503873c31e0d1075341a12dc84bd5a4c5ab479124f34tuexen		}
50390ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen		if (inp)
50400ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen			SCTP_INP_READ_UNLOCK(inp);
50410ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen		return (0);
504273c31e0d1075341a12dc84bd5a4c5ab479124f34tuexen	}
50430ffb57b9ad94ecba97f46f7a6f5134833f2089a7tuexen#endif
50448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp) {
50458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_UNLOCK(inp);
50468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
50478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp && inp->sctp_socket) {
50488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
50498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
50508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
50510612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
50528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct socket *so;
505373c31e0d1075341a12dc84bd5a4c5ab479124f34tuexen
50548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			so = SCTP_INP_SO(inp);
5055b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			if (stcb) {
5056b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				atomic_add_int(&stcb->asoc.refcnt, 1);
5057b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				SCTP_TCB_UNLOCK(stcb);
5058b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			}
50598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_LOCK(so, 1);
5060b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			if (stcb) {
5061b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				SCTP_TCB_LOCK(stcb);
5062b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				atomic_subtract_int(&stcb->asoc.refcnt, 1);
5063b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			}
50648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
50658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_SOCKET_UNLOCK(so, 1);
50668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (0);
50678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
50688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
50698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_sorwakeup(inp, inp->sctp_socket);
50700612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
50718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_UNLOCK(so, 1);
50728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
50738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
50748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
50758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
50768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
50778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*************HOLD THIS COMMENT FOR PATCH FILE OF
50818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *************ALTERNATE ROUTING CODE
50828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
50838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*************HOLD THIS COMMENT FOR END OF PATCH FILE OF
50858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *************ALTERNATE ROUTING CODE
50868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
50878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct mbuf *
50898f9e45fea288542b24a6bda01269c6fc184d991atsctp_generate_cause(uint16_t code, char *info)
50908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
50918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m;
50928f9e45fea288542b24a6bda01269c6fc184d991at	struct sctp_gen_error_cause *cause;
50938f9e45fea288542b24a6bda01269c6fc184d991at	size_t info_len, len;
50948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
50958f9e45fea288542b24a6bda01269c6fc184d991at	if ((code == 0) || (info == NULL)) {
50968f9e45fea288542b24a6bda01269c6fc184d991at		return (NULL);
50978f9e45fea288542b24a6bda01269c6fc184d991at	}
50988f9e45fea288542b24a6bda01269c6fc184d991at	info_len = strlen(info);
50998f9e45fea288542b24a6bda01269c6fc184d991at	len = sizeof(struct sctp_paramhdr) + info_len;
51008f9e45fea288542b24a6bda01269c6fc184d991at	m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
51018f9e45fea288542b24a6bda01269c6fc184d991at	if (m != NULL) {
51028f9e45fea288542b24a6bda01269c6fc184d991at		SCTP_BUF_LEN(m) = len;
51038f9e45fea288542b24a6bda01269c6fc184d991at		cause = mtod(m, struct sctp_gen_error_cause *);
51048f9e45fea288542b24a6bda01269c6fc184d991at		cause->code = htons(code);
51058f9e45fea288542b24a6bda01269c6fc184d991at		cause->length = htons((uint16_t)len);
51068f9e45fea288542b24a6bda01269c6fc184d991at		memcpy(cause->info, info, info_len);
51078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (m);
51098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
51108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5111a06ca64c1ea60031147a135d015c66e4803beb1ctstruct mbuf *
5112a06ca64c1ea60031147a135d015c66e4803beb1ctsctp_generate_no_user_data_cause(uint32_t tsn)
5113a06ca64c1ea60031147a135d015c66e4803beb1ct{
5114a06ca64c1ea60031147a135d015c66e4803beb1ct	struct mbuf *m;
5115a06ca64c1ea60031147a135d015c66e4803beb1ct	struct sctp_error_no_user_data *no_user_data_cause;
5116a06ca64c1ea60031147a135d015c66e4803beb1ct	size_t len;
5117a06ca64c1ea60031147a135d015c66e4803beb1ct
5118a06ca64c1ea60031147a135d015c66e4803beb1ct	len = sizeof(struct sctp_error_no_user_data);
5119a06ca64c1ea60031147a135d015c66e4803beb1ct	m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
5120a06ca64c1ea60031147a135d015c66e4803beb1ct	if (m != NULL) {
5121a06ca64c1ea60031147a135d015c66e4803beb1ct		SCTP_BUF_LEN(m) = len;
5122a06ca64c1ea60031147a135d015c66e4803beb1ct		no_user_data_cause = mtod(m, struct sctp_error_no_user_data *);
5123a06ca64c1ea60031147a135d015c66e4803beb1ct		no_user_data_cause->cause.code = htons(SCTP_CAUSE_NO_USER_DATA);
5124a06ca64c1ea60031147a135d015c66e4803beb1ct		no_user_data_cause->cause.length = htons((uint16_t)len);
5125a06ca64c1ea60031147a135d015c66e4803beb1ct		no_user_data_cause->tsn = tsn; /* tsn is passed in as NBO */
5126a06ca64c1ea60031147a135d015c66e4803beb1ct	}
5127a06ca64c1ea60031147a135d015c66e4803beb1ct	return (m);
5128a06ca64c1ea60031147a135d015c66e4803beb1ct}
5129a06ca64c1ea60031147a135d015c66e4803beb1ct
51308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MBCNT_LOGGING
51318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
51328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
51338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_tmit_chunk *tp1, int chk_cnt)
51348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
51358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (tp1->data == NULL) {
51368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
51378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->chunks_on_out_queue -= chk_cnt;
51398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBCNT_LOGGING_ENABLE) {
51408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE,
51418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       asoc->total_output_queue_size,
51428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       tp1->book_size,
51438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       0,
51448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       tp1->mbcnt);
51458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (asoc->total_output_queue_size >= tp1->book_size) {
51478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&asoc->total_output_queue_size, -tp1->book_size);
51488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
51498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asoc->total_output_queue_size = 0;
51508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_socket && (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) ||
51538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)))) {
51548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) {
51558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->sctp_socket->so_snd.sb_cc -= tp1->book_size;
51568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
51578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->sctp_socket->so_snd.sb_cc = 0;
51588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
51608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
51628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
51648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
51658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
51668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
516747674b651417d493ff4e0318113fd7beeef119dbtuexen			   uint8_t sent, int so_locked
51688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
51698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   SCTP_UNUSED
51708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
51718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	)
51728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
51738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_stream_out *strq;
51748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk = NULL, *tp2;
51758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_stream_queue_pending *sp;
5176b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	uint16_t stream = 0, seq = 0;
51778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t foundeom = 0;
51788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int ret_sz = 0;
51798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int notdone;
5180b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int do_wakeup_routine = 0;
518120d5d287bff2075897105f85287230d55bdfa420t
51828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
51838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (so_locked) {
51848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_lock_assert(SCTP_INP_SO(stcb->sctp_ep));
51858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
51868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_unlock_assert(SCTP_INP_SO(stcb->sctp_ep));
51878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
51888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
51898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stream = tp1->rec.data.stream_number;
51908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	seq = tp1->rec.data.stream_seq;
519120d5d287bff2075897105f85287230d55bdfa420t	if (sent || !(tp1->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG)) {
519220d5d287bff2075897105f85287230d55bdfa420t		stcb->asoc.abandoned_sent[0]++;
519320d5d287bff2075897105f85287230d55bdfa420t		stcb->asoc.abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++;
519420d5d287bff2075897105f85287230d55bdfa420t		stcb->asoc.strmout[stream].abandoned_sent[0]++;
519520d5d287bff2075897105f85287230d55bdfa420t#if defined(SCTP_DETAILED_STR_STATS)
519620d5d287bff2075897105f85287230d55bdfa420t		stcb->asoc.strmout[stream].abandoned_sent[PR_SCTP_POLICY(tp1->flags)]++;
519720d5d287bff2075897105f85287230d55bdfa420t#endif
519820d5d287bff2075897105f85287230d55bdfa420t	} else {
519920d5d287bff2075897105f85287230d55bdfa420t		stcb->asoc.abandoned_unsent[0]++;
520020d5d287bff2075897105f85287230d55bdfa420t		stcb->asoc.abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++;
520120d5d287bff2075897105f85287230d55bdfa420t		stcb->asoc.strmout[stream].abandoned_unsent[0]++;
520220d5d287bff2075897105f85287230d55bdfa420t#if defined(SCTP_DETAILED_STR_STATS)
520320d5d287bff2075897105f85287230d55bdfa420t		stcb->asoc.strmout[stream].abandoned_unsent[PR_SCTP_POLICY(tp1->flags)]++;
520420d5d287bff2075897105f85287230d55bdfa420t#endif
520520d5d287bff2075897105f85287230d55bdfa420t	}
52068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	do {
52078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ret_sz += tp1->book_size;
52088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (tp1->data != NULL) {
52098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->sent < SCTP_DATAGRAM_RESEND) {
52108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_flight_size_decrease(tp1);
52118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_total_flight_decrease(stcb, tp1);
52128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
52148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.peers_rwnd += tp1->send_size;
52158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh);
521647674b651417d493ff4e0318113fd7beeef119dbtuexen			if (sent) {
521747674b651417d493ff4e0318113fd7beeef119dbtuexen				sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked);
521847674b651417d493ff4e0318113fd7beeef119dbtuexen			} else {
521947674b651417d493ff4e0318113fd7beeef119dbtuexen				sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked);
522047674b651417d493ff4e0318113fd7beeef119dbtuexen			}
52218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->data) {
52228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(tp1->data);
52238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->data = NULL;
52248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			do_wakeup_routine = 1;
52268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (PR_SCTP_BUF_ENABLED(tp1->flags)) {
52278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.sent_queue_cnt_removeable--;
52288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tp1->sent = SCTP_FORWARD_TSN_SKIP;
52318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) ==
52328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_DATA_NOT_FRAG) {
52338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* not frag'ed we ae done   */
52348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			notdone = 0;
52358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			foundeom = 1;
52368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
52378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* end of frag, we are done */
52388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			notdone = 0;
52398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			foundeom = 1;
52408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
52418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
52428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Its a begin or middle piece, we must mark all of
52438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * it
52448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
52458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			notdone = 1;
52468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tp1 = TAILQ_NEXT(tp1, sctp_next);
52478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} while (tp1 && notdone);
52498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (foundeom == 0) {
52508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
52518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * The multi-part message was scattered across the send and
52528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * sent queue.
52538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
52548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) {
52558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((tp1->rec.data.stream_number != stream) ||
5256e2828360ea9cf8951730d46f5c14626c9425cb30t			    (tp1->rec.data.stream_seq != seq)) {
52578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
52588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* save to chk in case we have some on stream out
52608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * queue. If so and we have an un-transmitted one
52618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * we don't have to fudge the TSN.
52628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
52638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chk = tp1;
52648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ret_sz += tp1->book_size;
52658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
526647674b651417d493ff4e0318113fd7beeef119dbtuexen			if (sent) {
526747674b651417d493ff4e0318113fd7beeef119dbtuexen				sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked);
526847674b651417d493ff4e0318113fd7beeef119dbtuexen			} else {
526947674b651417d493ff4e0318113fd7beeef119dbtuexen				sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked);
527047674b651417d493ff4e0318113fd7beeef119dbtuexen			}
52718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->data) {
52728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(tp1->data);
52738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				tp1->data = NULL;
52748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* No flight involved here book the size to 0 */
52768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tp1->book_size = 0;
52778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
52788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				foundeom = 1;
52798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
52808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			do_wakeup_routine = 1;
52818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tp1->sent = SCTP_FORWARD_TSN_SKIP;
52828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next);
52838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* on to the sent queue so we can wait for it to be passed by. */
52848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1,
52858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					  sctp_next);
52868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.send_queue_cnt--;
52878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.sent_queue_cnt++;
52888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
52898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
52908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (foundeom == 0) {
52918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
52928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Still no eom found. That means there
52938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * is stuff left on the stream out queue.. yuck.
52948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
52958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_SEND_LOCK(stcb);
5296e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t		strq = &stcb->asoc.strmout[stream];
5297e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t		sp = TAILQ_FIRST(&strq->outqueue);
5298e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t		if (sp != NULL) {
5299e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			sp->discard_rest = 1;
5300e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			/*
5301e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			 * We may need to put a chunk on the
5302e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			 * queue that holds the TSN that
5303e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			 * would have been sent with the LAST
5304e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			 * bit.
5305e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			 */
5306e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			if (chk == NULL) {
5307e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				/* Yep, we have to */
5308e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				sctp_alloc_a_chunk(stcb, chk);
53098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (chk == NULL) {
5310e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t					/* we are hosed. All we can
5311e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t					 * do is nothing.. which will
5312e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t					 * cause an abort if the peer is
5313e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t					 * paying attention.
53148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
5315e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t					goto oh_well;
53168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
5317e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				memset(chk, 0, sizeof(*chk));
5318e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				chk->rec.data.rcv_flags = SCTP_DATA_LAST_FRAG;
5319e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				chk->sent = SCTP_FORWARD_TSN_SKIP;
5320e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				chk->asoc = &stcb->asoc;
5321e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				chk->rec.data.stream_seq = strq->next_sequence_send;
5322e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				chk->rec.data.stream_number = sp->stream;
5323e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				chk->rec.data.payloadtype = sp->ppid;
5324e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				chk->rec.data.context = sp->context;
5325e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				chk->flags = sp->act_flags;
5326e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				if (sp->net)
5327e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t					chk->whoTo = sp->net;
5328e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				else
5329e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t					chk->whoTo = stcb->asoc.primary_destination;
5330e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				atomic_add_int(&chk->whoTo->ref_count, 1);
5331e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t#if defined(__FreeBSD__) || defined(__Panda__)
5332e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1);
5333e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t#else
5334e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				chk->rec.data.TSN_seq = stcb->asoc.sending_seq++;
5335e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t#endif
5336e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				stcb->asoc.pr_sctp_cnt++;
5337e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next);
5338e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				stcb->asoc.sent_queue_cnt++;
5339e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				stcb->asoc.pr_sctp_cnt++;
5340e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			} else {
5341e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
5342e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			}
5343e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			strq->next_sequence_send++;
5344e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t		oh_well:
5345e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t			if (sp->data) {
5346e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				/* Pull any data to free up the SB and
5347e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				 * allow sender to "add more" while we
5348e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				 * will throw away :-)
5349e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				 */
5350e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				sctp_free_spbufspace(stcb, &stcb->asoc, sp);
5351e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				ret_sz += sp->length;
5352e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				do_wakeup_routine = 1;
5353e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				sp->some_taken = 1;
5354e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				sctp_m_freem(sp->data);
5355e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				sp->data = NULL;
5356e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				sp->tail_mbuf = NULL;
5357e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t				sp->length = 0;
53588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5359e5a3ccc4bb0971ef33da073d15fd0fc1ccaa3c01t		}
53608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_SEND_UNLOCK(stcb);
53618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
53628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (do_wakeup_routine) {
53630612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
53648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct socket *so;
53658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		so = SCTP_INP_SO(stcb->sctp_ep);
53678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!so_locked) {
53688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_add_int(&stcb->asoc.refcnt, 1);
53698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
53708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_LOCK(so, 1);
53718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_LOCK(stcb);
53728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_subtract_int(&stcb->asoc.refcnt, 1);
53738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
53748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* assoc was freed while we were unlocked */
53758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_SOCKET_UNLOCK(so, 1);
53768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (ret_sz);
53778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
53788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
53808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
53810612043f643c9b26245564c05defca64d472060etuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
53828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!so_locked) {
53838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_UNLOCK(so, 1);
53848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
53858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
53868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
53878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (ret_sz);
53888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
53898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
53908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
53918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * checks to see if the given address, sa, is one that is currently known by
53928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the kernel note: can't distinguish the same address on multiple interfaces
53938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * and doesn't handle multiple addresses with different zone/scope id's note:
53948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ifa_ifwithaddr() compares the entire sockaddr struct
53958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
53968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_ifa *
53978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr,
53988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    int holds_lock)
53998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
54008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_laddr *laddr;
54018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (holds_lock == 0) {
54038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RLOCK(inp);
54048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
54058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
54078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (laddr->ifa == NULL)
54088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
54098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addr->sa_family != laddr->ifa->address.sa.sa_family)
54108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
54118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
54128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addr->sa_family == AF_INET) {
54138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
54148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    laddr->ifa->address.sin.sin_addr.s_addr) {
54158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* found him. */
54168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (holds_lock == 0) {
54178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RUNLOCK(inp);
54188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
54198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (laddr->ifa);
54208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
54218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
54228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
54238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
54248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
54258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addr->sa_family == AF_INET6) {
54268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr,
54278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 &laddr->ifa->address.sin6)) {
54288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* found him. */
54298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (holds_lock == 0) {
54308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_INP_RUNLOCK(inp);
54318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
54328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (laddr->ifa);
54338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
54348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
54358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
54368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
543766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__)
543866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		if (addr->sa_family == AF_CONN) {
543966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			if (((struct sockaddr_conn *)addr)->sconn_addr == laddr->ifa->address.sconn.sconn_addr) {
544066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				/* found him. */
544166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				if (holds_lock == 0) {
544266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen					SCTP_INP_RUNLOCK(inp);
544366e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				}
544466e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				return (laddr->ifa);
544566e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				break;
544666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			}
544766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		}
544866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif
54498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
54508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (holds_lock == 0) {
54518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_RUNLOCK(inp);
54528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
54538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (NULL);
54548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
54558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
54578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_get_ifa_hash_val(struct sockaddr *addr)
54588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
54598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (addr->sa_family) {
54608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
54618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
54628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
54638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sin;
54648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin = (struct sockaddr_in *)addr;
54668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (sin->sin_addr.s_addr ^ (sin->sin_addr.s_addr >> 16));
54678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
54688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
54698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
54709ac77419b79fa1b61bed4326c4ef825a19335704t	case AF_INET6:
54718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
54728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6;
54738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t hash_of_addr;
54748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
54758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6 = (struct sockaddr_in6 *)addr;
547623273859c39742f09cc5ec7c9bf32ff225661e82tuexen#if !defined(__Windows__) && !defined(__Userspace_os_FreeBSD) && !defined(__Userspace_os_Darwin) && !defined(__Userspace_os_Windows)
54778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hash_of_addr = (sin6->sin6_addr.s6_addr32[0] +
54788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6->sin6_addr.s6_addr32[1] +
54798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6->sin6_addr.s6_addr32[2] +
54808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6->sin6_addr.s6_addr32[3]);
54818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
54828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hash_of_addr = (((uint32_t *)&sin6->sin6_addr)[0] +
54838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				((uint32_t *)&sin6->sin6_addr)[1] +
54848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				((uint32_t *)&sin6->sin6_addr)[2] +
54858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				((uint32_t *)&sin6->sin6_addr)[3]);
54868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
54878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hash_of_addr = (hash_of_addr ^ (hash_of_addr >> 16));
54888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (hash_of_addr);
54898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
54908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
54919ac77419b79fa1b61bed4326c4ef825a19335704t#if defined(__Userspace__)
54929ac77419b79fa1b61bed4326c4ef825a19335704t	case AF_CONN:
54939ac77419b79fa1b61bed4326c4ef825a19335704t	{
54949ac77419b79fa1b61bed4326c4ef825a19335704t		struct sockaddr_conn *sconn;
54955e35dea4d54c8ee4a750282fee252af98032dd37t		uintptr_t temp;
54969ac77419b79fa1b61bed4326c4ef825a19335704t
54979ac77419b79fa1b61bed4326c4ef825a19335704t		sconn = (struct sockaddr_conn *)addr;
54985e35dea4d54c8ee4a750282fee252af98032dd37t		temp = (uintptr_t)sconn->sconn_addr;
54999ac77419b79fa1b61bed4326c4ef825a19335704t		return ((uint32_t)(temp ^ (temp >> 16)));
55009ac77419b79fa1b61bed4326c4ef825a19335704t	}
55019ac77419b79fa1b61bed4326c4ef825a19335704t#endif
55028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
55038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
55048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
55058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
55068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
55078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_ifa *
55098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
55108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
55118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *sctp_ifap;
55128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_vrf *vrf;
55138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifalist *hash_head;
55148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t hash_of_addr;
55158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (holds_lock == 0)
55178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_IPI_ADDR_RLOCK();
55188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf = sctp_find_vrf(vrf_id);
55208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (vrf == NULL) {
55218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stage_right:
55228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (holds_lock == 0)
55238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_IPI_ADDR_RUNLOCK();
55248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
55258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
55268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	hash_of_addr = sctp_get_ifa_hash_val(addr);
55288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	hash_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_addr_hashmark)];
55308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hash_head == NULL) {
55318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("hash_of_addr:%x mask:%x table:%x - ",
55328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    hash_of_addr, (uint32_t)vrf->vrf_addr_hashmark,
55338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (uint32_t)(hash_of_addr & vrf->vrf_addr_hashmark));
55348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_print_address(addr);
55358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_PRINTF("No such bucket for address\n");
55368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (holds_lock == 0)
55378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_IPI_ADDR_RUNLOCK();
55388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
55408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
55418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(sctp_ifap, hash_head, next_bucket) {
55428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_ifap == NULL) {
55438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
55448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			panic("Huh LIST_FOREACH corrupt");
55458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        goto stage_right;
55468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
55478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("LIST corrupt of sctp_ifap's?\n");
55488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto stage_right;
55498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
55508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addr->sa_family != sctp_ifap->address.sa.sa_family)
55528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
55538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
55548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addr->sa_family == AF_INET) {
55558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
55568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    sctp_ifap->address.sin.sin_addr.s_addr) {
55578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* found him. */
55588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (holds_lock == 0)
55598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_IPI_ADDR_RUNLOCK();
55608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (sctp_ifap);
55618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
55628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
55638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
55658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
55668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addr->sa_family == AF_INET6) {
55678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr,
55688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 &sctp_ifap->address.sin6)) {
55698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* found him. */
55708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (holds_lock == 0)
55718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_IPI_ADDR_RUNLOCK();
55728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (sctp_ifap);
55738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
55748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
55758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
55768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
557766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__)
557866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		if (addr->sa_family == AF_CONN) {
557966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			if (((struct sockaddr_conn *)addr)->sconn_addr == sctp_ifap->address.sconn.sconn_addr) {
558066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				/* found him. */
558166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				if (holds_lock == 0)
558266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen					SCTP_IPI_ADDR_RUNLOCK();
558366e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				return (sctp_ifap);
558466e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				break;
558566e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			}
558666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		}
558766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif
55888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
55898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (holds_lock == 0)
55908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_IPI_ADDR_RUNLOCK();
55918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (NULL);
55928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
55938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
55948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
55958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_user_rcvd(struct sctp_tcb *stcb, uint32_t *freed_so_far, int hold_rlock,
55968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	       uint32_t rwnd_req)
55978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
55988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* User pulled some data, do we need a rwnd update? */
55998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int r_unlocked = 0;
56008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t dif, rwnd;
56018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct socket *so = NULL;
56028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
56038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL)
56048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
56058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
56068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&stcb->asoc.refcnt, 1);
56078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
56088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.state & (SCTP_STATE_ABOUT_TO_BE_FREED |
56098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_STATE_SHUTDOWN_RECEIVED |
56108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_STATE_SHUTDOWN_ACK_SENT)) {
56118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Pre-check If we are freeing no update */
56128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto no_lock;
56138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
56148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_INCR_REF(stcb->sctp_ep);
56158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
56168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
56178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
56188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
56198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	so = stcb->sctp_socket;
56208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (so == NULL) {
56218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
56228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
56238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&stcb->freed_by_sorcv_sincelast, *freed_so_far);
56248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Have you have freed enough to look */
56258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*freed_so_far = 0;
56268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Yep, its worth a look and the lock overhead */
56278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
56288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Figure out what the rwnd would be */
56298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	rwnd = sctp_calc_rwnd(stcb, &stcb->asoc);
56308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (rwnd >= stcb->asoc.my_last_reported_rwnd) {
56318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		dif = rwnd - stcb->asoc.my_last_reported_rwnd;
56328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
56338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		dif = 0;
56348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
56358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (dif >= rwnd_req) {
56368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hold_rlock) {
56378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
56388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			r_unlocked = 1;
56398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
56408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
56418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
56428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * One last check before we allow the guy possibly
56438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * to get in. There is a race, where the guy has not
56448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * reached the gate. In that case
56458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
56468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out;
56478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
56488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK(stcb);
56498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
56508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* No reports here */
56518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_TCB_UNLOCK(stcb);
56528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out;
56538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
56548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_STAT_INCR(sctps_wu_sacks_sent);
56558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_send_sack(stcb, SCTP_SO_LOCKED);
5656000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
56578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(stcb->sctp_ep, stcb,
56588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  SCTP_OUTPUT_FROM_USR_RCVD, SCTP_SO_LOCKED);
56598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* make sure no timer is running */
5660b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTPUTIL+SCTP_LOC_6);
56618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_UNLOCK(stcb);
56628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
56638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Update how much we have pending */
56648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->freed_by_sorcv_sincelast = dif;
56658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
56668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out:
56678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (so && r_unlocked && hold_rlock) {
56688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_LOCK(stcb->sctp_ep);
56698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
56708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
56718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INP_DECR_REF(stcb->sctp_ep);
56728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen no_lock:
56738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&stcb->asoc.refcnt, -1);
56748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return;
56758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
56768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
56778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
56788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_sorecvmsg(struct socket *so,
56798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct uio *uio,
56808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct mbuf **mp,
56818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sockaddr *from,
56828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int fromlen,
56838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int *msg_flags,
56848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    struct sctp_sndrcvinfo *sinfo,
56858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int filling_sinfo)
56868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
56878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
56888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * MSG flags we will look at MSG_DONTWAIT - non-blocking IO.
56898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * MSG_PEEK - Look don't touch :-D (only valid with OUT mbuf copy
56908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * mp=NULL thus uio is the copy method to userland) MSG_WAITALL - ??
56918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * On the way out we may send out any combination of:
56928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * MSG_NOTIFICATION MSG_EOR
56938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *
56948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
5695b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	struct sctp_inpcb *inp = NULL;
5696b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int my_len = 0;
5697b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int cp_len = 0, error = 0;
5698b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	struct sctp_queued_to_read *control = NULL, *ctl = NULL, *nxt = NULL;
5699b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	struct mbuf *m = NULL;
57008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tcb *stcb = NULL;
57018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int wakeup_read_socket = 0;
57028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int freecnt_applied = 0;
5703b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int out_flags = 0, in_flags = 0;
57048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int block_allowed = 1;
57058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t freed_so_far = 0;
57068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t copied_so_far = 0;
5707b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int in_eeor_mode = 0;
57088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int no_rcv_needed = 0;
5709b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	uint32_t rwnd_req = 0;
57108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int hold_sblock = 0;
57118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int hold_rlock = 0;
57128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int slen = 0;
57138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t held_length = 0;
57148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 700000
57158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int sockbuf_lock = 0;
57168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
57188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (uio == NULL) {
57198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
57208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EINVAL);
57218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
57228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
57238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (msg_flags) {
57248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		in_flags = *msg_flags;
57258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (in_flags & MSG_PEEK)
57268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_STAT_INCR(sctps_read_peeks);
57278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
57288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		in_flags = 0;
57298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
57308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
57311ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD)
57328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	slen = uio->uio_resid;
57331ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#else
57341ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen	slen = uio_resid(uio);
57358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
57378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	slen = uio->uio_resid;
57388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
57408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Pull in and set up our int flags */
57418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (in_flags & MSG_OOB) {
57428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Out of band's NOT supported */
57438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EOPNOTSUPP);
57448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
57458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((in_flags & MSG_PEEK) && (mp != NULL)) {
57468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
57478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EINVAL);
57488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
57498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((in_flags & (MSG_DONTWAIT
57508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version > 500000
57518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 | MSG_NBIO
57528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     )) ||
57548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_SO_IS_NBIO(so)) {
57558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		block_allowed = 0;
57568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
57578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* setup the endpoint */
57588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
57598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL) {
57608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT);
57618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EFAULT);
57628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
57638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	rwnd_req = (SCTP_SB_LIMIT_RCV(so) >> SCTP_RWND_HIWAT_SHIFT);
57648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Must be at least a MTU's worth */
57658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (rwnd_req < SCTP_MIN_RWND)
57668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		rwnd_req = SCTP_MIN_RWND;
57678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	in_eeor_mode = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
576815aed6e434dc1aac416f14635bb78920317d60e7t	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
57698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
57701ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD)
57718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_SORECV_ENTER,
57721ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen			       rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid);
57738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
57748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_SORECV_ENTER,
57751ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen			       rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio_resid(uio));
57768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
57788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_SORECV_ENTER,
57798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid);
57808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
57828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version < 700000) || defined(__Userspace__)
57838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SOCKBUF_LOCK(&so->so_rcv);
57848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	hold_sblock = 1;
57858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) &SCTP_RECV_RWND_LOGGING_ENABLE) {
57878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
57881ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD)
57898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_SORECV_ENTERPL,
57901ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen			       rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid);
57918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
57928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_SORECV_ENTERPL,
57931ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen			       rwnd_req, block_allowed, so->so_rcv.sb_cc, uio_resid(uio));
57948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
57968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_misc_ints(SCTP_SORECV_ENTERPL,
57978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			       rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid);
57988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
57998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
58008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
58028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = sblock(&so->so_rcv, SBLOCKWAIT(in_flags));
58038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
58048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__)
58068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = sblock(&so->so_rcv, (block_allowed ? SBL_WAIT : 0));
58078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
58088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error) {
58098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto release_unlocked;
58108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5811288bc15d7ec52924125686f12d3305b1730d9e6bt#if defined(__FreeBSD__) && __FreeBSD_version >= 700000
5812288bc15d7ec52924125686f12d3305b1730d9e6bt        sockbuf_lock = 1;
5813288bc15d7ec52924125686f12d3305b1730d9e6bt#endif
58148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen restart:
58158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version < 700000) || defined(__Userspace__)
58168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hold_sblock == 0) {
58178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_LOCK(&so->so_rcv);
58188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hold_sblock = 1;
58198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
58208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
58218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
58228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sbunlock(&so->so_rcv, 1);
58238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
58248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version < 700000
58268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sbunlock(&so->so_rcv);
58278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
58288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
58298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen restart_nosblocks:
58308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hold_sblock == 0) {
58318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_LOCK(&so->so_rcv);
58328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hold_sblock = 1;
58338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
58348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
58358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
58368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
58378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
58388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__)
583947674b651417d493ff4e0318113fd7beeef119dbtuexen	if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) && (so->so_rcv.sb_cc == 0)) {
58408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
584147674b651417d493ff4e0318113fd7beeef119dbtuexen	if ((so->so_state & SS_CANTRCVMORE) && (so->so_rcv.sb_cc == 0)) {
58428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
58438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (so->so_error) {
58448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = so->so_error;
58458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((in_flags & MSG_PEEK) == 0)
58468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				so->so_error = 0;
58478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out;
58488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
58498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (so->so_rcv.sb_cc == 0) {
58508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* indicate EOF */
58518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = 0;
58528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto out;
58538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
58548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
58558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
58568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((so->so_rcv.sb_cc <= held_length) && block_allowed) {
58578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we need to wait for data */
58588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((so->so_rcv.sb_cc == 0) &&
58598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
58608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
58618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
58628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* For active open side clear flags for re-use
58638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * passive open is blocked by connect.
58648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
58658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) {
58668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* You were aborted, passive side always hits here */
58678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
58688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					error = ECONNRESET;
58698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				so->so_state &= ~(SS_ISCONNECTING |
58718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						  SS_ISDISCONNECTING |
58728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						  SS_ISCONFIRMING |
58738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						  SS_ISCONNECTED);
58748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (error == 0) {
58758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
58768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
58778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						error = ENOTCONN;
58788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
58798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
58808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto out;
58818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
58828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
58838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sbwait(&so->so_rcv);
58848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error) {
58858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto out;
58868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
58878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		held_length = 0;
58888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto restart_nosblocks;
58898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (so->so_rcv.sb_cc == 0) {
58908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (so->so_error) {
58918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = so->so_error;
58928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((in_flags & MSG_PEEK) == 0)
58938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				so->so_error = 0;
58948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
58958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
58968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
58978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
58988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* For active open side clear flags for re-use
58998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * passive open is blocked by connect.
59008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
59018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) {
59028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* You were aborted, passive side always hits here */
59038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
59048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						error = ECONNRESET;
59058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
59068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					so->so_state &= ~(SS_ISCONNECTING |
59078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							  SS_ISDISCONNECTING |
59088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							  SS_ISCONFIRMING |
59098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							  SS_ISCONNECTED);
59108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (error == 0) {
59118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
59128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
59138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							error = ENOTCONN;
59148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
59158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
59168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					goto out;
59178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
59188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
59198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EWOULDBLOCK);
59208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = EWOULDBLOCK;
59218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
59228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
59238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
59248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hold_sblock == 1) {
59258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_UNLOCK(&so->so_rcv);
59268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hold_sblock = 0;
59278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
59288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
59298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = sblock(&so->so_rcv, SBLOCKWAIT(in_flags));
59308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
59318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version < 700000
59328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = sblock(&so->so_rcv, (block_allowed ? M_WAITOK : 0));
59338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
59348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* we possibly have data we can read */
59358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*sa_ignore FREED_MEMORY*/
59368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control = TAILQ_FIRST(&inp->read_queue);
59378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control == NULL) {
59388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* This could be happening since
59398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the appender did the increment but as not
59408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * yet did the tailq insert onto the read_queue
59418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
59428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hold_rlock == 0) {
59438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_LOCK(inp);
59448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
59458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control = TAILQ_FIRST(&inp->read_queue);
59468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((control == NULL) && (so->so_rcv.sb_cc != 0)) {
59478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
59488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			panic("Huh, its non zero and nothing on control?");
59498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
59508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			so->so_rcv.sb_cc = 0;
59518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
59528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_UNLOCK(inp);
59538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hold_rlock = 0;
59548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto restart;
59558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
59568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
59578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((control->length == 0) &&
59588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (control->do_not_ref_stcb)) {
59598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Clean up code for freeing assoc that left behind a pdapi..
59608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * maybe a peer in EEOR that just closed after sending and
59618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * never indicated a EOR.
59628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
59638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hold_rlock == 0) {
59648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hold_rlock = 1;
59658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_LOCK(inp);
59668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
59678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->held_length = 0;
59688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control->data) {
59698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Hmm there is data here .. fix */
59708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct mbuf *m_tmp;
5971b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			int cnt = 0;
59728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m_tmp = control->data;
59738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			while (m_tmp) {
59748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				cnt += SCTP_BUF_LEN(m_tmp);
59758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_BUF_NEXT(m_tmp) == NULL) {
59768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control->tail_mbuf = m_tmp;
59778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control->end_added = 1;
59788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
59798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				m_tmp = SCTP_BUF_NEXT(m_tmp);
59808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
59818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			control->length = cnt;
59828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
59838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* remove it */
59848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&inp->read_queue, control, next);
59858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Add back any hiddend data */
59868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_remote_addr(control->whoFrom);
59878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_a_readq(stcb, control);
59888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
59898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hold_rlock) {
59908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hold_rlock = 0;
59918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_UNLOCK(inp);
59928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
59938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto restart;
59948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
59958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((control->length == 0) &&
59968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (control->end_added == 1)) {
59978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Do we also need to check for (control->pdapi_aborted == 1)? */
59988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hold_rlock == 0) {
59998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hold_rlock = 1;
60008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_LOCK(inp);
60018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
60028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_REMOVE(&inp->read_queue, control, next);
60038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control->data) {
60048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
60058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			panic("control->data not null but control->length == 0");
60068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
60078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("Strange, data left in the control buffer. Cleaning up.\n");
60088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(control->data);
60098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			control->data = NULL;
60108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
60118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
60128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control->aux_data) {
60138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_free (control->aux_data);
60148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			control->aux_data = NULL;
60158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
60168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_remote_addr(control->whoFrom);
60178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_a_readq(stcb, control);
60188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hold_rlock) {
60198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hold_rlock = 0;
60208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_UNLOCK(inp);
60218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
60228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto restart;
60238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
60248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (control->length == 0) {
60258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) &&
60268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (filling_sinfo)) {
60278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* find a more suitable one then this */
60288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ctl = TAILQ_NEXT(control, next);
60298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			while (ctl) {
60308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((ctl->stcb != control->stcb) && (ctl->length) &&
60318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (ctl->some_taken ||
60328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     (ctl->spec_flags & M_NOTIFICATION) ||
60338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     ((ctl->do_not_ref_stcb == 0) &&
60348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				      (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0)))
60358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					) {
60368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*-
60378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * If we have a different TCB next, and there is data
60388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * present. If we have already taken some (pdapi), OR we can
60398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * ref the tcb and no delivery as started on this stream, we
60408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * take it. Note we allow a notification on a different
60418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * assoc to be delivered..
60428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
60438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control = ctl;
60448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					goto found_one;
60458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) &&
60468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					   (ctl->length) &&
60478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					   ((ctl->some_taken) ||
60488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    ((ctl->do_not_ref_stcb == 0) &&
60498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     ((ctl->spec_flags & M_NOTIFICATION) == 0) &&
60508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					     (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0)))) {
60518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*-
60528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * If we have the same tcb, and there is data present, and we
60538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * have the strm interleave feature present. Then if we have
60548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * taken some (pdapi) or we can refer to tht tcb AND we have
60558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * not started a delivery for this stream, we can take it.
60568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * Note we do NOT allow a notificaiton on the same assoc to
60578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * be delivered.
60588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
60598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control = ctl;
60608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					goto found_one;
60618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
60628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				ctl = TAILQ_NEXT(ctl, next);
60638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
60648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
60658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
60668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * if we reach here, not suitable replacement is available
60678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * <or> fragment interleave is NOT on. So stuff the sb_cc
60688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * into the our held count, and its time to sleep again.
60698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
60708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		held_length = so->so_rcv.sb_cc;
60718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->held_length = so->so_rcv.sb_cc;
60728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto restart;
60738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
60748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Clear the held length since there is something to read */
60758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->held_length = 0;
60768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hold_rlock) {
60778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_UNLOCK(inp);
60788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hold_rlock = 0;
60798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
60808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen found_one:
60818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
60828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * If we reach here, control has a some data for us to read off.
60838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Note that stcb COULD be NULL.
60848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
60858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	control->some_taken++;
60868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hold_sblock) {
60878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_UNLOCK(&so->so_rcv);
60888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hold_sblock = 0;
60898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
60908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb = control->stcb;
60918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
60928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((control->do_not_ref_stcb == 0) &&
60938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) {
60948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (freecnt_applied == 0)
60958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb = NULL;
60968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (control->do_not_ref_stcb == 0) {
60978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* you can't free it on me please */
60988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
60998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * The lock on the socket buffer protects us so the
61008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * free code will stop. But since we used the socketbuf
61018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * lock and the sender uses the tcb_lock to increment,
61028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * we need to use the atomic add to the refcnt
61038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
61048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (freecnt_applied) {
61058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
61068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				panic("refcnt already incremented");
61078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
610847a306d634abf33223ef347472c4b1cd441d139ftuexen				SCTP_PRINTF("refcnt already incremented?\n");
61098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
61108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
61118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				atomic_add_int(&stcb->asoc.refcnt, 1);
61128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				freecnt_applied = 1;
61138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
61158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Setup to remember how much we have not yet told
61168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * the peer our rwnd has opened up. Note we grab
61178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * the value from the tcb from last time.
61188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * Note too that sack sending clears this when a sack
61198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * is sent, which is fine. Once we hit the rwnd_req,
61208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * we then will go to the sctp_user_rcvd() that will
61218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * not lock until it KNOWs it MUST send a WUP-SACK.
61228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
61238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			freed_so_far = stcb->freed_by_sorcv_sincelast;
61248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->freed_by_sorcv_sincelast = 0;
61258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
61268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen        }
61278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb &&
61288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    ((control->spec_flags & M_NOTIFICATION) == 0) &&
61298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    control->do_not_ref_stcb == 0) {
61308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.strmin[control->sinfo_stream].delivery_started = 1;
61318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
61328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
61338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* First lets get off the sinfo and sockaddr info */
61348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((sinfo) && filling_sinfo) {
61358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(sinfo, control, sizeof(struct sctp_nonpad_sndrcvinfo));
61368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		nxt = TAILQ_NEXT(control, next);
61378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) ||
61388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) {
61398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_extrcvinfo *s_extra;
61408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			s_extra = (struct sctp_extrcvinfo *)sinfo;
61418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((nxt) &&
61428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (nxt->length)) {
61438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				s_extra->sreinfo_next_flags = SCTP_NEXT_MSG_AVAIL;
61448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (nxt->sinfo_flags & SCTP_UNORDERED) {
61458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED;
61468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
61478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (nxt->spec_flags & M_NOTIFICATION) {
61488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION;
61498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
61508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				s_extra->sreinfo_next_aid = nxt->sinfo_assoc_id;
61518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				s_extra->sreinfo_next_length = nxt->length;
61528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				s_extra->sreinfo_next_ppid = nxt->sinfo_ppid;
61538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				s_extra->sreinfo_next_stream = nxt->sinfo_stream;
61548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (nxt->tail_mbuf != NULL) {
61558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (nxt->end_added) {
61568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE;
61578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
61588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
61598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
61608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* we explicitly 0 this, since the memcpy got
61618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * some other things beyond the older sinfo_
61628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * that is on the control's structure :-D
61638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
61648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				nxt = NULL;
61658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG;
61668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				s_extra->sreinfo_next_aid = 0;
61678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				s_extra->sreinfo_next_length = 0;
61688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				s_extra->sreinfo_next_ppid = 0;
61698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				s_extra->sreinfo_next_stream = 0;
61708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
61728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
61738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * update off the real current cum-ack, if we have an stcb.
61748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
61758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((control->do_not_ref_stcb == 0) && stcb)
61768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sinfo->sinfo_cumtsn = stcb->asoc.cumulative_tsn;
61778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
61788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * mask off the high bits, we keep the actual chunk bits in
61798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * there.
61808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
61818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sinfo->sinfo_flags &= 0x00ff;
61828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((control->sinfo_flags >> 8) & SCTP_DATA_UNORDERED) {
61838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sinfo->sinfo_flags |= SCTP_UNORDERED;
61848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
61858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
61868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_ASOCLOG_OF_TSNS
61878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
61888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int index, newindex;
61898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_pcbtsn_rlog *entry;
61908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		do {
61918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			index = inp->readlog_index;
61928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			newindex = index + 1;
61938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (newindex >= SCTP_READ_LOG_SIZE) {
61948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				newindex = 0;
61958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
61968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} while (atomic_cmpset_int(&inp->readlog_index, index, newindex) == 0);
61978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		entry = &inp->readlog[index];
61988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		entry->vtag = control->sinfo_assoc_id;
61998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		entry->strm = control->sinfo_stream;
62008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		entry->seq = control->sinfo_ssn;
62018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		entry->sz = control->length;
62028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		entry->flgs = control->sinfo_flags;
62038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
62048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
62058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (fromlen && from) {
6206f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
6207314c1b3e200a8767983b36e7956f254e6c3ce322tuexen		cp_len = min((size_t)fromlen, (size_t)control->whoFrom->ro._l_addr.sa.sa_len);
62088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
6209314c1b3e200a8767983b36e7956f254e6c3ce322tuexen		switch (control->whoFrom->ro._l_addr.sa.sa_family) {
6210314c1b3e200a8767983b36e7956f254e6c3ce322tuexen#ifdef INET6
6211314c1b3e200a8767983b36e7956f254e6c3ce322tuexen			case AF_INET6:
6212f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifndef HAVE_SA_LEN
6213314c1b3e200a8767983b36e7956f254e6c3ce322tuexen				cp_len = min((size_t)fromlen, sizeof(struct sockaddr_in6));
62148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
6215314c1b3e200a8767983b36e7956f254e6c3ce322tuexen				((struct sockaddr_in6 *)from)->sin6_port = control->port_from;
6216314c1b3e200a8767983b36e7956f254e6c3ce322tuexen				break;
62178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
6218314c1b3e200a8767983b36e7956f254e6c3ce322tuexen#ifdef INET
6219314c1b3e200a8767983b36e7956f254e6c3ce322tuexen			case AF_INET:
6220f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifndef HAVE_SA_LEN
6221314c1b3e200a8767983b36e7956f254e6c3ce322tuexen				cp_len = min((size_t)fromlen, sizeof(struct sockaddr_in));
6222314c1b3e200a8767983b36e7956f254e6c3ce322tuexen#endif
6223314c1b3e200a8767983b36e7956f254e6c3ce322tuexen				((struct sockaddr_in *)from)->sin_port = control->port_from;
6224314c1b3e200a8767983b36e7956f254e6c3ce322tuexen				break;
6225314c1b3e200a8767983b36e7956f254e6c3ce322tuexen#endif
622666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__)
622766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			case AF_CONN:
6228f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifndef HAVE_SA_LEN
622966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				cp_len = min((size_t)fromlen, sizeof(struct sockaddr_conn));
623066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif
623166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				((struct sockaddr_conn *)from)->sconn_port = control->port_from;
623266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				break;
623366e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif
6234314c1b3e200a8767983b36e7956f254e6c3ce322tuexen			default:
6235f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifndef HAVE_SA_LEN
6236314c1b3e200a8767983b36e7956f254e6c3ce322tuexen				cp_len = min((size_t)fromlen, sizeof(struct sockaddr));
6237314c1b3e200a8767983b36e7956f254e6c3ce322tuexen#endif
6238314c1b3e200a8767983b36e7956f254e6c3ce322tuexen				break;
6239314c1b3e200a8767983b36e7956f254e6c3ce322tuexen		}
6240314c1b3e200a8767983b36e7956f254e6c3ce322tuexen		memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
62418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
62428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(INET) && defined(INET6)
62438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((sctp_is_feature_on(inp,SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
6244314c1b3e200a8767983b36e7956f254e6c3ce322tuexen		    (from->sa_family == AF_INET) &&
62458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((size_t)fromlen >= sizeof(struct sockaddr_in6))) {
62468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr_in *sin;
62478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr_in6 sin6;
62488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6249314c1b3e200a8767983b36e7956f254e6c3ce322tuexen			sin = (struct sockaddr_in *)from;
62508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bzero(&sin6, sizeof(sin6));
62518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin6.sin6_family = AF_INET6;
62527b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
62538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin6.sin6_len = sizeof(struct sockaddr_in6);
62548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
625523273859c39742f09cc5ec7c9bf32ff225661e82tuexen#if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Darwin) || defined(__Userspace_os_Windows)
6256314c1b3e200a8767983b36e7956f254e6c3ce322tuexen			((uint32_t *)&sin6.sin6_addr)[2] = htonl(0xffff);
62578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bcopy(&sin->sin_addr,
6258314c1b3e200a8767983b36e7956f254e6c3ce322tuexen			      &(((uint32_t *)&sin6.sin6_addr)[3]),
6259314c1b3e200a8767983b36e7956f254e6c3ce322tuexen			      sizeof(uint32_t));
62608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#elif defined(__Windows__)
62618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			((uint32_t *)&sin6.sin6_addr)[2] = htonl(0xffff);
62628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bcopy(&sin->sin_addr,
62638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			      &((uint32_t *)&sin6.sin6_addr)[3],
62648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			      sizeof(uint32_t));
62658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
62668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
62678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bcopy(&sin->sin_addr,
62688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			      &sin6.sin6_addr.s6_addr32[3],
62698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			      sizeof(sin6.sin6_addr.s6_addr32[3]));
62708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
62718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin6.sin6_port = sin->sin_port;
6272314c1b3e200a8767983b36e7956f254e6c3ce322tuexen			memcpy(from, &sin6, sizeof(struct sockaddr_in6));
62738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
62748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
62758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE)
6276e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET6
62778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
6278314c1b3e200a8767983b36e7956f254e6c3ce322tuexen			struct sockaddr_in6 lsa6, *from6;
6279314c1b3e200a8767983b36e7956f254e6c3ce322tuexen
6280314c1b3e200a8767983b36e7956f254e6c3ce322tuexen			from6 = (struct sockaddr_in6 *)from;
6281314c1b3e200a8767983b36e7956f254e6c3ce322tuexen			sctp_recover_scope_mac(from6, (&lsa6));
62828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
62838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
62848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
62858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
62868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* now copy out what data we can */
62878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (mp == NULL) {
62888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* copy out each mbuf in the chain up to length */
62898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	get_more_data:
62908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m = control->data;
62918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		while (m) {
62928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Move out all we can */
62938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
62941ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD)
62958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cp_len = (int)uio->uio_resid;
62961ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#else
62971ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen			cp_len = (int)uio_resid(uio);
62988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
62998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
63008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cp_len = (int)uio->uio_resid;
63018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
63028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			my_len = (int)SCTP_BUF_LEN(m);
63038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (cp_len > my_len) {
63048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* not enough in this buf */
63058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				cp_len = my_len;
63068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
63078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (hold_rlock) {
63088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_READ_UNLOCK(inp);
63098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				hold_rlock = 0;
63108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
63118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
63128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_UNLOCK(so, 0);
63138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
63148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (cp_len > 0)
63158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				error = uiomove(mtod(m, char *), cp_len, uio);
63168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
63178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_SOCKET_LOCK(so, 0);
63188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
63198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* re-read */
63208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
63218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto release;
63228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
63238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
63248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((control->do_not_ref_stcb == 0) && stcb &&
63258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
63268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				no_rcv_needed = 1;
63278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
63288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (error) {
63298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* error we are out of here */
63308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto release;
63318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
63328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((SCTP_BUF_NEXT(m) == NULL) &&
63338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (cp_len >= SCTP_BUF_LEN(m)) &&
63348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    ((control->end_added == 0) ||
63358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			     (control->end_added &&
63368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			      (TAILQ_NEXT(control, next) == NULL)))
63378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				) {
63388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_READ_LOCK(inp);
63398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				hold_rlock = 1;
63408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
63418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (cp_len == SCTP_BUF_LEN(m)) {
63428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((SCTP_BUF_NEXT(m)== NULL) &&
63438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (control->end_added)) {
63448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					out_flags |= MSG_EOR;
63458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((control->do_not_ref_stcb == 0)  &&
63468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (control->stcb != NULL) &&
63478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    ((control->spec_flags & M_NOTIFICATION) == 0))
63488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
63498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
63508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (control->spec_flags & M_NOTIFICATION) {
63518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					out_flags |= MSG_NOTIFICATION;
63528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
63538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* we ate up the mbuf */
63548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (in_flags & MSG_PEEK) {
63558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* just looking */
63568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					m = SCTP_BUF_NEXT(m);
63578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					copied_so_far += cp_len;
63588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
63598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* dispose of the mbuf */
63608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
63618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_sblog(&so->so_rcv,
63628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						   control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m));
63638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
63648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_sbfree(control, stcb, &so->so_rcv, m);
63658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
63668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_sblog(&so->so_rcv,
63678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						   control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
63688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
63698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					copied_so_far += cp_len;
63708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					freed_so_far += cp_len;
63718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					freed_so_far += MSIZE;
63728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					atomic_subtract_int(&control->length, cp_len);
63738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control->data = sctp_m_free(m);
63748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					m = control->data;
63758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* been through it all, must hold sb lock ok to null tail */
63768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (control->data == NULL) {
63778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
63788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__APPLE__)
63798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((control->end_added == 0) ||
63808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (TAILQ_NEXT(control, next) == NULL)) {
63818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							/* If the end is not added, OR the
63828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 * next is NOT null we MUST have the lock.
63838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 */
63848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (mtx_owned(&inp->inp_rdata_mtx) == 0) {
63858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								panic("Hmm we don't own the lock?");
63868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
63878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
63888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
63898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
63908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						control->tail_mbuf = NULL;
63918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
63928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((control->end_added) && ((out_flags & MSG_EOR) == 0)) {
63938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							panic("end_added, nothing left and no MSG_EOR");
63948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
63958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
63968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
63978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
63988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
63998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Do we need to trim the mbuf? */
64008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (control->spec_flags & M_NOTIFICATION) {
64018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					out_flags |= MSG_NOTIFICATION;
64028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
64038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((in_flags & MSG_PEEK) == 0) {
64048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_BUF_RESV_UF(m, cp_len);
64058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_BUF_LEN(m) -= cp_len;
64068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
64078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_sblog(&so->so_rcv, control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE, cp_len);
64088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
64098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					atomic_subtract_int(&so->so_rcv.sb_cc, cp_len);
6410b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen					if ((control->do_not_ref_stcb == 0) &&
64118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    stcb) {
64128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						atomic_subtract_int(&stcb->asoc.sb_cc, cp_len);
64138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
64148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					copied_so_far += cp_len;
64158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					freed_so_far += cp_len;
64168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					freed_so_far += MSIZE;
64178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
64188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_sblog(&so->so_rcv, control->do_not_ref_stcb?NULL:stcb,
64198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							   SCTP_LOG_SBRESULT, 0);
64208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
64218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					atomic_subtract_int(&control->length, cp_len);
64228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
64238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					copied_so_far += cp_len;
64248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
64258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
64271ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD)
64288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((out_flags & MSG_EOR) || (uio->uio_resid == 0)) {
64291ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#else
64301ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen			if ((out_flags & MSG_EOR) || (uio_resid(uio) == 0)) {
64318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
64328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
64338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((out_flags & MSG_EOR) || (uio->uio_resid == 0)) {
64348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
64358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
64368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (((stcb) && (in_flags & MSG_PEEK) == 0) &&
64388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (control->do_not_ref_stcb == 0) &&
64398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (freed_so_far >= rwnd_req)) {
64408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
64418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
64428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} /* end while(m) */
64438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
64448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * At this point we have looked at it all and we either have
64458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * a MSG_EOR/or read all the user wants... <OR>
64468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * control->length == 0.
64478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
64488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((out_flags & MSG_EOR) && ((in_flags & MSG_PEEK) == 0)) {
64498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* we are done with this control */
64508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (control->length == 0) {
64518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (control->data) {
64528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
64538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					panic("control->data not null at read eor?");
64548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
64558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_PRINTF("Strange, data left in the control buffer .. invarients would panic?\n");
64568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_m_freem(control->data);
64578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control->data = NULL;
64588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
64598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
64608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			done_with_control:
64618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (TAILQ_NEXT(control, next) == NULL) {
64628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* If we don't have a next we need a
64638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * lock, if there is a next interrupt
64648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * is filling ahead of us and we don't
64658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * need a lock to remove this guy
64668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * (which is the head of the queue).
64678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
64688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (hold_rlock == 0) {
64698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_INP_READ_LOCK(inp);
64708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						hold_rlock = 1;
64718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
64728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
64738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				TAILQ_REMOVE(&inp->read_queue, control, next);
64748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Add back any hiddend data */
64758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (control->held_length) {
64768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					held_length = 0;
64778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control->held_length = 0;
64788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					wakeup_read_socket = 1;
64798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
64808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (control->aux_data) {
64818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_m_free (control->aux_data);
64828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					control->aux_data = NULL;
64838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
64848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				no_rcv_needed = control->do_not_ref_stcb;
64858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_remote_addr(control->whoFrom);
64868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				control->data = NULL;
64878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_a_readq(stcb, control);
64888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				control = NULL;
64898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if ((freed_so_far >= rwnd_req) &&
64908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (no_rcv_needed == 0))
64918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
64928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
64938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
64948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
64958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * The user did not read all of this
64968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * message, turn off the returned MSG_EOR
64978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * since we are leaving more behind on the
64988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * control to read.
64998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
65008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
65018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (control->end_added &&
65028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (control->data == NULL) &&
65038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    (control->tail_mbuf == NULL)) {
65048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					panic("Gak, control->length is corrupt?");
65058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
65068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
65078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				no_rcv_needed = control->do_not_ref_stcb;
65088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				out_flags &= ~MSG_EOR;
65098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
65108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (out_flags & MSG_EOR) {
65128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto release;
65138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
65151ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD)
65168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((uio->uio_resid == 0) ||
65171ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#else
65181ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen		if ((uio_resid(uio) == 0) ||
65198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
65208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
65218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((uio->uio_resid == 0) ||
65228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
652318818c8dd0d4cafdb259fa73f01f7825948faadct		    ((in_eeor_mode) &&
652418818c8dd0d4cafdb259fa73f01f7825948faadct		     (copied_so_far >= (uint32_t)max(so->so_rcv.sb_lowat, 1)))) {
65258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto release;
65268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
65288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * If I hit here the receiver wants more and this message is
65298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * NOT done (pd-api). So two questions. Can we block? if not
65308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * we are done. Did the user NOT set MSG_WAITALL?
65318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
65328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (block_allowed == 0) {
65338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto release;
65348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
65368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * We need to wait for more data a few things: - We don't
65378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * sbunlock() so we don't get someone else reading. - We
65388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * must be sure to account for the case where what is added
65398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * is NOT to our control when we wakeup.
65408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
65418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
65428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Do we need to tell the transport a rwnd update might be
65438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * needed before we go to sleep?
65448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
65458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (((stcb) && (in_flags & MSG_PEEK) == 0) &&
65468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((freed_so_far >= rwnd_req) &&
65478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (control->do_not_ref_stcb == 0) &&
65488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (no_rcv_needed == 0))) {
65498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
65508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	wait_some_more:
65528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__)
65538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
65548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto release;
65558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
65578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (so->so_state & SS_CANTRCVMORE) {
65588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto release;
65598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
65618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
65628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)
65638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto release;
65648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
65658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hold_rlock == 1) {
65668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_UNLOCK(inp);
65678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hold_rlock = 0;
65688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hold_sblock == 0) {
65708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SOCKBUF_LOCK(&so->so_rcv);
65718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hold_sblock = 1;
65728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((copied_so_far) && (control->length == 0) &&
65748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE))) {
65758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto release;
65768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65774b225662b4d798e7046f8c27ae1867b4fe4f4c17t#if defined(__APPLE__)
65784b225662b4d798e7046f8c27ae1867b4fe4f4c17t		sbunlock(&so->so_rcv, 1);
65794b225662b4d798e7046f8c27ae1867b4fe4f4c17t#endif
65808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (so->so_rcv.sb_cc <= control->held_length) {
65818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = sbwait(&so->so_rcv);
65828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (error) {
65838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__)
65848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto release;
65858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
65868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto release_unlocked;
65878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
65888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
65898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			control->held_length = 0;
65908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
65928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sblock(&so->so_rcv, SBLOCKWAIT(in_flags));
65938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
65948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (hold_sblock) {
65958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SOCKBUF_UNLOCK(&so->so_rcv);
65968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			hold_sblock = 0;
65978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
65988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control->length == 0) {
65998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* still nothing here */
66008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (control->end_added == 1) {
66018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* he aborted, or is done i.e.did a shutdown */
66028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				out_flags |= MSG_EOR;
66038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (control->pdapi_aborted) {
66048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0))
66058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
66068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
66078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					out_flags |= MSG_TRUNC;
66088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				} else {
66098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0))
66108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
66118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
66128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto done_with_control;
66138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
66148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (so->so_rcv.sb_cc > held_length) {
66158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				control->held_length = so->so_rcv.sb_cc;
66168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				held_length = 0;
66178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
66188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto wait_some_more;
66198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (control->data == NULL) {
66208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* we must re-sync since data
66218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * is probably being added
66228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
66238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_LOCK(inp);
66248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((control->length > 0) && (control->data == NULL)) {
66258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* big trouble.. we have the lock and its corrupt? */
66268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
66278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				panic ("Impossible data==NULL length !=0");
66288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
66298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				out_flags |= MSG_EOR;
66308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				out_flags |= MSG_TRUNC;
66318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				control->length = 0;
66328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_READ_UNLOCK(inp);
66338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto done_with_control;
66348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
66358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_READ_UNLOCK(inp);
66368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* We will fall around to get more data */
66378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
66388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto get_more_data;
66398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
66408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*-
66418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Give caller back the mbuf chain,
66428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * store in uio_resid the length
66438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
66448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		wakeup_read_socket = 0;
66458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((control->end_added == 0) ||
66468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (TAILQ_NEXT(control, next) == NULL)) {
66478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Need to get rlock */
66488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (hold_rlock == 0) {
66498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_INP_READ_LOCK(inp);
66508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				hold_rlock = 1;
66518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
66528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
66538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control->end_added) {
66548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			out_flags |= MSG_EOR;
6655b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			if ((control->do_not_ref_stcb == 0) &&
6656b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			    (control->stcb != NULL) &&
6657b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			    ((control->spec_flags & M_NOTIFICATION) == 0))
66588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
66598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
66608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (control->spec_flags & M_NOTIFICATION) {
66618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			out_flags |= MSG_NOTIFICATION;
66628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
66638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
66641ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD)
66658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uio->uio_resid = control->length;
66661ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#else
66671ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen		uio_setresid(uio, control->length);
66688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
66698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
66708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uio->uio_resid = control->length;
66718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
66728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*mp = control->data;
66738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m = control->data;
66748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		while (m) {
66758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
66768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_sblog(&so->so_rcv,
66778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				   control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m));
66788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
66798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_sbfree(control, stcb, &so->so_rcv, m);
66808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			freed_so_far += SCTP_BUF_LEN(m);
66818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			freed_so_far += MSIZE;
66828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
66838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_sblog(&so->so_rcv,
66848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				   control->do_not_ref_stcb?NULL:stcb, SCTP_LOG_SBRESULT, 0);
66858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
66868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m = SCTP_BUF_NEXT(m);
66878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
66888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->data = control->tail_mbuf = NULL;
66898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		control->length = 0;
66908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (out_flags & MSG_EOR) {
66918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Done with this control */
66928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto done_with_control;
66938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
66948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
66958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen release:
66968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hold_rlock == 1) {
66978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_UNLOCK(inp);
66988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hold_rlock = 0;
66998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version < 700000) || defined(__Userspace__)
67018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hold_sblock == 0) {
67028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_LOCK(&so->so_rcv);
67038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hold_sblock = 1;
67048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
67068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hold_sblock == 1) {
67078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_UNLOCK(&so->so_rcv);
67088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hold_sblock = 0;
67098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
67128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sbunlock(&so->so_rcv, 1);
67138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
67158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__)
67168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sbunlock(&so->so_rcv);
67178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 700000
67188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sockbuf_lock = 0;
67198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
67228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen release_unlocked:
67238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hold_sblock) {
67248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_UNLOCK(&so->so_rcv);
67258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hold_sblock = 0;
67268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((stcb) && (in_flags & MSG_PEEK) == 0) {
67288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((freed_so_far >= rwnd_req) &&
67298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (control && (control->do_not_ref_stcb == 0)) &&
67308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (no_rcv_needed == 0))
67318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
67328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out:
67348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (msg_flags) {
67358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*msg_flags = out_flags;
67368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (((out_flags & MSG_EOR) == 0) &&
67388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    ((in_flags & MSG_PEEK) == 0) &&
67398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (sinfo) &&
67408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) ||
67418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO))) {
67428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_extrcvinfo *s_extra;
67438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		s_extra = (struct sctp_extrcvinfo *)sinfo;
67448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG;
67458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hold_rlock == 1) {
67478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_READ_UNLOCK(inp);
67488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hold_sblock) {
67508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SOCKBUF_UNLOCK(&so->so_rcv);
67518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) && __FreeBSD_version >= 700000
67538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sockbuf_lock) {
67548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sbunlock(&so->so_rcv);
67558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
67588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (freecnt_applied) {
67598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
67608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * The lock on the socket buffer protects us so the free
67618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * code will stop. But since we used the socketbuf lock and
67628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the sender uses the tcb_lock to increment, we need to use
67638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * the atomic add to the refcnt.
67648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
67658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb == NULL) {
67668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
67678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			panic("stcb for refcnt has gone NULL?");
67688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto stage_left;
67698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
67708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto stage_left;
67718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
67738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&stcb->asoc.refcnt, -1);
67748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Save the value back for next time */
67758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->freed_by_sorcv_sincelast = freed_so_far;
67768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
67778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) &SCTP_RECV_RWND_LOGGING_ENABLE) {
67788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
67798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_misc_ints(SCTP_SORECV_DONE,
67808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       freed_so_far,
67818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
67821ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD)
67831ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen				       ((uio) ? (slen - uio->uio_resid) : slen),
67848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
67851ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen				       ((uio) ? (slen - uio_resid(uio)) : slen),
67868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
67881ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen				       ((uio) ? (slen - uio->uio_resid) : slen),
67898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
67908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       stcb->asoc.my_rwnd,
67918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       so->so_rcv.sb_cc);
67928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
67938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_misc_ints(SCTP_SORECV_DONE,
67948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       freed_so_far,
67958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
67961ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen#if defined(APPLE_LEOPARD)
67971ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen				       ((uio) ? (slen - uio->uio_resid) : slen),
67988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
67991ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen				       ((uio) ? (slen - uio_resid(uio)) : slen),
68008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
68021ebe9fa737dc60b9cb716812477d62f9b4107f53tuexen				       ((uio) ? (slen - uio->uio_resid) : slen),
68038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       0,
68058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       so->so_rcv.sb_cc);
68068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
68078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
68088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen stage_left:
68098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (wakeup_read_socket) {
68108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_sorwakeup(inp, so);
68118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
68128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
68138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
68148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MBUF_LOGGING
68178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct mbuf *
68188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_m_free(struct mbuf *m)
68198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
68208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
68218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BUF_IS_EXTENDED(m)) {
68228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_log_mb(m, SCTP_MBUF_IFREE);
68238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
68248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
68258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (m_free(m));
68268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
68278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid sctp_m_freem(struct mbuf *mb)
68298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
68308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (mb != NULL)
68318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		mb = sctp_m_free(mb);
68328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
68338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
68378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
68388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
68398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Given a local address. For all associations
68408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * that holds the address, request a peer-set-primary.
68418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
68428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *ifa;
68438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_laddr *wi;
68448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
68468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ifa == NULL) {
68478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EADDRNOTAVAIL);
68488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EADDRNOTAVAIL);
68498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
68508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now that we have the ifa we must awaken the
68518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * iterator with this message.
68528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
68538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr);
68548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (wi == NULL) {
68558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
68568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ENOMEM);
68578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
68588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now incr the count and int wi structure */
68598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_INCR_LADDR_COUNT();
68608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(wi, sizeof(*wi));
68618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	(void)SCTP_GETTIME_TIMEVAL(&wi->start_time);
68628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	wi->ifa = ifa;
68638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	wi->action = SCTP_SET_PRIM_ADDR;
68648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&ifa->refcount, 1);
68658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now add it to the work queue */
68678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_WQ_ADDR_LOCK();
68688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
68698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Should this really be a tailq? As it is we will process the
68708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * newest first :-0
68718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
68728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr);
68738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_WQ_ADDR_UNLOCK();
68748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
68758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 (struct sctp_inpcb *)NULL,
68768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 (struct sctp_tcb *)NULL,
68778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 (struct sctp_nets *)NULL);
68788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
68798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
68808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Userspace__)
68828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* no sctp_soreceive for __Userspace__ now */
68838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
68848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
68858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !defined(__Userspace__)
68868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
68878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_soreceive(	struct socket *so,
68888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr **psa,
68898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct uio *uio,
68908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct mbuf **mp0,
68918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct mbuf **controlp,
68928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		int *flagsp)
68938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
68948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error, fromlen;
68958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t sockbuf[256];
68968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *from;
68978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_extrcvinfo sinfo;
68988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int filling_sinfo = 1;
68998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
69008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
69018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = (struct sctp_inpcb *)so->so_pcb;
69028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* pickup the assoc we are reading from */
69038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp == NULL) {
69048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
69058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EINVAL);
69068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) &&
69088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
69098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) ||
69108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (controlp == NULL)) {
69118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* user does not want the sndrcv ctl */
69128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		filling_sinfo = 0;
69138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (psa) {
69158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		from = (struct sockaddr *)sockbuf;
69168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		fromlen = sizeof(sockbuf);
6917f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
69188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		from->sa_len = 0;
69198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
69208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
69218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		from = NULL;
69228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		fromlen = 0;
69238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
69258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
69268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_SOCKET_LOCK(so, 1);
69278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
6928f496fe99adbad377f85add3a45e17f21a4702b41t	if (filling_sinfo) {
6929f496fe99adbad377f85add3a45e17f21a4702b41t		memset(&sinfo, 0, sizeof(struct sctp_extrcvinfo));
6930f496fe99adbad377f85add3a45e17f21a4702b41t	}
69318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, flagsp,
69328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (struct sctp_sndrcvinfo *)&sinfo, filling_sinfo);
6933f496fe99adbad377f85add3a45e17f21a4702b41t	if (controlp != NULL) {
69348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* copy back the sinfo in a CMSG format */
69358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (filling_sinfo)
69368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*controlp = sctp_build_ctl_nchunk(inp,
69378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                                  (struct sctp_sndrcvinfo *)&sinfo);
69388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else
69398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*controlp = NULL;
69408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (psa) {
69428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* copy back the address info */
6943f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
69448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (from && from->sa_len) {
69458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
69468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (from) {
69478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
69488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version > 500000) || defined(__Windows__)
69498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*psa = sodupsockaddr(from, M_NOWAIT);
69508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
69518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*psa = dup_sockaddr(from, mp0 == 0);
69528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
69538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
69548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*psa = NULL;
69558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
69568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
69588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_SOCKET_UNLOCK(so, 1);
69598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
69608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (error);
69618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
69628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
69638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
69648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if (defined(__FreeBSD__) && __FreeBSD_version < 603000) || defined(__Windows__)
69658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
69668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * General routine to allocate a hash table with control of memory flags.
69678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * is in 7.0 and beyond for sure :-)
69688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
69698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid *
69708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hashinit_flags(int elements, struct malloc_type *type,
69718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                    u_long *hashmask, int flags)
69728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
69738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	long hashsize;
69748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_HEAD(generic, generic) *hashtbl;
69758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
69768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
69778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
69788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (elements <= 0) {
69798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
69808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		panic("hashinit: bad elements");
69818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
698247a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("hashinit: bad elements?");
69838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		elements = 1;
69848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
69858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
69868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
69878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		continue;
69888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	hashsize >>= 1;
69898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (flags & HASH_WAITOK)
69908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_WAITOK);
69918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else if (flags & HASH_NOWAIT)
69928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl), type, M_NOWAIT);
69938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else {
69948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
69958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		panic("flag incorrect in hashinit_flags");
69968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
69978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
69988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
69998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
70008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* no memory? */
70028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hashtbl == NULL)
70038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
70048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < hashsize; i++)
70068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_INIT(&hashtbl[i]);
70078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*hashmask = hashsize - 1;
70088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (hashtbl);
70098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
70108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
70118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else /*  __Userspace__ ifdef above sctp_soreceive */
70138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
70148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * __Userspace__ Defining sctp_hashinit_flags() and sctp_hashdestroy() for userland.
70158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: We don't want multiple definitions here. So sctp_hashinit_flags() above for
70168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *__FreeBSD__ must be excluded.
70178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
70188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
70198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid *
70218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hashinit_flags(int elements, struct malloc_type *type,
70228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                    u_long *hashmask, int flags)
70238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
70248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	long hashsize;
70258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_HEAD(generic, generic) *hashtbl;
70268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
70278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (elements <= 0) {
702947a306d634abf33223ef347472c4b1cd441d139ftuexen		SCTP_PRINTF("hashinit: bad elements?");
70308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
703147a306d634abf33223ef347472c4b1cd441d139ftuexen		return (NULL);
70328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
70338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		elements = 1;
70348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
70358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
70368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (hashsize = 1; hashsize <= elements; hashsize <<= 1)
70378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		continue;
70388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	hashsize >>= 1;
70398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*cannot use MALLOC here because it has to be declared or defined
70408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	  using MALLOC_DECLARE or MALLOC_DEFINE first. */
70418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (flags & HASH_WAITOK)
70428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl));
70438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else if (flags & HASH_NOWAIT)
70448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		hashtbl = malloc((u_long)hashsize * sizeof(*hashtbl));
70458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	else {
70468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INVARIANTS
7047ac15c9a0691d5760c1c3b9b70f6daaaa067b7274t		SCTP_PRINTF("flag incorrect in hashinit_flags.\n");
70488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
704947a306d634abf33223ef347472c4b1cd441d139ftuexen		return (NULL);
70508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
70518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* no memory? */
70538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (hashtbl == NULL)
70548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
70558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < hashsize; i++)
70578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_INIT(&hashtbl[i]);
70588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*hashmask = hashsize - 1;
70598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (hashtbl);
70608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
70618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
70648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hashdestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask)
70658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
70668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_HEAD(generic, generic) *hashtbl, *hp;
70678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	hashtbl = vhashtbl;
70698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++)
70708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!LIST_EMPTY(hp)) {
7071ac15c9a0691d5760c1c3b9b70f6daaaa067b7274t			SCTP_PRINTF("hashdestroy: hash not empty.\n");
70728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
70738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
70748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	FREE(hashtbl, type);
70758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
70768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
70788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
70798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_hashfreedestroy(void *vhashtbl, struct malloc_type *type, u_long hashmask)
70808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
70818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_HEAD(generic, generic) *hashtbl/*, *hp*/;
70828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
70838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_ENTRY(type) *start, *temp;
70848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
70858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	hashtbl = vhashtbl;
70868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Apparently temp is not dynamically allocated, so attempts to
70878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	   free it results in error.
70888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (hp = hashtbl; hp <= &hashtbl[hashmask]; hp++)
70898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (!LIST_EMPTY(hp)) {
70908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			start = LIST_FIRST(hp);
7091b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			while (start != NULL) {
70928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				temp = start;
70938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				start = start->le_next;
7094ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t				SCTP_PRINTF("%s: %p \n", __func__, (void *)temp);
70958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				FREE(temp, type);
70968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
70978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
70988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
70998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	FREE(hashtbl, type);
71008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
71018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
71028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
71038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
71048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
71058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
71068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
71078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
71088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 int totaddr, int *error)
71098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
71108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int added = 0;
71118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i;
71128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
71138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *sa;
71148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	size_t incr = 0;
71158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
71168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin;
71178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
71188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
71198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in6 *sin6;
71208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
71218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
71228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sa = addr;
71238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	inp = stcb->sctp_ep;
71248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*error = 0;
71258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < totaddr; i++) {
71268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (sa->sa_family) {
71278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
71288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case AF_INET:
71298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			incr = sizeof(struct sockaddr_in);
71308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin = (struct sockaddr_in *)sa;
71318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((sin->sin_addr.s_addr == INADDR_ANY) ||
71328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (sin->sin_addr.s_addr == INADDR_BROADCAST) ||
71338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
71348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
71358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7);
71368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*error = EINVAL;
71378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto out_now;
71388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
71398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
71408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* assoc gone no un-lock */
71418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
71428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_7);
71438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*error = ENOBUFS;
71448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto out_now;
71458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
71468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			added++;
71478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
71488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
71498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
71508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case AF_INET6:
71518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			incr = sizeof(struct sockaddr_in6);
71528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin6 = (struct sockaddr_in6 *)sa;
71538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
71548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
71558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
71568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8);
71578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*error = EINVAL;
71588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto out_now;
71598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
71608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
71618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* assoc gone no un-lock */
71628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
71638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8);
71648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*error = ENOBUFS;
71658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				goto out_now;
71668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
71678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			added++;
71688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
71698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
717066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__)
717166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen		case AF_CONN:
717266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			incr = sizeof(struct sockaddr_in6);
717366e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
717466e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				/* assoc gone no un-lock */
717566e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
717666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ+SCTP_LOC_8);
717766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				*error = ENOBUFS;
717866e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				goto out_now;
717966e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			}
718066e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			added++;
718166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen			break;
718266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif
71838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
71848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
71858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
71868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sa = (struct sockaddr *)((caddr_t)sa + incr);
71878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
71888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out_now:
71898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (added);
71908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
71918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
71928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct sctp_tcb *
71938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
71948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  int *totaddr, int *num_v4, int *num_v6, int *error,
71958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  int limit, int *bad_addr)
71968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
71978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *sa;
7198b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	struct sctp_tcb *stcb = NULL;
71998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	size_t incr, at, i;
72008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	at = incr = 0;
72018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sa = addr;
72028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
72038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*error = *num_v6 = *num_v4 = 0;
72048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* account and validate addresses */
72058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < (size_t)*totaddr; i++) {
72068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (sa->sa_family) {
72078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
72088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case AF_INET:
72098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(*num_v4) += 1;
72108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			incr = sizeof(struct sockaddr_in);
7211f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
72128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_len != incr) {
72138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
72148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*error = EINVAL;
72158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*bad_addr = 1;
72168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (NULL);
72178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
72188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
72208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
72228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case AF_INET6:
72238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
72248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr_in6 *sin6;
72258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
72268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sin6 = (struct sockaddr_in6 *)sa;
72278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
72288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Must be non-mapped for connectx */
72298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
72308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*error = EINVAL;
72318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*bad_addr = 1;
72328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (NULL);
72338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
72348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(*num_v6) += 1;
72358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			incr = sizeof(struct sockaddr_in6);
7236f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
72378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_len != incr) {
72388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
72398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*error = EINVAL;
72408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*bad_addr = 1;
72418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (NULL);
72428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
72438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
7245000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		}
72468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
72488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*totaddr = i;
72498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* we are done */
72508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
72518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
72528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (i == (size_t)*totaddr) {
72538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
72548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
72558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_INP_INCR_REF(inp);
72568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL);
72578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb != NULL) {
72588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Already have or am bring up an association */
72598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (stcb);
72608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
72618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_DECR_REF(inp);
72628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
72638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((at + incr) > (size_t)limit) {
72648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*totaddr = i;
72658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
72668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
72678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sa = (struct sockaddr *)((caddr_t)sa + incr);
72688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
72698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return ((struct sctp_tcb *)NULL);
72708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
72718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
72728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
72738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_bindx(ADD) for one address.
72748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assumes all arguments are valid/checked by caller.
72758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
72768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
72778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
72788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       struct sockaddr *sa, sctp_assoc_t assoc_id,
72798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       uint32_t vrf_id, int *error, void *p)
72808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
72818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *addr_touse;
72828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
72838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in sin;
72848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
72868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i, fnd = 0;
72878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
72888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
72898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* see if we're bound all already! */
72908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
72918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
72928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*error = EINVAL;
72938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
72948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
72958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
72968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Is the VRF one we have */
72978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < inp->num_vrfs; i++) {
72988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (vrf_id == inp->m_vrf_ids[i]) {
72998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			fnd = 1;
73008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
73018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!fnd) {
73048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
73058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*error = EINVAL;
73068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
73078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	addr_touse = sa;
73108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
73118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sa->sa_family == AF_INET6) {
73128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6;
7313f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
73148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sa->sa_len != sizeof(struct sockaddr_in6)) {
73158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
73168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = EINVAL;
73178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
73188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
73218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* can only bind v6 on PF_INET6 sockets */
73228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
73238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = EINVAL;
73248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
73258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6 = (struct sockaddr_in6 *)addr_touse;
73278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
73288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
73298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_IPV6_V6ONLY(inp)) {
73308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* can't bind v4-mapped on PF_INET sockets */
73318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
73328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*error = EINVAL;
73338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
73348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
73358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			in6_sin6_2_sin(&sin, sin6);
73368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			addr_touse = (struct sockaddr *)&sin;
73378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
73418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sa->sa_family == AF_INET) {
7342f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
73438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sa->sa_len != sizeof(struct sockaddr_in)) {
73448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
73458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = EINVAL;
73468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
73478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
73508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_IPV6_V6ONLY(inp)) {
73518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* can't bind v4 on PF_INET sockets */
73528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
73538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = EINVAL;
73548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
73558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
73598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if !(defined(__Panda__) || defined(__Windows__))
73608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (p == NULL) {
73618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Can't get proc for Net/Open BSD */
73628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
73638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = EINVAL;
73648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
73658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
73678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*error = sctp_inpcb_bind(so, addr_touse, NULL, p);
73688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
73698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
73708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
73718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * No locks required here since bind and mgmt_ep_sa
73728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * all do their own locking. If we do something for
73738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * the FIX: below we may need to lock in that case.
73748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
73758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (assoc_id == 0) {
73768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* add the address */
73778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_inpcb *lep;
73788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *lsin = (struct sockaddr_in *)addr_touse;
73798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* validate the incoming port */
73818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((lsin->sin_port != 0) &&
73828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (lsin->sin_port != inp->sctp_lport)) {
73838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
73848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = EINVAL;
73858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
73868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
73878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* user specified 0 port, set it to existing port */
73888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			lsin->sin_port = inp->sctp_lport;
73898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
73908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
73918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		lep = sctp_pcb_findep(addr_touse, 1, 0, vrf_id);
73928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (lep != NULL) {
73938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
73948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * We must decrement the refcount
73958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * since we have the ep already and
73968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * are binding. No remove going on
73978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * here.
73988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
73998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_DECR_REF(lep);
74008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (lep == inp) {
74028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* already bound to it.. ok */
74038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
74048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (lep == NULL) {
74058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			((struct sockaddr_in *)addr_touse)->sin_port = 0;
74068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = sctp_addr_mgmt_ep_sa(inp, addr_touse,
74078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      SCTP_ADD_IP_ADDRESS,
74088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						      vrf_id, NULL);
74098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
74108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = EADDRINUSE;
74118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (*error)
74138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
74148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
74158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
74168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * FIX: decide whether we allow assoc based
74178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * bindx
74188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
74198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
74218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
74228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
74238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_bindx(DELETE) for one address.
74248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * assumes all arguments are valid/checked by caller.
74258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
74268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
74270ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_bindx_delete_address(struct sctp_inpcb *inp,
74288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  struct sockaddr *sa, sctp_assoc_t assoc_id,
74298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  uint32_t vrf_id, int *error)
74308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
74318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *addr_touse;
74328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
74338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in sin;
74348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
74368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int i, fnd = 0;
74378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
74398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* see if we're bound all already! */
74408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
74418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
74428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*error = EINVAL;
74438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
74448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_MVRF
74468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Is the VRF one we have */
74478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (i = 0; i < inp->num_vrfs; i++) {
74488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (vrf_id == inp->m_vrf_ids[i]) {
74498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			fnd = 1;
74508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
74518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!fnd) {
74548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
74558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*error = EINVAL;
74568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
74578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	addr_touse = sa;
7460e857b728270b80432f048a8de3c84aa9089dd06btuexen#ifdef INET6
74618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sa->sa_family == AF_INET6) {
74628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6;
7463f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
74648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sa->sa_len != sizeof(struct sockaddr_in6)) {
74658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
74668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = EINVAL;
74678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
74688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
74718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* can only bind v6 on PF_INET6 sockets */
74728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
74738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = EINVAL;
74748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
74758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6 = (struct sockaddr_in6 *)addr_touse;
74778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
74788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
74798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_IPV6_V6ONLY(inp)) {
74808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* can't bind mapped-v4 on PF_INET sockets */
74818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
74828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				*error = EINVAL;
74838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
74848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
74858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			in6_sin6_2_sin(&sin, sin6);
74868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			addr_touse = (struct sockaddr *)&sin;
74878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
74898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
74918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sa->sa_family == AF_INET) {
7492f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
74938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sa->sa_len != sizeof(struct sockaddr_in)) {
74948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
74958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = EINVAL;
74968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
74978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
74988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
74998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
75008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_IPV6_V6ONLY(inp)) {
75018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* can't bind v4 on PF_INET sockets */
75028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
75038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			*error = EINVAL;
75048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
75058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
75068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
75078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
75088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
75098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * No lock required mgmt_ep_sa does its own locking.
75108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * If the FIX: below is ever changed we may need to
75118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * lock before calling association level binding.
75128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
75138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (assoc_id == 0) {
75148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* delete the address */
75158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*error = sctp_addr_mgmt_ep_sa(inp, addr_touse,
75168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					      SCTP_DEL_IP_ADDRESS,
75178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					      vrf_id, NULL);
75188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
75198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
75208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * FIX: decide whether we allow assoc based
75218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * bindx
75228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
75238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
75248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
75258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
75268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
75278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns the valid local address count for an assoc, taking into account
75288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * all scoping rules
75298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
75308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
75318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_local_addr_count(struct sctp_tcb *stcb)
75328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
7533bb7718cf40846152b19b119af6d4b3bdb85db6b1t	int loopback_scope;
7534bb7718cf40846152b19b119af6d4b3bdb85db6b1t#if defined(INET)
7535bb7718cf40846152b19b119af6d4b3bdb85db6b1t	int ipv4_local_scope, ipv4_addr_legal;
7536bb7718cf40846152b19b119af6d4b3bdb85db6b1t#endif
7537bb7718cf40846152b19b119af6d4b3bdb85db6b1t#if defined (INET6)
7538bb7718cf40846152b19b119af6d4b3bdb85db6b1t	int local_scope, site_scope, ipv6_addr_legal;
7539bb7718cf40846152b19b119af6d4b3bdb85db6b1t#endif
75407988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
75417988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	int conn_addr_legal;
75427988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
75438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_vrf *vrf;
75448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifn *sctp_ifn;
75458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *sctp_ifa;
75468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int count = 0;
75478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
75488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Turn on all the appropriate scopes */
75497988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	loopback_scope = stcb->asoc.scope.loopback_scope;
7550bb7718cf40846152b19b119af6d4b3bdb85db6b1t#if defined(INET)
75517988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
7552bb7718cf40846152b19b119af6d4b3bdb85db6b1t	ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
7553bb7718cf40846152b19b119af6d4b3bdb85db6b1t#endif
7554bb7718cf40846152b19b119af6d4b3bdb85db6b1t#if defined(INET6)
75557988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	local_scope = stcb->asoc.scope.local_scope;
75567988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	site_scope = stcb->asoc.scope.site_scope;
75577988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
7558bb7718cf40846152b19b119af6d4b3bdb85db6b1t#endif
75597988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#if defined(__Userspace__)
75607988ea8f0c067cf3757e798b473b1ae4d34b6dfdt	conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
75617988ea8f0c067cf3757e798b473b1ae4d34b6dfdt#endif
75628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RLOCK();
75638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf = sctp_find_vrf(stcb->asoc.vrf_id);
75648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (vrf == NULL) {
75658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no vrf, no addresses */
75668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_IPI_ADDR_RUNLOCK();
75678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
75688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
75698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
75708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
75718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
75728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * bound all case: go through all ifns on the vrf
75738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
75748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
75758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((loopback_scope == 0) &&
75768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
75778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
75788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
75798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
75808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_addr_restricted(stcb, sctp_ifa))
75818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
75828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				switch (sctp_ifa->address.sa.sa_family) {
75838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
75848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET:
75858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (ipv4_addr_legal) {
75868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						struct sockaddr_in *sin;
75878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7588bfb1bf7e665a02b48026482bf33d05c83dfad73bt						sin = &sctp_ifa->address.sin;
75898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (sin->sin_addr.s_addr == 0) {
75908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							/* skip unspecified addrs */
75918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
75928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
7593998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
7594998635733088fde643e6d807fa76679c4ceeaa00t						if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
7595998635733088fde643e6d807fa76679c4ceeaa00t						                     &sin->sin_addr) != 0) {
7596998635733088fde643e6d807fa76679c4ceeaa00t							continue;
7597998635733088fde643e6d807fa76679c4ceeaa00t						}
7598998635733088fde643e6d807fa76679c4ceeaa00t#endif
75998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((ipv4_local_scope == 0) &&
76008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
76018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
76028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
76038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* count this one */
76048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						count++;
76058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					} else {
76068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
76078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
76088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
76098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
76108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
76118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET6:
76128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (ipv6_addr_legal) {
76138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						struct sockaddr_in6 *sin6;
76148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
76158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
76168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						struct sockaddr_in6 lsa6;
76178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7618bfb1bf7e665a02b48026482bf33d05c83dfad73bt						sin6 = &sctp_ifa->address.sin6;
76198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
76208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
76218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
7622998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
7623998635733088fde643e6d807fa76679c4ceeaa00t						if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
7624998635733088fde643e6d807fa76679c4ceeaa00t						                     &sin6->sin6_addr) != 0) {
7625998635733088fde643e6d807fa76679c4ceeaa00t							continue;
7626998635733088fde643e6d807fa76679c4ceeaa00t						}
7627998635733088fde643e6d807fa76679c4ceeaa00t#endif
76288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
76298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (local_scope == 0)
76308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								continue;
76318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_EMBEDDED_V6_SCOPE)
76328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							if (sin6->sin6_scope_id == 0) {
76338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_KAME
76348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								if (sa6_recoverscope(sin6) != 0)
76358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									/*
76368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * bad link
76378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * local
76388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * address
76398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 */
76408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									continue;
76418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
76428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								lsa6 = *sin6;
76438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								if (in6_recoverscope(&lsa6,
76448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								                     &lsa6.sin6_addr,
76458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								                     NULL))
76468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									/*
76478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * bad link
76488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * local
76498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 * address
76508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									 */
76518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									continue;
76528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen								sin6 = &lsa6;
76538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_KAME */
76548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							}
76558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
76568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
76578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						if ((site_scope == 0) &&
76588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
76598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							continue;
76608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						}
76618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* count this one */
76628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						count++;
76638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
76648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
76658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
766666e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#if defined(__Userspace__)
766766e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen				case AF_CONN:
76687988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					if (conn_addr_legal) {
76697988ea8f0c067cf3757e798b473b1ae4d34b6dfdt						count++;
76707988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					}
767166e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen					break;
767266e2e9e4f917602ca2550fd7aa1de334a3128e0ftuexen#endif
76738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				default:
76748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* TSNH */
76758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
76768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
76778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
76788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
76798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
76808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
76818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * subset bound case
76828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
76838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_laddr *laddr;
76848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list,
76858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			     sctp_nxt_addr) {
76868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
76878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
76888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
76898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* count this one */
76908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			count++;
76918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
76928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
76938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RUNLOCK();
76948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (count);
76958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
76968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
76978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(SCTP_LOCAL_TRACE_BUF)
76988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
76998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
77008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_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)
7701000a5bac556b28e74e4e98c540f66b1743e9312dtuexen{
77028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t saveindex, newindex;
77038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
77048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__Windows__)
77058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_log) == NULL) {
77068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
77078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
77088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	do {
77098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		saveindex = SCTP_BASE_SYSCTL(sctp_log)->index;
77108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
77118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			newindex = 1;
77128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
77138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			newindex = saveindex + 1;
77148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
77158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} while (atomic_cmpset_int(&SCTP_BASE_SYSCTL(sctp_log)->index, saveindex, newindex) == 0);
77168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
77178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		saveindex = 0;
77188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
77198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].timestamp = SCTP_GET_CYCLECOUNT;
77208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].subsys = subsys;
77218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[0] = a;
77228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[1] = b;
77238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[2] = c;
77248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[3] = d;
77258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[4] = e;
77268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log)->entry[saveindex].params[5] = f;
77278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
77288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	do {
77298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		saveindex = SCTP_BASE_SYSCTL(sctp_log).index;
77308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
77318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			newindex = 1;
77328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
77338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			newindex = saveindex + 1;
77348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
77358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} while (atomic_cmpset_int(&SCTP_BASE_SYSCTL(sctp_log).index, saveindex, newindex) == 0);
77368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
77378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		saveindex = 0;
77388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
77398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].timestamp = SCTP_GET_CYCLECOUNT;
77408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].subsys = subsys;
77418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[0] = a;
77428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[1] = b;
77438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[2] = c;
77448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[3] = d;
77458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[4] = e;
77468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[5] = f;
77478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
77498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
77508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
77518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__)
77528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version >= 800044
77538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
77548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
77558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
77568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct ip *iph;
7757b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#ifdef INET6
7758b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	struct ip6_hdr *ip6;
7759b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif
77608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *sp, *last;
77618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct udphdr *uhdr;
7762b0959c60931b4d5bff2fd48cea483d72c437969etuexen	uint16_t port;
77638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
77648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((m->m_flags & M_PKTHDR) == 0) {
77658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Can't handle one that is not a pkt hdr */
77668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
77678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7768b0959c60931b4d5bff2fd48cea483d72c437969etuexen	/* Pull the src port */
77698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	iph = mtod(m, struct ip *);
77708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uhdr = (struct udphdr *)((caddr_t)iph + off);
77718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	port = uhdr->uh_sport;
7772b0959c60931b4d5bff2fd48cea483d72c437969etuexen	/* Split out the mbuf chain. Leave the
7773b0959c60931b4d5bff2fd48cea483d72c437969etuexen	 * IP header in m, place the
7774b0959c60931b4d5bff2fd48cea483d72c437969etuexen	 * rest in the sp.
7775b0959c60931b4d5bff2fd48cea483d72c437969etuexen	 */
777668beeca578347438d9c434680197647ed551935ft	sp = m_split(m, off, M_NOWAIT);
77778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sp == NULL) {
77788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Gak, drop packet, we can't do a split */
77798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
77808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7781b0959c60931b4d5bff2fd48cea483d72c437969etuexen	if (sp->m_pkthdr.len < sizeof(struct udphdr) + sizeof(struct sctphdr)) {
7782b0959c60931b4d5bff2fd48cea483d72c437969etuexen		/* Gak, packet can't have an SCTP header in it - too small */
77838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_freem(sp);
77848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
77858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7786b0959c60931b4d5bff2fd48cea483d72c437969etuexen	/* Now pull up the UDP header and SCTP header together */
7787b0959c60931b4d5bff2fd48cea483d72c437969etuexen	sp = m_pullup(sp, sizeof(struct udphdr) + sizeof(struct sctphdr));
77888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sp == NULL) {
77898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Gak pullup failed */
77908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto out;
77918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7792b0959c60931b4d5bff2fd48cea483d72c437969etuexen	/* Trim out the UDP header */
77938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m_adj(sp, sizeof(struct udphdr));
77948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
77958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now reconstruct the mbuf chain */
7796b0959c60931b4d5bff2fd48cea483d72c437969etuexen	for (last = m; last->m_next; last = last->m_next);
77978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	last->m_next = sp;
77988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m->m_pkthdr.len += sp->m_pkthdr.len;
77998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	iph = mtod(m, struct ip *);
78008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (iph->ip_v) {
78018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
7802b0959c60931b4d5bff2fd48cea483d72c437969etuexen	case IPVERSION:
78034bda18bd6192b29406d04eeb576f5d5d7bd32fc7t#if __FreeBSD_version >= 1000000
78044bda18bd6192b29406d04eeb576f5d5d7bd32fc7t		iph->ip_len = htons(ntohs(iph->ip_len) - sizeof(struct udphdr));
78054bda18bd6192b29406d04eeb576f5d5d7bd32fc7t#else
7806b0959c60931b4d5bff2fd48cea483d72c437969etuexen		iph->ip_len -= sizeof(struct udphdr);
78074bda18bd6192b29406d04eeb576f5d5d7bd32fc7t#endif
7808b0959c60931b4d5bff2fd48cea483d72c437969etuexen		sctp_input_with_port(m, off, port);
7809b0959c60931b4d5bff2fd48cea483d72c437969etuexen		break;
78108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
78118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
7812b0959c60931b4d5bff2fd48cea483d72c437969etuexen	case IPV6_VERSION >> 4:
7813b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		ip6 = mtod(m, struct ip6_hdr *);
7814b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - sizeof(struct udphdr));
7815b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		sctp6_input_with_port(&m, &off, port);
7816b0959c60931b4d5bff2fd48cea483d72c437969etuexen		break;
78178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7818b0959c60931b4d5bff2fd48cea483d72c437969etuexen	default:
7819b0959c60931b4d5bff2fd48cea483d72c437969etuexen		goto out;
7820b0959c60931b4d5bff2fd48cea483d72c437969etuexen		break;
78218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
78228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return;
78238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen out:
78248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m_freem(m);
78258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
78268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
78278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7828000a5bac556b28e74e4e98c540f66b1743e9312dtuexenvoid
78298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_over_udp_stop(void)
78308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
78318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
78328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * This function assumes sysctl caller holds sctp_sysctl_info_lock() for writting!
78338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
7834b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#ifdef INET
7835b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) {
7836b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		soclose(SCTP_BASE_INFO(udp4_tun_socket));
7837b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		SCTP_BASE_INFO(udp4_tun_socket) = NULL;
78388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7839b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif
7840b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#ifdef INET6
7841b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) {
7842b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		soclose(SCTP_BASE_INFO(udp6_tun_socket));
7843b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		SCTP_BASE_INFO(udp6_tun_socket) = NULL;
7844b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	}
7845b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif
78468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
78478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
78488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
78498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_over_udp_start(void)
78508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
78518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if __FreeBSD_version >= 800044
78528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t port;
78538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int ret;
7854b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#ifdef INET
78558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in sin;
7856b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif
7857b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#ifdef INET6
7858b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	struct sockaddr_in6 sin6;
7859b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif
78608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
78618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * This function assumes sysctl caller holds sctp_sysctl_info_lock() for writting!
78628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
78638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port);
7864b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	if (ntohs(port) == 0) {
78658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Must have a port set */
7866b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EINVAL);
78678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7868b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#ifdef INET
7869b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) {
7870b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		/* Already running -- must stop first */
7871b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		return (EALREADY);
7872b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	}
7873b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif
7874b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#ifdef INET6
7875b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) {
78768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Already running -- must stop first */
7877b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (EALREADY);
78788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7879b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif
7880b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#ifdef INET
7881b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	if ((ret = socreate(PF_INET, &SCTP_BASE_INFO(udp4_tun_socket),
7882b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	                    SOCK_DGRAM, IPPROTO_UDP,
7883b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	                    curthread->td_ucred, curthread))) {
7884b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		sctp_over_udp_stop();
78858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ret);
78868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7887b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	/* Call the special UDP hook. */
7888b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket),
7889b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	                                    sctp_recv_udp_tunneled_packet))) {
7890b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		sctp_over_udp_stop();
7891b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		return (ret);
78928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7893b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	/* Ok, we have a socket, bind it to the port. */
7894b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	memset(&sin, 0, sizeof(struct sockaddr_in));
7895b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	sin.sin_len = sizeof(struct sockaddr_in);
78968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin.sin_family = AF_INET;
78978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin.sin_port = htons(port);
7898b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	if ((ret = sobind(SCTP_BASE_INFO(udp4_tun_socket),
7899b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	                  (struct sockaddr *)&sin, curthread))) {
79008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_over_udp_stop();
79018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (ret);
79028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7903b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif
7904b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#ifdef INET6
7905b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	if ((ret = socreate(PF_INET6, &SCTP_BASE_INFO(udp6_tun_socket),
7906b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	                    SOCK_DGRAM, IPPROTO_UDP,
7907b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	                    curthread->td_ucred, curthread))) {
7908b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		sctp_over_udp_stop();
7909b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		return (ret);
7910b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	}
7911b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	/* Call the special UDP hook. */
7912b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket),
7913b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	                                    sctp_recv_udp_tunneled_packet))) {
7914b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		sctp_over_udp_stop();
7915b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		return (ret);
7916b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	}
7917b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	/* Ok, we have a socket, bind it to the port. */
7918b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	memset(&sin6, 0, sizeof(struct sockaddr_in6));
7919b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	sin6.sin6_len = sizeof(struct sockaddr_in6);
7920b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	sin6.sin6_family = AF_INET6;
7921b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	sin6.sin6_port = htons(port);
7922b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	if ((ret = sobind(SCTP_BASE_INFO(udp6_tun_socket),
7923b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	                  (struct sockaddr *)&sin6, curthread))) {
7924b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		sctp_over_udp_stop();
7925b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t		return (ret);
7926b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	}
7927b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t#endif
79288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
79298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
7930b7a28211ba99e7b9116f93a0ec2e3f27acaa8f72t	return (ENOTSUP);
79318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
79328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
79338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
7934