1163953Srrs/*-
2185694Srrs * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
3237896Stuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4237896Stuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
5163953Srrs *
6163953Srrs * Redistribution and use in source and binary forms, with or without
7163953Srrs * modification, are permitted provided that the following conditions are met:
8163953Srrs *
9163953Srrs * a) Redistributions of source code must retain the above copyright notice,
10231038Stuexen *    this list of conditions and the following disclaimer.
11163953Srrs *
12163953Srrs * b) Redistributions in binary form must reproduce the above copyright
13163953Srrs *    notice, this list of conditions and the following disclaimer in
14231038Stuexen *    the documentation and/or other materials provided with the distribution.
15163953Srrs *
16163953Srrs * c) Neither the name of Cisco Systems, Inc. nor the names of its
17163953Srrs *    contributors may be used to endorse or promote products derived
18163953Srrs *    from this software without specific prior written permission.
19163953Srrs *
20163953Srrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21163953Srrs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22163953Srrs * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23163953Srrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24163953Srrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25163953Srrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26163953Srrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27163953Srrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28163953Srrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29163953Srrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30163953Srrs * THE POSSIBILITY OF SUCH DAMAGE.
31163953Srrs */
32163953Srrs
33163953Srrs#include <sys/cdefs.h>
34163953Srrs__FBSDID("$FreeBSD$");
35163953Srrs
36163953Srrs#include <netinet/sctp_os.h>
37163953Srrs#include <netinet/sctp_pcb.h>
38163953Srrs#include <netinet/sctputil.h>
39163953Srrs#include <netinet/sctp_var.h>
40167598Srrs#include <netinet/sctp_sysctl.h>
41163953Srrs#ifdef INET6
42252944Stuexen#include <netinet6/sctp6_var.h>
43163953Srrs#endif
44163953Srrs#include <netinet/sctp_header.h>
45163953Srrs#include <netinet/sctp_output.h>
46163953Srrs#include <netinet/sctp_uio.h>
47163953Srrs#include <netinet/sctp_timer.h>
48163953Srrs#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
49163953Srrs#include <netinet/sctp_auth.h>
50163953Srrs#include <netinet/sctp_asconf.h>
51208160Srrs#include <netinet/sctp_bsd_addr.h>
52252944Stuexen#include <netinet/udp.h>
53252944Stuexen#include <netinet/udp_var.h>
54252944Stuexen#include <sys/proc.h>
55163953Srrs
56163953Srrs
57170791Srrs#ifndef KTR_SCTP
58170791Srrs#define KTR_SCTP KTR_SUBSYS
59170744Srrs#endif
60163953Srrs
61217611Stuexenextern struct sctp_cc_functions sctp_cc_functions[];
62217760Stuexenextern struct sctp_ss_functions sctp_ss_functions[];
63217611Stuexen
64163953Srrsvoid
65252932Stuexensctp_sblog(struct sockbuf *sb, struct sctp_tcb *stcb, int from, int incr)
66163953Srrs{
67170744Srrs	struct sctp_cwnd_log sctp_clog;
68163953Srrs
69170744Srrs	sctp_clog.x.sb.stcb = stcb;
70170744Srrs	sctp_clog.x.sb.so_sbcc = sb->sb_cc;
71163953Srrs	if (stcb)
72170744Srrs		sctp_clog.x.sb.stcb_sbcc = stcb->asoc.sb_cc;
73163953Srrs	else
74170744Srrs		sctp_clog.x.sb.stcb_sbcc = 0;
75170744Srrs	sctp_clog.x.sb.incr = incr;
76171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
77170744Srrs	    SCTP_LOG_EVENT_SB,
78170744Srrs	    from,
79170744Srrs	    sctp_clog.x.misc.log1,
80170744Srrs	    sctp_clog.x.misc.log2,
81170744Srrs	    sctp_clog.x.misc.log3,
82170744Srrs	    sctp_clog.x.misc.log4);
83163953Srrs}
84163953Srrs
85163953Srrsvoid
86163953Srrssctp_log_closing(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int16_t loc)
87163953Srrs{
88170744Srrs	struct sctp_cwnd_log sctp_clog;
89163953Srrs
90170744Srrs	sctp_clog.x.close.inp = (void *)inp;
91170744Srrs	sctp_clog.x.close.sctp_flags = inp->sctp_flags;
92163953Srrs	if (stcb) {
93170744Srrs		sctp_clog.x.close.stcb = (void *)stcb;
94170744Srrs		sctp_clog.x.close.state = (uint16_t) stcb->asoc.state;
95163953Srrs	} else {
96170744Srrs		sctp_clog.x.close.stcb = 0;
97170744Srrs		sctp_clog.x.close.state = 0;
98163953Srrs	}
99170744Srrs	sctp_clog.x.close.loc = loc;
100171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
101170744Srrs	    SCTP_LOG_EVENT_CLOSE,
102170744Srrs	    0,
103170744Srrs	    sctp_clog.x.misc.log1,
104170744Srrs	    sctp_clog.x.misc.log2,
105170744Srrs	    sctp_clog.x.misc.log3,
106170744Srrs	    sctp_clog.x.misc.log4);
107163953Srrs}
108163953Srrs
109163953Srrsvoid
110163953Srrsrto_logging(struct sctp_nets *net, int from)
111163953Srrs{
112170744Srrs	struct sctp_cwnd_log sctp_clog;
113163953Srrs
114179141Srrs	memset(&sctp_clog, 0, sizeof(sctp_clog));
115170744Srrs	sctp_clog.x.rto.net = (void *)net;
116219013Stuexen	sctp_clog.x.rto.rtt = net->rtt / 1000;
117171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
118170744Srrs	    SCTP_LOG_EVENT_RTT,
119170744Srrs	    from,
120170744Srrs	    sctp_clog.x.misc.log1,
121170744Srrs	    sctp_clog.x.misc.log2,
122170744Srrs	    sctp_clog.x.misc.log3,
123170744Srrs	    sctp_clog.x.misc.log4);
124163953Srrs}
125163953Srrs
126163953Srrsvoid
127164181Srrssctp_log_strm_del_alt(struct sctp_tcb *stcb, uint32_t tsn, uint16_t sseq, uint16_t stream, int from)
128163953Srrs{
129170744Srrs	struct sctp_cwnd_log sctp_clog;
130163953Srrs
131170744Srrs	sctp_clog.x.strlog.stcb = stcb;
132170744Srrs	sctp_clog.x.strlog.n_tsn = tsn;
133170744Srrs	sctp_clog.x.strlog.n_sseq = sseq;
134170744Srrs	sctp_clog.x.strlog.e_tsn = 0;
135170744Srrs	sctp_clog.x.strlog.e_sseq = 0;
136170744Srrs	sctp_clog.x.strlog.strm = stream;
137171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
138170744Srrs	    SCTP_LOG_EVENT_STRM,
139170744Srrs	    from,
140170744Srrs	    sctp_clog.x.misc.log1,
141170744Srrs	    sctp_clog.x.misc.log2,
142170744Srrs	    sctp_clog.x.misc.log3,
143170744Srrs	    sctp_clog.x.misc.log4);
144163953Srrs}
145163953Srrs
146163953Srrsvoid
147163953Srrssctp_log_nagle_event(struct sctp_tcb *stcb, int action)
148163953Srrs{
149170744Srrs	struct sctp_cwnd_log sctp_clog;
150163953Srrs
151170744Srrs	sctp_clog.x.nagle.stcb = (void *)stcb;
152170744Srrs	sctp_clog.x.nagle.total_flight = stcb->asoc.total_flight;
153170744Srrs	sctp_clog.x.nagle.total_in_queue = stcb->asoc.total_output_queue_size;
154170744Srrs	sctp_clog.x.nagle.count_in_queue = stcb->asoc.chunks_on_out_queue;
155170744Srrs	sctp_clog.x.nagle.count_in_flight = stcb->asoc.total_flight_count;
156171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
157170744Srrs	    SCTP_LOG_EVENT_NAGLE,
158170744Srrs	    action,
159170744Srrs	    sctp_clog.x.misc.log1,
160170744Srrs	    sctp_clog.x.misc.log2,
161170744Srrs	    sctp_clog.x.misc.log3,
162170744Srrs	    sctp_clog.x.misc.log4);
163163953Srrs}
164163953Srrs
165163953Srrsvoid
166163953Srrssctp_log_sack(uint32_t old_cumack, uint32_t cumack, uint32_t tsn, uint16_t gaps, uint16_t dups, int from)
167163953Srrs{
168170744Srrs	struct sctp_cwnd_log sctp_clog;
169163953Srrs
170170744Srrs	sctp_clog.x.sack.cumack = cumack;
171170744Srrs	sctp_clog.x.sack.oldcumack = old_cumack;
172170744Srrs	sctp_clog.x.sack.tsn = tsn;
173170744Srrs	sctp_clog.x.sack.numGaps = gaps;
174170744Srrs	sctp_clog.x.sack.numDups = dups;
175171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
176170744Srrs	    SCTP_LOG_EVENT_SACK,
177170744Srrs	    from,
178170744Srrs	    sctp_clog.x.misc.log1,
179170744Srrs	    sctp_clog.x.misc.log2,
180170744Srrs	    sctp_clog.x.misc.log3,
181170744Srrs	    sctp_clog.x.misc.log4);
182163953Srrs}
183163953Srrs
184163953Srrsvoid
185163953Srrssctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from)
186163953Srrs{
187170744Srrs	struct sctp_cwnd_log sctp_clog;
188163953Srrs
189179141Srrs	memset(&sctp_clog, 0, sizeof(sctp_clog));
190170744Srrs	sctp_clog.x.map.base = map;
191170744Srrs	sctp_clog.x.map.cum = cum;
192170744Srrs	sctp_clog.x.map.high = high;
193171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
194170744Srrs	    SCTP_LOG_EVENT_MAP,
195170744Srrs	    from,
196170744Srrs	    sctp_clog.x.misc.log1,
197170744Srrs	    sctp_clog.x.misc.log2,
198170744Srrs	    sctp_clog.x.misc.log3,
199170744Srrs	    sctp_clog.x.misc.log4);
200163953Srrs}
201163953Srrs
202163953Srrsvoid
203252932Stuexensctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn, int from)
204163953Srrs{
205170744Srrs	struct sctp_cwnd_log sctp_clog;
206163953Srrs
207179141Srrs	memset(&sctp_clog, 0, sizeof(sctp_clog));
208170744Srrs	sctp_clog.x.fr.largest_tsn = biggest_tsn;
209170744Srrs	sctp_clog.x.fr.largest_new_tsn = biggest_new_tsn;
210170744Srrs	sctp_clog.x.fr.tsn = tsn;
211171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
212170744Srrs	    SCTP_LOG_EVENT_FR,
213170744Srrs	    from,
214170744Srrs	    sctp_clog.x.misc.log1,
215170744Srrs	    sctp_clog.x.misc.log2,
216170744Srrs	    sctp_clog.x.misc.log3,
217170744Srrs	    sctp_clog.x.misc.log4);
218163953Srrs}
219163953Srrs
220163953Srrsvoid
221163953Srrssctp_log_mb(struct mbuf *m, int from)
222163953Srrs{
223170744Srrs	struct sctp_cwnd_log sctp_clog;
224163953Srrs
225170744Srrs	sctp_clog.x.mb.mp = m;
226170744Srrs	sctp_clog.x.mb.mbuf_flags = (uint8_t) (SCTP_BUF_GET_FLAGS(m));
227170744Srrs	sctp_clog.x.mb.size = (uint16_t) (SCTP_BUF_LEN(m));
228170744Srrs	sctp_clog.x.mb.data = SCTP_BUF_AT(m, 0);
229165647Srrs	if (SCTP_BUF_IS_EXTENDED(m)) {
230170744Srrs		sctp_clog.x.mb.ext = SCTP_BUF_EXTEND_BASE(m);
231170744Srrs		sctp_clog.x.mb.refcnt = (uint8_t) (SCTP_BUF_EXTEND_REFCNT(m));
232163953Srrs	} else {
233170744Srrs		sctp_clog.x.mb.ext = 0;
234170744Srrs		sctp_clog.x.mb.refcnt = 0;
235163953Srrs	}
236171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
237170744Srrs	    SCTP_LOG_EVENT_MBUF,
238170744Srrs	    from,
239170744Srrs	    sctp_clog.x.misc.log1,
240170744Srrs	    sctp_clog.x.misc.log2,
241170744Srrs	    sctp_clog.x.misc.log3,
242170744Srrs	    sctp_clog.x.misc.log4);
243163953Srrs}
244163953Srrs
245163953Srrsvoid
246252932Stuexensctp_log_strm_del(struct sctp_queued_to_read *control, struct sctp_queued_to_read *poschk, int from)
247163953Srrs{
248170744Srrs	struct sctp_cwnd_log sctp_clog;
249163953Srrs
250163953Srrs	if (control == NULL) {
251169420Srrs		SCTP_PRINTF("Gak log of NULL?\n");
252163953Srrs		return;
253163953Srrs	}
254170744Srrs	sctp_clog.x.strlog.stcb = control->stcb;
255170744Srrs	sctp_clog.x.strlog.n_tsn = control->sinfo_tsn;
256170744Srrs	sctp_clog.x.strlog.n_sseq = control->sinfo_ssn;
257170744Srrs	sctp_clog.x.strlog.strm = control->sinfo_stream;
258163953Srrs	if (poschk != NULL) {
259170744Srrs		sctp_clog.x.strlog.e_tsn = poschk->sinfo_tsn;
260170744Srrs		sctp_clog.x.strlog.e_sseq = poschk->sinfo_ssn;
261163953Srrs	} else {
262170744Srrs		sctp_clog.x.strlog.e_tsn = 0;
263170744Srrs		sctp_clog.x.strlog.e_sseq = 0;
264163953Srrs	}
265171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
266170744Srrs	    SCTP_LOG_EVENT_STRM,
267170744Srrs	    from,
268170744Srrs	    sctp_clog.x.misc.log1,
269170744Srrs	    sctp_clog.x.misc.log2,
270170744Srrs	    sctp_clog.x.misc.log3,
271170744Srrs	    sctp_clog.x.misc.log4);
272163953Srrs}
273163953Srrs
274163953Srrsvoid
275163953Srrssctp_log_cwnd(struct sctp_tcb *stcb, struct sctp_nets *net, int augment, uint8_t from)
276163953Srrs{
277170744Srrs	struct sctp_cwnd_log sctp_clog;
278163953Srrs
279170744Srrs	sctp_clog.x.cwnd.net = net;
280163953Srrs	if (stcb->asoc.send_queue_cnt > 255)
281170744Srrs		sctp_clog.x.cwnd.cnt_in_send = 255;
282163953Srrs	else
283170744Srrs		sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt;
284163953Srrs	if (stcb->asoc.stream_queue_cnt > 255)
285170744Srrs		sctp_clog.x.cwnd.cnt_in_str = 255;
286163953Srrs	else
287170744Srrs		sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt;
288163953Srrs
289163953Srrs	if (net) {
290170744Srrs		sctp_clog.x.cwnd.cwnd_new_value = net->cwnd;
291170744Srrs		sctp_clog.x.cwnd.inflight = net->flight_size;
292170744Srrs		sctp_clog.x.cwnd.pseudo_cumack = net->pseudo_cumack;
293170744Srrs		sctp_clog.x.cwnd.meets_pseudo_cumack = net->new_pseudo_cumack;
294170744Srrs		sctp_clog.x.cwnd.need_new_pseudo_cumack = net->find_pseudo_cumack;
295163953Srrs	}
296163953Srrs	if (SCTP_CWNDLOG_PRESEND == from) {
297170744Srrs		sctp_clog.x.cwnd.meets_pseudo_cumack = stcb->asoc.peers_rwnd;
298163953Srrs	}
299170744Srrs	sctp_clog.x.cwnd.cwnd_augment = augment;
300171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
301170744Srrs	    SCTP_LOG_EVENT_CWND,
302170744Srrs	    from,
303170744Srrs	    sctp_clog.x.misc.log1,
304170744Srrs	    sctp_clog.x.misc.log2,
305170744Srrs	    sctp_clog.x.misc.log3,
306170744Srrs	    sctp_clog.x.misc.log4);
307163953Srrs}
308163953Srrs
309163953Srrsvoid
310163953Srrssctp_log_lock(struct sctp_inpcb *inp, struct sctp_tcb *stcb, uint8_t from)
311163953Srrs{
312170744Srrs	struct sctp_cwnd_log sctp_clog;
313163953Srrs
314179141Srrs	memset(&sctp_clog, 0, sizeof(sctp_clog));
315164085Srrs	if (inp) {
316170744Srrs		sctp_clog.x.lock.sock = (void *)inp->sctp_socket;
317164085Srrs
318164085Srrs	} else {
319170744Srrs		sctp_clog.x.lock.sock = (void *)NULL;
320164085Srrs	}
321170744Srrs	sctp_clog.x.lock.inp = (void *)inp;
322163953Srrs	if (stcb) {
323170744Srrs		sctp_clog.x.lock.tcb_lock = mtx_owned(&stcb->tcb_mtx);
324163953Srrs	} else {
325170744Srrs		sctp_clog.x.lock.tcb_lock = SCTP_LOCK_UNKNOWN;
326163953Srrs	}
327163953Srrs	if (inp) {
328170744Srrs		sctp_clog.x.lock.inp_lock = mtx_owned(&inp->inp_mtx);
329170744Srrs		sctp_clog.x.lock.create_lock = mtx_owned(&inp->inp_create_mtx);
330163953Srrs	} else {
331170744Srrs		sctp_clog.x.lock.inp_lock = SCTP_LOCK_UNKNOWN;
332170744Srrs		sctp_clog.x.lock.create_lock = SCTP_LOCK_UNKNOWN;
333163953Srrs	}
334179783Srrs	sctp_clog.x.lock.info_lock = rw_wowned(&SCTP_BASE_INFO(ipi_ep_mtx));
335212225Srrs	if (inp && (inp->sctp_socket)) {
336170744Srrs		sctp_clog.x.lock.sock_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx));
337170744Srrs		sctp_clog.x.lock.sockrcvbuf_lock = mtx_owned(&(inp->sctp_socket->so_rcv.sb_mtx));
338170744Srrs		sctp_clog.x.lock.socksndbuf_lock = mtx_owned(&(inp->sctp_socket->so_snd.sb_mtx));
339163953Srrs	} else {
340170744Srrs		sctp_clog.x.lock.sock_lock = SCTP_LOCK_UNKNOWN;
341170744Srrs		sctp_clog.x.lock.sockrcvbuf_lock = SCTP_LOCK_UNKNOWN;
342170744Srrs		sctp_clog.x.lock.socksndbuf_lock = SCTP_LOCK_UNKNOWN;
343163953Srrs	}
344171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
345170744Srrs	    SCTP_LOG_LOCK_EVENT,
346170744Srrs	    from,
347170744Srrs	    sctp_clog.x.misc.log1,
348170744Srrs	    sctp_clog.x.misc.log2,
349170744Srrs	    sctp_clog.x.misc.log3,
350170744Srrs	    sctp_clog.x.misc.log4);
351163953Srrs}
352163953Srrs
353163953Srrsvoid
354163953Srrssctp_log_maxburst(struct sctp_tcb *stcb, struct sctp_nets *net, int error, int burst, uint8_t from)
355163953Srrs{
356170744Srrs	struct sctp_cwnd_log sctp_clog;
357163953Srrs
358179141Srrs	memset(&sctp_clog, 0, sizeof(sctp_clog));
359170744Srrs	sctp_clog.x.cwnd.net = net;
360170744Srrs	sctp_clog.x.cwnd.cwnd_new_value = error;
361170744Srrs	sctp_clog.x.cwnd.inflight = net->flight_size;
362170744Srrs	sctp_clog.x.cwnd.cwnd_augment = burst;
363163953Srrs	if (stcb->asoc.send_queue_cnt > 255)
364170744Srrs		sctp_clog.x.cwnd.cnt_in_send = 255;
365163953Srrs	else
366170744Srrs		sctp_clog.x.cwnd.cnt_in_send = stcb->asoc.send_queue_cnt;
367163953Srrs	if (stcb->asoc.stream_queue_cnt > 255)
368170744Srrs		sctp_clog.x.cwnd.cnt_in_str = 255;
369163953Srrs	else
370170744Srrs		sctp_clog.x.cwnd.cnt_in_str = stcb->asoc.stream_queue_cnt;
371171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
372170744Srrs	    SCTP_LOG_EVENT_MAXBURST,
373170744Srrs	    from,
374170744Srrs	    sctp_clog.x.misc.log1,
375170744Srrs	    sctp_clog.x.misc.log2,
376170744Srrs	    sctp_clog.x.misc.log3,
377170744Srrs	    sctp_clog.x.misc.log4);
378163953Srrs}
379163953Srrs
380163953Srrsvoid
381163953Srrssctp_log_rwnd(uint8_t from, uint32_t peers_rwnd, uint32_t snd_size, uint32_t overhead)
382163953Srrs{
383170744Srrs	struct sctp_cwnd_log sctp_clog;
384163953Srrs
385170744Srrs	sctp_clog.x.rwnd.rwnd = peers_rwnd;
386170744Srrs	sctp_clog.x.rwnd.send_size = snd_size;
387170744Srrs	sctp_clog.x.rwnd.overhead = overhead;
388170744Srrs	sctp_clog.x.rwnd.new_rwnd = 0;
389171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
390170744Srrs	    SCTP_LOG_EVENT_RWND,
391170744Srrs	    from,
392170744Srrs	    sctp_clog.x.misc.log1,
393170744Srrs	    sctp_clog.x.misc.log2,
394170744Srrs	    sctp_clog.x.misc.log3,
395170744Srrs	    sctp_clog.x.misc.log4);
396163953Srrs}
397163953Srrs
398163953Srrsvoid
399163953Srrssctp_log_rwnd_set(uint8_t from, uint32_t peers_rwnd, uint32_t flight_size, uint32_t overhead, uint32_t a_rwndval)
400163953Srrs{
401170744Srrs	struct sctp_cwnd_log sctp_clog;
402163953Srrs
403170744Srrs	sctp_clog.x.rwnd.rwnd = peers_rwnd;
404170744Srrs	sctp_clog.x.rwnd.send_size = flight_size;
405170744Srrs	sctp_clog.x.rwnd.overhead = overhead;
406170744Srrs	sctp_clog.x.rwnd.new_rwnd = a_rwndval;
407171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
408170744Srrs	    SCTP_LOG_EVENT_RWND,
409170744Srrs	    from,
410170744Srrs	    sctp_clog.x.misc.log1,
411170744Srrs	    sctp_clog.x.misc.log2,
412170744Srrs	    sctp_clog.x.misc.log3,
413170744Srrs	    sctp_clog.x.misc.log4);
414163953Srrs}
415163953Srrs
416163953Srrsvoid
417163953Srrssctp_log_mbcnt(uint8_t from, uint32_t total_oq, uint32_t book, uint32_t total_mbcnt_q, uint32_t mbcnt)
418163953Srrs{
419170744Srrs	struct sctp_cwnd_log sctp_clog;
420163953Srrs
421170744Srrs	sctp_clog.x.mbcnt.total_queue_size = total_oq;
422170744Srrs	sctp_clog.x.mbcnt.size_change = book;
423170744Srrs	sctp_clog.x.mbcnt.total_queue_mb_size = total_mbcnt_q;
424170744Srrs	sctp_clog.x.mbcnt.mbcnt_change = mbcnt;
425171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
426170744Srrs	    SCTP_LOG_EVENT_MBCNT,
427170744Srrs	    from,
428170744Srrs	    sctp_clog.x.misc.log1,
429170744Srrs	    sctp_clog.x.misc.log2,
430170744Srrs	    sctp_clog.x.misc.log3,
431170744Srrs	    sctp_clog.x.misc.log4);
432163953Srrs}
433163953Srrs
434163953Srrsvoid
435163953Srrssctp_misc_ints(uint8_t from, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
436163953Srrs{
437171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
438170744Srrs	    SCTP_LOG_MISC_EVENT,
439170744Srrs	    from,
440170744Srrs	    a, b, c, d);
441163953Srrs}
442163953Srrs
443163953Srrsvoid
444231038Stuexensctp_wakeup_log(struct sctp_tcb *stcb, uint32_t wake_cnt, int from)
445163953Srrs{
446170744Srrs	struct sctp_cwnd_log sctp_clog;
447163953Srrs
448170744Srrs	sctp_clog.x.wake.stcb = (void *)stcb;
449170744Srrs	sctp_clog.x.wake.wake_cnt = wake_cnt;
450170744Srrs	sctp_clog.x.wake.flight = stcb->asoc.total_flight_count;
451170744Srrs	sctp_clog.x.wake.send_q = stcb->asoc.send_queue_cnt;
452170744Srrs	sctp_clog.x.wake.sent_q = stcb->asoc.sent_queue_cnt;
453163953Srrs
454163953Srrs	if (stcb->asoc.stream_queue_cnt < 0xff)
455170744Srrs		sctp_clog.x.wake.stream_qcnt = (uint8_t) stcb->asoc.stream_queue_cnt;
456163953Srrs	else
457170744Srrs		sctp_clog.x.wake.stream_qcnt = 0xff;
458163953Srrs
459163953Srrs	if (stcb->asoc.chunks_on_out_queue < 0xff)
460170744Srrs		sctp_clog.x.wake.chunks_on_oque = (uint8_t) stcb->asoc.chunks_on_out_queue;
461163953Srrs	else
462170744Srrs		sctp_clog.x.wake.chunks_on_oque = 0xff;
463163953Srrs
464170744Srrs	sctp_clog.x.wake.sctpflags = 0;
465163953Srrs	/* set in the defered mode stuff */
466163953Srrs	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE)
467170744Srrs		sctp_clog.x.wake.sctpflags |= 1;
468163953Srrs	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT)
469170744Srrs		sctp_clog.x.wake.sctpflags |= 2;
470163953Srrs	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT)
471170744Srrs		sctp_clog.x.wake.sctpflags |= 4;
472163953Srrs	/* what about the sb */
473163953Srrs	if (stcb->sctp_socket) {
474163953Srrs		struct socket *so = stcb->sctp_socket;
475163953Srrs
476170744Srrs		sctp_clog.x.wake.sbflags = (uint8_t) ((so->so_snd.sb_flags & 0x00ff));
477163953Srrs	} else {
478170744Srrs		sctp_clog.x.wake.sbflags = 0xff;
479163953Srrs	}
480171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
481170744Srrs	    SCTP_LOG_EVENT_WAKE,
482170744Srrs	    from,
483170744Srrs	    sctp_clog.x.misc.log1,
484170744Srrs	    sctp_clog.x.misc.log2,
485170744Srrs	    sctp_clog.x.misc.log3,
486170744Srrs	    sctp_clog.x.misc.log4);
487163953Srrs}
488163953Srrs
489163953Srrsvoid
490231038Stuexensctp_log_block(uint8_t from, struct sctp_association *asoc, int sendlen)
491163953Srrs{
492170744Srrs	struct sctp_cwnd_log sctp_clog;
493163953Srrs
494170744Srrs	sctp_clog.x.blk.onsb = asoc->total_output_queue_size;
495170744Srrs	sctp_clog.x.blk.send_sent_qcnt = (uint16_t) (asoc->send_queue_cnt + asoc->sent_queue_cnt);
496170744Srrs	sctp_clog.x.blk.peer_rwnd = asoc->peers_rwnd;
497170744Srrs	sctp_clog.x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt;
498170744Srrs	sctp_clog.x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue;
499170744Srrs	sctp_clog.x.blk.flight_size = (uint16_t) (asoc->total_flight / 1024);
500170744Srrs	sctp_clog.x.blk.sndlen = sendlen;
501171943Srrs	SCTP_CTR6(KTR_SCTP, "SCTP:%d[%d]:%x-%x-%x-%x",
502170744Srrs	    SCTP_LOG_EVENT_BLOCK,
503170744Srrs	    from,
504170744Srrs	    sctp_clog.x.misc.log1,
505170744Srrs	    sctp_clog.x.misc.log2,
506170744Srrs	    sctp_clog.x.misc.log3,
507170744Srrs	    sctp_clog.x.misc.log4);
508163953Srrs}
509163953Srrs
510163953Srrsint
511231038Stuexensctp_fill_stat_log(void *optval SCTP_UNUSED, size_t *optsize SCTP_UNUSED)
512163953Srrs{
513170744Srrs	/* May need to fix this if ktrdump does not work */
514163953Srrs	return (0);
515163953Srrs}
516163953Srrs
517163953Srrs#ifdef SCTP_AUDITING_ENABLED
518163953Srrsuint8_t sctp_audit_data[SCTP_AUDIT_SIZE][2];
519163953Srrsstatic int sctp_audit_indx = 0;
520163953Srrs
521163953Srrsstatic
522163953Srrsvoid
523163953Srrssctp_print_audit_report(void)
524163953Srrs{
525163953Srrs	int i;
526163953Srrs	int cnt;
527163953Srrs
528163953Srrs	cnt = 0;
529163953Srrs	for (i = sctp_audit_indx; i < SCTP_AUDIT_SIZE; i++) {
530163953Srrs		if ((sctp_audit_data[i][0] == 0xe0) &&
531163953Srrs		    (sctp_audit_data[i][1] == 0x01)) {
532163953Srrs			cnt = 0;
533169420Srrs			SCTP_PRINTF("\n");
534163953Srrs		} else if (sctp_audit_data[i][0] == 0xf0) {
535163953Srrs			cnt = 0;
536169420Srrs			SCTP_PRINTF("\n");
537163953Srrs		} else if ((sctp_audit_data[i][0] == 0xc0) &&
538163953Srrs		    (sctp_audit_data[i][1] == 0x01)) {
539169420Srrs			SCTP_PRINTF("\n");
540163953Srrs			cnt = 0;
541163953Srrs		}
542169420Srrs		SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0],
543163953Srrs		    (uint32_t) sctp_audit_data[i][1]);
544163953Srrs		cnt++;
545163953Srrs		if ((cnt % 14) == 0)
546169420Srrs			SCTP_PRINTF("\n");
547163953Srrs	}
548163953Srrs	for (i = 0; i < sctp_audit_indx; i++) {
549163953Srrs		if ((sctp_audit_data[i][0] == 0xe0) &&
550163953Srrs		    (sctp_audit_data[i][1] == 0x01)) {
551163953Srrs			cnt = 0;
552169420Srrs			SCTP_PRINTF("\n");
553163953Srrs		} else if (sctp_audit_data[i][0] == 0xf0) {
554163953Srrs			cnt = 0;
555169420Srrs			SCTP_PRINTF("\n");
556163953Srrs		} else if ((sctp_audit_data[i][0] == 0xc0) &&
557163953Srrs		    (sctp_audit_data[i][1] == 0x01)) {
558169420Srrs			SCTP_PRINTF("\n");
559163953Srrs			cnt = 0;
560163953Srrs		}
561169420Srrs		SCTP_PRINTF("%2.2x%2.2x ", (uint32_t) sctp_audit_data[i][0],
562163953Srrs		    (uint32_t) sctp_audit_data[i][1]);
563163953Srrs		cnt++;
564163953Srrs		if ((cnt % 14) == 0)
565169420Srrs			SCTP_PRINTF("\n");
566163953Srrs	}
567169420Srrs	SCTP_PRINTF("\n");
568163953Srrs}
569163953Srrs
570163953Srrsvoid
571163953Srrssctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
572163953Srrs    struct sctp_nets *net)
573163953Srrs{
574163953Srrs	int resend_cnt, tot_out, rep, tot_book_cnt;
575163953Srrs	struct sctp_nets *lnet;
576163953Srrs	struct sctp_tmit_chunk *chk;
577163953Srrs
578163953Srrs	sctp_audit_data[sctp_audit_indx][0] = 0xAA;
579163953Srrs	sctp_audit_data[sctp_audit_indx][1] = 0x000000ff & from;
580163953Srrs	sctp_audit_indx++;
581163953Srrs	if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
582163953Srrs		sctp_audit_indx = 0;
583163953Srrs	}
584163953Srrs	if (inp == NULL) {
585163953Srrs		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
586163953Srrs		sctp_audit_data[sctp_audit_indx][1] = 0x01;
587163953Srrs		sctp_audit_indx++;
588163953Srrs		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
589163953Srrs			sctp_audit_indx = 0;
590163953Srrs		}
591163953Srrs		return;
592163953Srrs	}
593163953Srrs	if (stcb == NULL) {
594163953Srrs		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
595163953Srrs		sctp_audit_data[sctp_audit_indx][1] = 0x02;
596163953Srrs		sctp_audit_indx++;
597163953Srrs		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
598163953Srrs			sctp_audit_indx = 0;
599163953Srrs		}
600163953Srrs		return;
601163953Srrs	}
602163953Srrs	sctp_audit_data[sctp_audit_indx][0] = 0xA1;
603163953Srrs	sctp_audit_data[sctp_audit_indx][1] =
604163953Srrs	    (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
605163953Srrs	sctp_audit_indx++;
606163953Srrs	if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
607163953Srrs		sctp_audit_indx = 0;
608163953Srrs	}
609163953Srrs	rep = 0;
610163953Srrs	tot_book_cnt = 0;
611163953Srrs	resend_cnt = tot_out = 0;
612163953Srrs	TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
613163953Srrs		if (chk->sent == SCTP_DATAGRAM_RESEND) {
614163953Srrs			resend_cnt++;
615163953Srrs		} else if (chk->sent < SCTP_DATAGRAM_RESEND) {
616163953Srrs			tot_out += chk->book_size;
617163953Srrs			tot_book_cnt++;
618163953Srrs		}
619163953Srrs	}
620163953Srrs	if (resend_cnt != stcb->asoc.sent_queue_retran_cnt) {
621163953Srrs		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
622163953Srrs		sctp_audit_data[sctp_audit_indx][1] = 0xA1;
623163953Srrs		sctp_audit_indx++;
624163953Srrs		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
625163953Srrs			sctp_audit_indx = 0;
626163953Srrs		}
627169420Srrs		SCTP_PRINTF("resend_cnt:%d asoc-tot:%d\n",
628163953Srrs		    resend_cnt, stcb->asoc.sent_queue_retran_cnt);
629163953Srrs		rep = 1;
630163953Srrs		stcb->asoc.sent_queue_retran_cnt = resend_cnt;
631163953Srrs		sctp_audit_data[sctp_audit_indx][0] = 0xA2;
632163953Srrs		sctp_audit_data[sctp_audit_indx][1] =
633163953Srrs		    (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
634163953Srrs		sctp_audit_indx++;
635163953Srrs		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
636163953Srrs			sctp_audit_indx = 0;
637163953Srrs		}
638163953Srrs	}
639163953Srrs	if (tot_out != stcb->asoc.total_flight) {
640163953Srrs		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
641163953Srrs		sctp_audit_data[sctp_audit_indx][1] = 0xA2;
642163953Srrs		sctp_audit_indx++;
643163953Srrs		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
644163953Srrs			sctp_audit_indx = 0;
645163953Srrs		}
646163953Srrs		rep = 1;
647169420Srrs		SCTP_PRINTF("tot_flt:%d asoc_tot:%d\n", tot_out,
648163953Srrs		    (int)stcb->asoc.total_flight);
649163953Srrs		stcb->asoc.total_flight = tot_out;
650163953Srrs	}
651163953Srrs	if (tot_book_cnt != stcb->asoc.total_flight_count) {
652163953Srrs		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
653163953Srrs		sctp_audit_data[sctp_audit_indx][1] = 0xA5;
654163953Srrs		sctp_audit_indx++;
655163953Srrs		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
656163953Srrs			sctp_audit_indx = 0;
657163953Srrs		}
658163953Srrs		rep = 1;
659207099Stuexen		SCTP_PRINTF("tot_flt_book:%d\n", tot_book_cnt);
660163953Srrs
661163953Srrs		stcb->asoc.total_flight_count = tot_book_cnt;
662163953Srrs	}
663163953Srrs	tot_out = 0;
664163953Srrs	TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
665163953Srrs		tot_out += lnet->flight_size;
666163953Srrs	}
667163953Srrs	if (tot_out != stcb->asoc.total_flight) {
668163953Srrs		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
669163953Srrs		sctp_audit_data[sctp_audit_indx][1] = 0xA3;
670163953Srrs		sctp_audit_indx++;
671163953Srrs		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
672163953Srrs			sctp_audit_indx = 0;
673163953Srrs		}
674163953Srrs		rep = 1;
675169420Srrs		SCTP_PRINTF("real flight:%d net total was %d\n",
676163953Srrs		    stcb->asoc.total_flight, tot_out);
677163953Srrs		/* now corrective action */
678163953Srrs		TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
679163953Srrs
680163953Srrs			tot_out = 0;
681163953Srrs			TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
682163953Srrs				if ((chk->whoTo == lnet) &&
683163953Srrs				    (chk->sent < SCTP_DATAGRAM_RESEND)) {
684163953Srrs					tot_out += chk->book_size;
685163953Srrs				}
686163953Srrs			}
687163953Srrs			if (lnet->flight_size != tot_out) {
688207099Stuexen				SCTP_PRINTF("net:%p flight was %d corrected to %d\n",
689252927Stuexen				    (void *)lnet, lnet->flight_size,
690169420Srrs				    tot_out);
691163953Srrs				lnet->flight_size = tot_out;
692163953Srrs			}
693163953Srrs		}
694163953Srrs	}
695163953Srrs	if (rep) {
696163953Srrs		sctp_print_audit_report();
697163953Srrs	}
698163953Srrs}
699163953Srrs
700163953Srrsvoid
701163953Srrssctp_audit_log(uint8_t ev, uint8_t fd)
702163953Srrs{
703163953Srrs
704163953Srrs	sctp_audit_data[sctp_audit_indx][0] = ev;
705163953Srrs	sctp_audit_data[sctp_audit_indx][1] = fd;
706163953Srrs	sctp_audit_indx++;
707163953Srrs	if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
708163953Srrs		sctp_audit_indx = 0;
709163953Srrs	}
710163953Srrs}
711163953Srrs
712163953Srrs#endif
713163953Srrs
714163953Srrs/*
715214918Stuexen * sctp_stop_timers_for_shutdown() should be called
716214918Stuexen * when entering the SHUTDOWN_SENT or SHUTDOWN_ACK_SENT
717214918Stuexen * state to make sure that all timers are stopped.
718214918Stuexen */
719214918Stuexenvoid
720214918Stuexensctp_stop_timers_for_shutdown(struct sctp_tcb *stcb)
721214918Stuexen{
722214918Stuexen	struct sctp_association *asoc;
723214918Stuexen	struct sctp_nets *net;
724214918Stuexen
725214918Stuexen	asoc = &stcb->asoc;
726214918Stuexen
727214918Stuexen	(void)SCTP_OS_TIMER_STOP(&asoc->dack_timer.timer);
728214918Stuexen	(void)SCTP_OS_TIMER_STOP(&asoc->strreset_timer.timer);
729214918Stuexen	(void)SCTP_OS_TIMER_STOP(&asoc->asconf_timer.timer);
730214918Stuexen	(void)SCTP_OS_TIMER_STOP(&asoc->autoclose_timer.timer);
731214918Stuexen	(void)SCTP_OS_TIMER_STOP(&asoc->delayed_event_timer.timer);
732214918Stuexen	TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
733214918Stuexen		(void)SCTP_OS_TIMER_STOP(&net->pmtu_timer.timer);
734224641Stuexen		(void)SCTP_OS_TIMER_STOP(&net->hb_timer.timer);
735214918Stuexen	}
736214918Stuexen}
737214918Stuexen
738214918Stuexen/*
739163953Srrs * a list of sizes based on typical mtu's, used only if next hop size not
740163953Srrs * returned.
741163953Srrs */
742214939Stuexenstatic uint32_t sctp_mtu_sizes[] = {
743163953Srrs	68,
744163953Srrs	296,
745163953Srrs	508,
746163953Srrs	512,
747163953Srrs	544,
748163953Srrs	576,
749163953Srrs	1006,
750163953Srrs	1492,
751163953Srrs	1500,
752163953Srrs	1536,
753163953Srrs	2002,
754163953Srrs	2048,
755163953Srrs	4352,
756163953Srrs	4464,
757163953Srrs	8166,
758163953Srrs	17914,
759163953Srrs	32000,
760163953Srrs	65535
761163953Srrs};
762163953Srrs
763214939Stuexen/*
764214939Stuexen * Return the largest MTU smaller than val. If there is no
765214939Stuexen * entry, just return val.
766214939Stuexen */
767214939Stuexenuint32_t
768214939Stuexensctp_get_prev_mtu(uint32_t val)
769163953Srrs{
770214939Stuexen	uint32_t i;
771163953Srrs
772214939Stuexen	if (val <= sctp_mtu_sizes[0]) {
773214939Stuexen		return (val);
774214939Stuexen	}
775214939Stuexen	for (i = 1; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) {
776214939Stuexen		if (val <= sctp_mtu_sizes[i]) {
777163953Srrs			break;
778163953Srrs		}
779163953Srrs	}
780214939Stuexen	return (sctp_mtu_sizes[i - 1]);
781163953Srrs}
782163953Srrs
783214939Stuexen/*
784214939Stuexen * Return the smallest MTU larger than val. If there is no
785214939Stuexen * entry, just return val.
786214939Stuexen */
787214939Stuexenuint32_t
788231038Stuexensctp_get_next_mtu(uint32_t val)
789214939Stuexen{
790214939Stuexen	/* select another MTU that is just bigger than this one */
791214939Stuexen	uint32_t i;
792214939Stuexen
793214939Stuexen	for (i = 0; i < (sizeof(sctp_mtu_sizes) / sizeof(uint32_t)); i++) {
794214939Stuexen		if (val < sctp_mtu_sizes[i]) {
795214939Stuexen			return (sctp_mtu_sizes[i]);
796214939Stuexen		}
797214939Stuexen	}
798214939Stuexen	return (val);
799214939Stuexen}
800214939Stuexen
801163953Srrsvoid
802163953Srrssctp_fill_random_store(struct sctp_pcb *m)
803163953Srrs{
804163953Srrs	/*
805163953Srrs	 * Here we use the MD5/SHA-1 to hash with our good randomNumbers and
806163953Srrs	 * our counter. The result becomes our good random numbers and we
807163953Srrs	 * then setup to give these out. Note that we do no locking to
808163953Srrs	 * protect this. This is ok, since if competing folks call this we
809169352Srrs	 * will get more gobbled gook in the random store which is what we
810163953Srrs	 * want. There is a danger that two guys will use the same random
811163953Srrs	 * numbers, but thats ok too since that is random as well :->
812163953Srrs	 */
813163953Srrs	m->store_at = 0;
814169420Srrs	(void)sctp_hmac(SCTP_HMAC, (uint8_t *) m->random_numbers,
815163953Srrs	    sizeof(m->random_numbers), (uint8_t *) & m->random_counter,
816163953Srrs	    sizeof(m->random_counter), (uint8_t *) m->random_store);
817163953Srrs	m->random_counter++;
818163953Srrs}
819163953Srrs
820163953Srrsuint32_t
821172091Srrssctp_select_initial_TSN(struct sctp_pcb *inp)
822163953Srrs{
823163953Srrs	/*
824163953Srrs	 * A true implementation should use random selection process to get
825163953Srrs	 * the initial stream sequence number, using RFC1750 as a good
826163953Srrs	 * guideline
827163953Srrs	 */
828165647Srrs	uint32_t x, *xp;
829163953Srrs	uint8_t *p;
830172091Srrs	int store_at, new_store;
831163953Srrs
832172091Srrs	if (inp->initial_sequence_debug != 0) {
833163953Srrs		uint32_t ret;
834163953Srrs
835172091Srrs		ret = inp->initial_sequence_debug;
836172091Srrs		inp->initial_sequence_debug++;
837163953Srrs		return (ret);
838163953Srrs	}
839172091Srrsretry:
840172091Srrs	store_at = inp->store_at;
841172091Srrs	new_store = store_at + sizeof(uint32_t);
842172091Srrs	if (new_store >= (SCTP_SIGNATURE_SIZE - 3)) {
843172091Srrs		new_store = 0;
844172091Srrs	}
845172091Srrs	if (!atomic_cmpset_int(&inp->store_at, store_at, new_store)) {
846172091Srrs		goto retry;
847172091Srrs	}
848172091Srrs	if (new_store == 0) {
849163953Srrs		/* Refill the random store */
850172091Srrs		sctp_fill_random_store(inp);
851163953Srrs	}
852172091Srrs	p = &inp->random_store[store_at];
853165647Srrs	xp = (uint32_t *) p;
854163953Srrs	x = *xp;
855163953Srrs	return (x);
856163953Srrs}
857163953Srrs
858163953Srrsuint32_t
859231038Stuexensctp_select_a_tag(struct sctp_inpcb *inp, uint16_t lport, uint16_t rport, int check)
860163953Srrs{
861231038Stuexen	uint32_t x;
862163953Srrs	struct timeval now;
863163953Srrs
864231038Stuexen	if (check) {
865231038Stuexen		(void)SCTP_GETTIME_TIMEVAL(&now);
866231038Stuexen	}
867231038Stuexen	for (;;) {
868172091Srrs		x = sctp_select_initial_TSN(&inp->sctp_ep);
869163953Srrs		if (x == 0) {
870163953Srrs			/* we never use 0 */
871163953Srrs			continue;
872163953Srrs		}
873231038Stuexen		if (!check || sctp_is_vtag_good(x, lport, rport, &now)) {
874231038Stuexen			break;
875163953Srrs		}
876163953Srrs	}
877163953Srrs	return (x);
878163953Srrs}
879163953Srrs
880163953Srrsint
881252961Stuexensctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
882206137Stuexen    uint32_t override_tag, uint32_t vrf_id)
883163953Srrs{
884170138Srrs	struct sctp_association *asoc;
885170138Srrs
886163953Srrs	/*
887163953Srrs	 * Anything set to zero is taken care of by the allocation routine's
888163953Srrs	 * bzero
889163953Srrs	 */
890163953Srrs
891163953Srrs	/*
892163953Srrs	 * Up front select what scoping to apply on addresses I tell my peer
893163953Srrs	 * Not sure what to do with these right now, we will need to come up
894163953Srrs	 * with a way to set them. We may need to pass them through from the
895163953Srrs	 * caller in the sctp_aloc_assoc() function.
896163953Srrs	 */
897163953Srrs	int i;
898163953Srrs
899170138Srrs	asoc = &stcb->asoc;
900163953Srrs	/* init all variables to a known value. */
901171943Srrs	SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE);
902252961Stuexen	asoc->max_burst = inp->sctp_ep.max_burst;
903252961Stuexen	asoc->fr_max_burst = inp->sctp_ep.fr_max_burst;
904252961Stuexen	asoc->heart_beat_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
905252961Stuexen	asoc->cookie_life = inp->sctp_ep.def_cookie_life;
906252961Stuexen	asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off;
907252961Stuexen	asoc->ecn_allowed = inp->sctp_ecn_enable;
908185694Srrs	asoc->sctp_nr_sack_on_off = (uint8_t) SCTP_BASE_SYSCTL(sctp_nr_sack_on_off);
909224641Stuexen	asoc->sctp_cmt_pf = (uint8_t) 0;
910252961Stuexen	asoc->sctp_frag_point = inp->sctp_frag_point;
911252961Stuexen	asoc->sctp_features = inp->sctp_features;
912252961Stuexen	asoc->default_dscp = inp->sctp_ep.default_dscp;
913167598Srrs#ifdef INET6
914252961Stuexen	if (inp->sctp_ep.default_flowlabel) {
915252961Stuexen		asoc->default_flowlabel = inp->sctp_ep.default_flowlabel;
916225549Stuexen	} else {
917252961Stuexen		if (inp->ip_inp.inp.inp_flags & IN6P_AUTOFLOWLABEL) {
918252961Stuexen			asoc->default_flowlabel = sctp_select_initial_TSN(&inp->sctp_ep);
919225549Stuexen			asoc->default_flowlabel &= 0x000fffff;
920225549Stuexen			asoc->default_flowlabel |= 0x80000000;
921225549Stuexen		} else {
922225549Stuexen			asoc->default_flowlabel = 0;
923225549Stuexen		}
924225549Stuexen	}
925163953Srrs#endif
926174257Srrs	asoc->sb_send_resv = 0;
927163953Srrs	if (override_tag) {
928185694Srrs		asoc->my_vtag = override_tag;
929163953Srrs	} else {
930252961Stuexen		asoc->my_vtag = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 1);
931163953Srrs	}
932164144Srrs	/* Get the nonce tags */
933252961Stuexen	asoc->my_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
934252961Stuexen	asoc->peer_vtag_nonce = sctp_select_a_tag(inp, stcb->sctp_ep->sctp_lport, stcb->rport, 0);
935167598Srrs	asoc->vrf_id = vrf_id;
936164144Srrs
937171477Srrs#ifdef SCTP_ASOCLOG_OF_TSNS
938171477Srrs	asoc->tsn_in_at = 0;
939171477Srrs	asoc->tsn_out_at = 0;
940171477Srrs	asoc->tsn_in_wrapped = 0;
941171477Srrs	asoc->tsn_out_wrapped = 0;
942171477Srrs	asoc->cumack_log_at = 0;
943172703Srrs	asoc->cumack_log_atsnt = 0;
944171477Srrs#endif
945171477Srrs#ifdef SCTP_FS_SPEC_LOG
946171477Srrs	asoc->fs_index = 0;
947171477Srrs#endif
948163953Srrs	asoc->refcnt = 0;
949163953Srrs	asoc->assoc_up_sent = 0;
950163953Srrs	asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq =
951252961Stuexen	    sctp_select_initial_TSN(&inp->sctp_ep);
952179157Srrs	asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
953163953Srrs	/* we are optimisitic here */
954163953Srrs	asoc->peer_supports_pktdrop = 1;
955185694Srrs	asoc->peer_supports_nat = 0;
956163953Srrs	asoc->sent_queue_retran_cnt = 0;
957163953Srrs
958163953Srrs	/* for CMT */
959190689Srrs	asoc->last_net_cmt_send_started = NULL;
960163953Srrs
961163953Srrs	/* This will need to be adjusted */
962163953Srrs	asoc->last_acked_seq = asoc->init_seq_number - 1;
963163953Srrs	asoc->advanced_peer_ack_point = asoc->last_acked_seq;
964163953Srrs	asoc->asconf_seq_in = asoc->last_acked_seq;
965163953Srrs
966163953Srrs	/* here we are different, we hold the next one we expect */
967163953Srrs	asoc->str_reset_seq_in = asoc->last_acked_seq + 1;
968163953Srrs
969252961Stuexen	asoc->initial_init_rto_max = inp->sctp_ep.initial_init_rto_max;
970252961Stuexen	asoc->initial_rto = inp->sctp_ep.initial_rto;
971163953Srrs
972252961Stuexen	asoc->max_init_times = inp->sctp_ep.max_init_times;
973252961Stuexen	asoc->max_send_times = inp->sctp_ep.max_send_times;
974252961Stuexen	asoc->def_net_failure = inp->sctp_ep.def_net_failure;
975252961Stuexen	asoc->def_net_pf_threshold = inp->sctp_ep.def_net_pf_threshold;
976163953Srrs	asoc->free_chunk_cnt = 0;
977163953Srrs
978163953Srrs	asoc->iam_blocking = 0;
979252961Stuexen	asoc->context = inp->sctp_context;
980252961Stuexen	asoc->local_strreset_support = inp->local_strreset_support;
981252961Stuexen	asoc->def_send = inp->def_send;
982252961Stuexen	asoc->delayed_ack = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
983252961Stuexen	asoc->sack_freq = inp->sctp_ep.sctp_sack_freq;
984163953Srrs	asoc->pr_sctp_cnt = 0;
985163953Srrs	asoc->total_output_queue_size = 0;
986163953Srrs
987252961Stuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
988252961Stuexen		asoc->scope.ipv6_addr_legal = 1;
989252961Stuexen		if (SCTP_IPV6_V6ONLY(inp) == 0) {
990252961Stuexen			asoc->scope.ipv4_addr_legal = 1;
991163953Srrs		} else {
992252961Stuexen			asoc->scope.ipv4_addr_legal = 0;
993163953Srrs		}
994163953Srrs	} else {
995252961Stuexen		asoc->scope.ipv6_addr_legal = 0;
996252961Stuexen		asoc->scope.ipv4_addr_legal = 1;
997163953Srrs	}
998163953Srrs
999252961Stuexen	asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND);
1000252961Stuexen	asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(inp->sctp_socket);
1001163953Srrs
1002252961Stuexen	asoc->smallest_mtu = inp->sctp_frag_point;
1003252961Stuexen	asoc->minrto = inp->sctp_ep.sctp_minrto;
1004252961Stuexen	asoc->maxrto = inp->sctp_ep.sctp_maxrto;
1005163953Srrs
1006163953Srrs	asoc->locked_on_sending = NULL;
1007163953Srrs	asoc->stream_locked_on = 0;
1008163953Srrs	asoc->ecn_echo_cnt_onq = 0;
1009163953Srrs	asoc->stream_locked = 0;
1010163953Srrs
1011167598Srrs	asoc->send_sack = 1;
1012167598Srrs
1013167598Srrs	LIST_INIT(&asoc->sctp_restricted_addrs);
1014167598Srrs
1015163953Srrs	TAILQ_INIT(&asoc->nets);
1016163953Srrs	TAILQ_INIT(&asoc->pending_reply_queue);
1017171990Srrs	TAILQ_INIT(&asoc->asconf_ack_sent);
1018163953Srrs	/* Setup to fill the hb random cache at first HB */
1019163953Srrs	asoc->hb_random_idx = 4;
1020163953Srrs
1021252961Stuexen	asoc->sctp_autoclose_ticks = inp->sctp_ep.auto_close_time;
1022163953Srrs
1023252961Stuexen	stcb->asoc.congestion_control_module = inp->sctp_ep.sctp_default_cc_module;
1024252961Stuexen	stcb->asoc.cc_functions = sctp_cc_functions[inp->sctp_ep.sctp_default_cc_module];
1025171440Srrs
1026252961Stuexen	stcb->asoc.stream_scheduling_module = inp->sctp_ep.sctp_default_ss_module;
1027252961Stuexen	stcb->asoc.ss_functions = sctp_ss_functions[inp->sctp_ep.sctp_default_ss_module];
1028217760Stuexen
1029171440Srrs	/*
1030163953Srrs	 * Now the stream parameters, here we allocate space for all streams
1031163953Srrs	 * that we request by default.
1032163953Srrs	 */
1033188854Srrs	asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams =
1034252961Stuexen	    inp->sctp_ep.pre_open_stream_count;
1035163953Srrs	SCTP_MALLOC(asoc->strmout, struct sctp_stream_out *,
1036163953Srrs	    asoc->streamoutcnt * sizeof(struct sctp_stream_out),
1037170091Srrs	    SCTP_M_STRMO);
1038163953Srrs	if (asoc->strmout == NULL) {
1039163953Srrs		/* big trouble no memory */
1040171943Srrs		SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
1041163953Srrs		return (ENOMEM);
1042163953Srrs	}
1043163953Srrs	for (i = 0; i < asoc->streamoutcnt; i++) {
1044163953Srrs		/*
1045163953Srrs		 * inbound side must be set to 0xffff, also NOTE when we get
1046163953Srrs		 * the INIT-ACK back (for INIT sender) we MUST reduce the
1047163953Srrs		 * count (streamoutcnt) but first check if we sent to any of
1048163953Srrs		 * the upper streams that were dropped (if some were). Those
1049163953Srrs		 * that were dropped must be notified to the upper layer as
1050163953Srrs		 * failed to send.
1051163953Srrs		 */
1052252940Stuexen		asoc->strmout[i].next_sequence_send = 0x0;
1053163953Srrs		TAILQ_INIT(&asoc->strmout[i].outqueue);
1054252943Stuexen		asoc->strmout[i].chunks_on_queues = 0;
1055163953Srrs		asoc->strmout[i].stream_no = i;
1056163953Srrs		asoc->strmout[i].last_msg_incomplete = 0;
1057218241Stuexen		asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
1058163953Srrs	}
1059217760Stuexen	asoc->ss_functions.sctp_ss_init(stcb, asoc, 0);
1060217760Stuexen
1061163953Srrs	/* Now the mapping array */
1062163953Srrs	asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;
1063163953Srrs	SCTP_MALLOC(asoc->mapping_array, uint8_t *, asoc->mapping_array_size,
1064170091Srrs	    SCTP_M_MAP);
1065163953Srrs	if (asoc->mapping_array == NULL) {
1066170091Srrs		SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
1067171943Srrs		SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
1068163953Srrs		return (ENOMEM);
1069163953Srrs	}
1070163953Srrs	memset(asoc->mapping_array, 0, asoc->mapping_array_size);
1071206137Stuexen	SCTP_MALLOC(asoc->nr_mapping_array, uint8_t *, asoc->mapping_array_size,
1072185694Srrs	    SCTP_M_MAP);
1073193089Srrs	if (asoc->nr_mapping_array == NULL) {
1074193089Srrs		SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
1075193089Srrs		SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
1076193089Srrs		SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
1077193089Srrs		return (ENOMEM);
1078193089Srrs	}
1079206137Stuexen	memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size);
1080185694Srrs
1081163953Srrs	/* Now the init of the other outqueues */
1082163953Srrs	TAILQ_INIT(&asoc->free_chunks);
1083163953Srrs	TAILQ_INIT(&asoc->control_send_queue);
1084179157Srrs	TAILQ_INIT(&asoc->asconf_send_queue);
1085163953Srrs	TAILQ_INIT(&asoc->send_queue);
1086163953Srrs	TAILQ_INIT(&asoc->sent_queue);
1087163953Srrs	TAILQ_INIT(&asoc->reasmqueue);
1088163953Srrs	TAILQ_INIT(&asoc->resetHead);
1089252961Stuexen	asoc->max_inbound_streams = inp->sctp_ep.max_open_streams_intome;
1090163953Srrs	TAILQ_INIT(&asoc->asconf_queue);
1091163953Srrs	/* authentication fields */
1092163953Srrs	asoc->authinfo.random = NULL;
1093185694Srrs	asoc->authinfo.active_keyid = 0;
1094163953Srrs	asoc->authinfo.assoc_key = NULL;
1095163953Srrs	asoc->authinfo.assoc_keyid = 0;
1096163953Srrs	asoc->authinfo.recv_key = NULL;
1097163953Srrs	asoc->authinfo.recv_keyid = 0;
1098163953Srrs	LIST_INIT(&asoc->shared_keys);
1099166675Srrs	asoc->marked_retrans = 0;
1100252961Stuexen	asoc->port = inp->sctp_ep.port;
1101166675Srrs	asoc->timoinit = 0;
1102166675Srrs	asoc->timodata = 0;
1103166675Srrs	asoc->timosack = 0;
1104166675Srrs	asoc->timoshutdown = 0;
1105166675Srrs	asoc->timoheartbeat = 0;
1106166675Srrs	asoc->timocookie = 0;
1107166675Srrs	asoc->timoshutdownack = 0;
1108169378Srrs	(void)SCTP_GETTIME_TIMEVAL(&asoc->start_time);
1109169378Srrs	asoc->discontinuity_time = asoc->start_time;
1110170931Srrs	/*
1111170931Srrs	 * sa_ignore MEMLEAK {memory is put in the assoc mapping array and
1112205627Srrs	 * freed later when the association is freed.
1113170931Srrs	 */
1114163953Srrs	return (0);
1115163953Srrs}
1116163953Srrs
1117205502Srrsvoid
1118205502Srrssctp_print_mapping_array(struct sctp_association *asoc)
1119205502Srrs{
1120206281Stuexen	unsigned int i, limit;
1121205502Srrs
1122235164Stuexen	SCTP_PRINTF("Mapping array size: %d, baseTSN: %8.8x, cumAck: %8.8x, highestTSN: (%8.8x, %8.8x).\n",
1123205502Srrs	    asoc->mapping_array_size,
1124205502Srrs	    asoc->mapping_array_base_tsn,
1125205502Srrs	    asoc->cumulative_tsn,
1126206281Stuexen	    asoc->highest_tsn_inside_map,
1127206281Stuexen	    asoc->highest_tsn_inside_nr_map);
1128206281Stuexen	for (limit = asoc->mapping_array_size; limit > 1; limit--) {
1129231039Stuexen		if (asoc->mapping_array[limit - 1] != 0) {
1130205627Srrs			break;
1131205627Srrs		}
1132205627Srrs	}
1133235164Stuexen	SCTP_PRINTF("Renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
1134205627Srrs	for (i = 0; i < limit; i++) {
1135235164Stuexen		SCTP_PRINTF("%2.2x%c", asoc->mapping_array[i], ((i + 1) % 16) ? ' ' : '\n');
1136205502Srrs	}
1137206281Stuexen	if (limit % 16)
1138235164Stuexen		SCTP_PRINTF("\n");
1139206281Stuexen	for (limit = asoc->mapping_array_size; limit > 1; limit--) {
1140206281Stuexen		if (asoc->nr_mapping_array[limit - 1]) {
1141205627Srrs			break;
1142205627Srrs		}
1143205627Srrs	}
1144235164Stuexen	SCTP_PRINTF("Non renegable mapping array (last %d entries are zero):\n", asoc->mapping_array_size - limit);
1145205627Srrs	for (i = 0; i < limit; i++) {
1146235164Stuexen		SCTP_PRINTF("%2.2x%c", asoc->nr_mapping_array[i], ((i + 1) % 16) ? ' ' : '\n');
1147205627Srrs	}
1148206281Stuexen	if (limit % 16)
1149235164Stuexen		SCTP_PRINTF("\n");
1150205502Srrs}
1151205502Srrs
1152163953Srrsint
1153170138Srrssctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed)
1154163953Srrs{
1155163953Srrs	/* mapping array needs to grow */
1156206137Stuexen	uint8_t *new_array1, *new_array2;
1157170138Srrs	uint32_t new_size;
1158163953Srrs
1159170138Srrs	new_size = asoc->mapping_array_size + ((needed + 7) / 8 + SCTP_MAPPING_ARRAY_INCR);
1160206137Stuexen	SCTP_MALLOC(new_array1, uint8_t *, new_size, SCTP_M_MAP);
1161206137Stuexen	SCTP_MALLOC(new_array2, uint8_t *, new_size, SCTP_M_MAP);
1162206137Stuexen	if ((new_array1 == NULL) || (new_array2 == NULL)) {
1163163953Srrs		/* can't get more, forget it */
1164206137Stuexen		SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n", new_size);
1165206137Stuexen		if (new_array1) {
1166206137Stuexen			SCTP_FREE(new_array1, SCTP_M_MAP);
1167206137Stuexen		}
1168206137Stuexen		if (new_array2) {
1169206137Stuexen			SCTP_FREE(new_array2, SCTP_M_MAP);
1170206137Stuexen		}
1171163953Srrs		return (-1);
1172163953Srrs	}
1173206137Stuexen	memset(new_array1, 0, new_size);
1174206137Stuexen	memset(new_array2, 0, new_size);
1175206137Stuexen	memcpy(new_array1, asoc->mapping_array, asoc->mapping_array_size);
1176206137Stuexen	memcpy(new_array2, asoc->nr_mapping_array, asoc->mapping_array_size);
1177170091Srrs	SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
1178206137Stuexen	SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP);
1179206137Stuexen	asoc->mapping_array = new_array1;
1180206137Stuexen	asoc->nr_mapping_array = new_array2;
1181163953Srrs	asoc->mapping_array_size = new_size;
1182163953Srrs	return (0);
1183163953Srrs}
1184163953Srrs
1185185694Srrs
1186167598Srrsstatic void
1187167598Srrssctp_iterator_work(struct sctp_iterator *it)
1188167598Srrs{
1189167598Srrs	int iteration_count = 0;
1190167598Srrs	int inp_skip = 0;
1191209029Srrs	int first_in = 1;
1192209029Srrs	struct sctp_inpcb *tinp;
1193163953Srrs
1194209029Srrs	SCTP_INP_INFO_RLOCK();
1195167598Srrs	SCTP_ITERATOR_LOCK();
1196169420Srrs	if (it->inp) {
1197209029Srrs		SCTP_INP_RLOCK(it->inp);
1198167598Srrs		SCTP_INP_DECR_REF(it->inp);
1199169420Srrs	}
1200167598Srrs	if (it->inp == NULL) {
1201167598Srrs		/* iterator is complete */
1202167598Srrsdone_with_iterator:
1203167598Srrs		SCTP_ITERATOR_UNLOCK();
1204209029Srrs		SCTP_INP_INFO_RUNLOCK();
1205167598Srrs		if (it->function_atend != NULL) {
1206167598Srrs			(*it->function_atend) (it->pointer, it->val);
1207167598Srrs		}
1208170091Srrs		SCTP_FREE(it, SCTP_M_ITER);
1209167598Srrs		return;
1210167598Srrs	}
1211167598Srrsselect_a_new_ep:
1212209029Srrs	if (first_in) {
1213209029Srrs		first_in = 0;
1214209029Srrs	} else {
1215209029Srrs		SCTP_INP_RLOCK(it->inp);
1216209029Srrs	}
1217167598Srrs	while (((it->pcb_flags) &&
1218167598Srrs	    ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) ||
1219167598Srrs	    ((it->pcb_features) &&
1220167598Srrs	    ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) {
1221167598Srrs		/* endpoint flags or features don't match, so keep looking */
1222167598Srrs		if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
1223208160Srrs			SCTP_INP_RUNLOCK(it->inp);
1224167598Srrs			goto done_with_iterator;
1225167598Srrs		}
1226209029Srrs		tinp = it->inp;
1227167598Srrs		it->inp = LIST_NEXT(it->inp, sctp_list);
1228209029Srrs		SCTP_INP_RUNLOCK(tinp);
1229167598Srrs		if (it->inp == NULL) {
1230167598Srrs			goto done_with_iterator;
1231167598Srrs		}
1232208160Srrs		SCTP_INP_RLOCK(it->inp);
1233167598Srrs	}
1234167598Srrs	/* now go through each assoc which is in the desired state */
1235167598Srrs	if (it->done_current_ep == 0) {
1236167598Srrs		if (it->function_inp != NULL)
1237167598Srrs			inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val);
1238167598Srrs		it->done_current_ep = 1;
1239167598Srrs	}
1240167598Srrs	if (it->stcb == NULL) {
1241167598Srrs		/* run the per instance function */
1242167598Srrs		it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
1243167598Srrs	}
1244167598Srrs	if ((inp_skip) || it->stcb == NULL) {
1245167598Srrs		if (it->function_inp_end != NULL) {
1246167598Srrs			inp_skip = (*it->function_inp_end) (it->inp,
1247167598Srrs			    it->pointer,
1248167598Srrs			    it->val);
1249167598Srrs		}
1250167598Srrs		SCTP_INP_RUNLOCK(it->inp);
1251167598Srrs		goto no_stcb;
1252167598Srrs	}
1253167598Srrs	while (it->stcb) {
1254167598Srrs		SCTP_TCB_LOCK(it->stcb);
1255167598Srrs		if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
1256167598Srrs			/* not in the right state... keep looking */
1257167598Srrs			SCTP_TCB_UNLOCK(it->stcb);
1258167598Srrs			goto next_assoc;
1259167598Srrs		}
1260167598Srrs		/* see if we have limited out the iterator loop */
1261167598Srrs		iteration_count++;
1262167598Srrs		if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) {
1263167598Srrs			/* Pause to let others grab the lock */
1264167598Srrs			atomic_add_int(&it->stcb->asoc.refcnt, 1);
1265167598Srrs			SCTP_TCB_UNLOCK(it->stcb);
1266171943Srrs			SCTP_INP_INCR_REF(it->inp);
1267167598Srrs			SCTP_INP_RUNLOCK(it->inp);
1268167598Srrs			SCTP_ITERATOR_UNLOCK();
1269209029Srrs			SCTP_INP_INFO_RUNLOCK();
1270209029Srrs			SCTP_INP_INFO_RLOCK();
1271167598Srrs			SCTP_ITERATOR_LOCK();
1272208160Srrs			if (sctp_it_ctl.iterator_flags) {
1273208160Srrs				/* We won't be staying here */
1274208160Srrs				SCTP_INP_DECR_REF(it->inp);
1275208160Srrs				atomic_add_int(&it->stcb->asoc.refcnt, -1);
1276208160Srrs				if (sctp_it_ctl.iterator_flags &
1277208160Srrs				    SCTP_ITERATOR_STOP_CUR_IT) {
1278208160Srrs					sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_IT;
1279208160Srrs					goto done_with_iterator;
1280208160Srrs				}
1281208160Srrs				if (sctp_it_ctl.iterator_flags &
1282208160Srrs				    SCTP_ITERATOR_STOP_CUR_INP) {
1283208160Srrs					sctp_it_ctl.iterator_flags &= ~SCTP_ITERATOR_STOP_CUR_INP;
1284208160Srrs					goto no_stcb;
1285208160Srrs				}
1286208160Srrs				/* If we reach here huh? */
1287235164Stuexen				SCTP_PRINTF("Unknown it ctl flag %x\n",
1288208160Srrs				    sctp_it_ctl.iterator_flags);
1289208160Srrs				sctp_it_ctl.iterator_flags = 0;
1290208160Srrs			}
1291167598Srrs			SCTP_INP_RLOCK(it->inp);
1292171943Srrs			SCTP_INP_DECR_REF(it->inp);
1293167598Srrs			SCTP_TCB_LOCK(it->stcb);
1294167598Srrs			atomic_add_int(&it->stcb->asoc.refcnt, -1);
1295167598Srrs			iteration_count = 0;
1296167598Srrs		}
1297167598Srrs		/* run function on this one */
1298167598Srrs		(*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val);
1299167598Srrs
1300167598Srrs		/*
1301167598Srrs		 * we lie here, it really needs to have its own type but
1302167598Srrs		 * first I must verify that this won't effect things :-0
1303167598Srrs		 */
1304167598Srrs		if (it->no_chunk_output == 0)
1305172090Srrs			sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
1306167598Srrs
1307167598Srrs		SCTP_TCB_UNLOCK(it->stcb);
1308167598Srrsnext_assoc:
1309167598Srrs		it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
1310167598Srrs		if (it->stcb == NULL) {
1311167598Srrs			/* Run last function */
1312167598Srrs			if (it->function_inp_end != NULL) {
1313167598Srrs				inp_skip = (*it->function_inp_end) (it->inp,
1314167598Srrs				    it->pointer,
1315167598Srrs				    it->val);
1316167598Srrs			}
1317167598Srrs		}
1318167598Srrs	}
1319167598Srrs	SCTP_INP_RUNLOCK(it->inp);
1320167598Srrsno_stcb:
1321167598Srrs	/* done with all assocs on this endpoint, move on to next endpoint */
1322167598Srrs	it->done_current_ep = 0;
1323167598Srrs	if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
1324167598Srrs		it->inp = NULL;
1325167598Srrs	} else {
1326167598Srrs		it->inp = LIST_NEXT(it->inp, sctp_list);
1327167598Srrs	}
1328167598Srrs	if (it->inp == NULL) {
1329167598Srrs		goto done_with_iterator;
1330167598Srrs	}
1331167598Srrs	goto select_a_new_ep;
1332167598Srrs}
1333167598Srrs
1334167598Srrsvoid
1335167598Srrssctp_iterator_worker(void)
1336167598Srrs{
1337216822Stuexen	struct sctp_iterator *it, *nit;
1338167598Srrs
1339167598Srrs	/* This function is called with the WQ lock in place */
1340167598Srrs
1341208160Srrs	sctp_it_ctl.iterator_running = 1;
1342216822Stuexen	TAILQ_FOREACH_SAFE(it, &sctp_it_ctl.iteratorhead, sctp_nxt_itr, nit) {
1343216822Stuexen		sctp_it_ctl.cur_it = it;
1344167598Srrs		/* now lets work on this one */
1345208160Srrs		TAILQ_REMOVE(&sctp_it_ctl.iteratorhead, it, sctp_nxt_itr);
1346167598Srrs		SCTP_IPI_ITERATOR_WQ_UNLOCK();
1347208160Srrs		CURVNET_SET(it->vn);
1348167598Srrs		sctp_iterator_work(it);
1349219397Srrs		sctp_it_ctl.cur_it = NULL;
1350208160Srrs		CURVNET_RESTORE();
1351167598Srrs		SCTP_IPI_ITERATOR_WQ_LOCK();
1352169655Srrs		/* sa_ignore FREED_MEMORY */
1353167598Srrs	}
1354208160Srrs	sctp_it_ctl.iterator_running = 0;
1355167598Srrs	return;
1356167598Srrs}
1357167598Srrs
1358167598Srrs
1359163953Srrsstatic void
1360163953Srrssctp_handle_addr_wq(void)
1361163953Srrs{
1362163953Srrs	/* deal with the ADDR wq from the rtsock calls */
1363216822Stuexen	struct sctp_laddr *wi, *nwi;
1364167598Srrs	struct sctp_asconf_iterator *asc;
1365163953Srrs
1366167598Srrs	SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
1367170091Srrs	    sizeof(struct sctp_asconf_iterator), SCTP_M_ASC_IT);
1368167598Srrs	if (asc == NULL) {
1369167598Srrs		/* Try later, no memory */
1370163953Srrs		sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
1371163953Srrs		    (struct sctp_inpcb *)NULL,
1372163953Srrs		    (struct sctp_tcb *)NULL,
1373163953Srrs		    (struct sctp_nets *)NULL);
1374167598Srrs		return;
1375163953Srrs	}
1376167598Srrs	LIST_INIT(&asc->list_of_work);
1377167598Srrs	asc->cnt = 0;
1378208160Srrs
1379208160Srrs	SCTP_WQ_ADDR_LOCK();
1380216822Stuexen	LIST_FOREACH_SAFE(wi, &SCTP_BASE_INFO(addr_wq), sctp_nxt_addr, nwi) {
1381167598Srrs		LIST_REMOVE(wi, sctp_nxt_addr);
1382167598Srrs		LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
1383167598Srrs		asc->cnt++;
1384163953Srrs	}
1385208160Srrs	SCTP_WQ_ADDR_UNLOCK();
1386208160Srrs
1387167598Srrs	if (asc->cnt == 0) {
1388170091Srrs		SCTP_FREE(asc, SCTP_M_ASC_IT);
1389167598Srrs	} else {
1390171572Srrs		(void)sctp_initiate_iterator(sctp_asconf_iterator_ep,
1391171572Srrs		    sctp_asconf_iterator_stcb,
1392167598Srrs		    NULL,	/* No ep end for boundall */
1393167598Srrs		    SCTP_PCB_FLAGS_BOUNDALL,
1394167598Srrs		    SCTP_PCB_ANY_FEATURES,
1395171572Srrs		    SCTP_ASOC_ANY_STATE,
1396171572Srrs		    (void *)asc, 0,
1397171572Srrs		    sctp_asconf_iterator_end, NULL, 0);
1398167598Srrs	}
1399163953Srrs}
1400163953Srrs
1401163953Srrsvoid
1402163953Srrssctp_timeout_handler(void *t)
1403163953Srrs{
1404163953Srrs	struct sctp_inpcb *inp;
1405163953Srrs	struct sctp_tcb *stcb;
1406163953Srrs	struct sctp_nets *net;
1407163953Srrs	struct sctp_timer *tmr;
1408172090Srrs
1409252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1410172090Srrs	struct socket *so;
1411172090Srrs
1412172090Srrs#endif
1413179180Srrs	int did_output, type;
1414163953Srrs
1415163953Srrs	tmr = (struct sctp_timer *)t;
1416163953Srrs	inp = (struct sctp_inpcb *)tmr->ep;
1417163953Srrs	stcb = (struct sctp_tcb *)tmr->tcb;
1418163953Srrs	net = (struct sctp_nets *)tmr->net;
1419197326Stuexen	CURVNET_SET((struct vnet *)tmr->vnet);
1420163953Srrs	did_output = 1;
1421163953Srrs
1422163953Srrs#ifdef SCTP_AUDITING_ENABLED
1423163953Srrs	sctp_audit_log(0xF0, (uint8_t) tmr->type);
1424163953Srrs	sctp_auditing(3, inp, stcb, net);
1425163953Srrs#endif
1426163953Srrs
1427163953Srrs	/* sanity checks... */
1428163953Srrs	if (tmr->self != (void *)tmr) {
1429163953Srrs		/*
1430169420Srrs		 * SCTP_PRINTF("Stale SCTP timer fired (%p), ignoring...\n",
1431252927Stuexen		 * (void *)tmr);
1432163953Srrs		 */
1433197326Stuexen		CURVNET_RESTORE();
1434163953Srrs		return;
1435163953Srrs	}
1436165220Srrs	tmr->stopped_from = 0xa001;
1437163953Srrs	if (!SCTP_IS_TIMER_TYPE_VALID(tmr->type)) {
1438163953Srrs		/*
1439169420Srrs		 * SCTP_PRINTF("SCTP timer fired with invalid type: 0x%x\n",
1440163953Srrs		 * tmr->type);
1441163953Srrs		 */
1442197326Stuexen		CURVNET_RESTORE();
1443163953Srrs		return;
1444163953Srrs	}
1445165220Srrs	tmr->stopped_from = 0xa002;
1446163953Srrs	if ((tmr->type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL)) {
1447197326Stuexen		CURVNET_RESTORE();
1448163953Srrs		return;
1449163953Srrs	}
1450163953Srrs	/* if this is an iterator timeout, get the struct and clear inp */
1451165220Srrs	tmr->stopped_from = 0xa003;
1452179180Srrs	type = tmr->type;
1453163953Srrs	if (inp) {
1454163953Srrs		SCTP_INP_INCR_REF(inp);
1455231040Stuexen		if ((inp->sctp_socket == NULL) &&
1456163953Srrs		    ((tmr->type != SCTP_TIMER_TYPE_INPKILL) &&
1457196260Stuexen		    (tmr->type != SCTP_TIMER_TYPE_INIT) &&
1458184883Srrs		    (tmr->type != SCTP_TIMER_TYPE_SEND) &&
1459184883Srrs		    (tmr->type != SCTP_TIMER_TYPE_RECV) &&
1460184883Srrs		    (tmr->type != SCTP_TIMER_TYPE_HEARTBEAT) &&
1461163953Srrs		    (tmr->type != SCTP_TIMER_TYPE_SHUTDOWN) &&
1462163953Srrs		    (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNACK) &&
1463163953Srrs		    (tmr->type != SCTP_TIMER_TYPE_SHUTDOWNGUARD) &&
1464163953Srrs		    (tmr->type != SCTP_TIMER_TYPE_ASOCKILL))
1465163953Srrs		    ) {
1466163953Srrs			SCTP_INP_DECR_REF(inp);
1467197326Stuexen			CURVNET_RESTORE();
1468163953Srrs			return;
1469163953Srrs		}
1470163953Srrs	}
1471165220Srrs	tmr->stopped_from = 0xa004;
1472163953Srrs	if (stcb) {
1473168709Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
1474163953Srrs		if (stcb->asoc.state == 0) {
1475168709Srrs			atomic_add_int(&stcb->asoc.refcnt, -1);
1476163953Srrs			if (inp) {
1477163953Srrs				SCTP_INP_DECR_REF(inp);
1478163953Srrs			}
1479197326Stuexen			CURVNET_RESTORE();
1480163953Srrs			return;
1481163953Srrs		}
1482163953Srrs	}
1483165220Srrs	tmr->stopped_from = 0xa005;
1484169420Srrs	SCTPDBG(SCTP_DEBUG_TIMER1, "Timer type %d goes off\n", tmr->type);
1485165647Srrs	if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) {
1486163953Srrs		if (inp) {
1487163953Srrs			SCTP_INP_DECR_REF(inp);
1488163953Srrs		}
1489170091Srrs		if (stcb) {
1490170091Srrs			atomic_add_int(&stcb->asoc.refcnt, -1);
1491170091Srrs		}
1492197326Stuexen		CURVNET_RESTORE();
1493163953Srrs		return;
1494163953Srrs	}
1495165220Srrs	tmr->stopped_from = 0xa006;
1496165220Srrs
1497163953Srrs	if (stcb) {
1498163953Srrs		SCTP_TCB_LOCK(stcb);
1499163996Srrs		atomic_add_int(&stcb->asoc.refcnt, -1);
1500171440Srrs		if ((tmr->type != SCTP_TIMER_TYPE_ASOCKILL) &&
1501171440Srrs		    ((stcb->asoc.state == 0) ||
1502171440Srrs		    (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED))) {
1503171440Srrs			SCTP_TCB_UNLOCK(stcb);
1504171440Srrs			if (inp) {
1505171440Srrs				SCTP_INP_DECR_REF(inp);
1506171440Srrs			}
1507197326Stuexen			CURVNET_RESTORE();
1508171440Srrs			return;
1509171440Srrs		}
1510163953Srrs	}
1511166023Srrs	/* record in stopped what t-o occured */
1512166023Srrs	tmr->stopped_from = tmr->type;
1513166023Srrs
1514163953Srrs	/* mark as being serviced now */
1515166023Srrs	if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
1516166023Srrs		/*
1517166023Srrs		 * Callout has been rescheduled.
1518166023Srrs		 */
1519166023Srrs		goto get_out;
1520166023Srrs	}
1521166023Srrs	if (!SCTP_OS_TIMER_ACTIVE(&tmr->timer)) {
1522166023Srrs		/*
1523166023Srrs		 * Not active, so no action.
1524166023Srrs		 */
1525166023Srrs		goto get_out;
1526166023Srrs	}
1527165647Srrs	SCTP_OS_TIMER_DEACTIVATE(&tmr->timer);
1528163953Srrs
1529163953Srrs	/* call the handler for the appropriate timer type */
1530163953Srrs	switch (tmr->type) {
1531170056Srrs	case SCTP_TIMER_TYPE_ZERO_COPY:
1532170931Srrs		if (inp == NULL) {
1533170931Srrs			break;
1534170931Srrs		}
1535170056Srrs		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
1536170056Srrs			SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
1537170056Srrs		}
1538170056Srrs		break;
1539170181Srrs	case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
1540170931Srrs		if (inp == NULL) {
1541170931Srrs			break;
1542170931Srrs		}
1543170181Srrs		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
1544170181Srrs			SCTP_ZERO_COPY_SENDQ_EVENT(inp, inp->sctp_socket);
1545170181Srrs		}
1546170181Srrs		break;
1547163953Srrs	case SCTP_TIMER_TYPE_ADDR_WQ:
1548163953Srrs		sctp_handle_addr_wq();
1549163953Srrs		break;
1550163953Srrs	case SCTP_TIMER_TYPE_SEND:
1551169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1552169420Srrs			break;
1553169420Srrs		}
1554163953Srrs		SCTP_STAT_INCR(sctps_timodata);
1555166675Srrs		stcb->asoc.timodata++;
1556163953Srrs		stcb->asoc.num_send_timers_up--;
1557163953Srrs		if (stcb->asoc.num_send_timers_up < 0) {
1558163953Srrs			stcb->asoc.num_send_timers_up = 0;
1559163953Srrs		}
1560171440Srrs		SCTP_TCB_LOCK_ASSERT(stcb);
1561231039Stuexen		if (sctp_t3rxt_timer(inp, stcb, net)) {
1562163953Srrs			/* no need to unlock on tcb its gone */
1563163953Srrs
1564163953Srrs			goto out_decr;
1565163953Srrs		}
1566171440Srrs		SCTP_TCB_LOCK_ASSERT(stcb);
1567163953Srrs#ifdef SCTP_AUDITING_ENABLED
1568163953Srrs		sctp_auditing(4, inp, stcb, net);
1569163953Srrs#endif
1570172090Srrs		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
1571163953Srrs		if ((stcb->asoc.num_send_timers_up == 0) &&
1572216822Stuexen		    (stcb->asoc.sent_queue_cnt > 0)) {
1573163953Srrs			struct sctp_tmit_chunk *chk;
1574163953Srrs
1575163953Srrs			/*
1576163953Srrs			 * safeguard. If there on some on the sent queue
1577163953Srrs			 * somewhere but no timers running something is
1578163953Srrs			 * wrong... so we start a timer on the first chunk
1579163953Srrs			 * on the send queue on whatever net it is sent to.
1580163953Srrs			 */
1581163953Srrs			chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
1582163953Srrs			sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb,
1583163953Srrs			    chk->whoTo);
1584163953Srrs		}
1585163953Srrs		break;
1586163953Srrs	case SCTP_TIMER_TYPE_INIT:
1587169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1588169420Srrs			break;
1589169420Srrs		}
1590163953Srrs		SCTP_STAT_INCR(sctps_timoinit);
1591166675Srrs		stcb->asoc.timoinit++;
1592163953Srrs		if (sctp_t1init_timer(inp, stcb, net)) {
1593163953Srrs			/* no need to unlock on tcb its gone */
1594163953Srrs			goto out_decr;
1595163953Srrs		}
1596163953Srrs		/* We do output but not here */
1597163953Srrs		did_output = 0;
1598163953Srrs		break;
1599163953Srrs	case SCTP_TIMER_TYPE_RECV:
1600169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1601169420Srrs			break;
1602169420Srrs		}
1603224641Stuexen		SCTP_STAT_INCR(sctps_timosack);
1604224641Stuexen		stcb->asoc.timosack++;
1605224641Stuexen		sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
1606163953Srrs#ifdef SCTP_AUDITING_ENABLED
1607163953Srrs		sctp_auditing(4, inp, stcb, net);
1608163953Srrs#endif
1609172090Srrs		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SACK_TMR, SCTP_SO_NOT_LOCKED);
1610163953Srrs		break;
1611163953Srrs	case SCTP_TIMER_TYPE_SHUTDOWN:
1612169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1613169420Srrs			break;
1614169420Srrs		}
1615163953Srrs		if (sctp_shutdown_timer(inp, stcb, net)) {
1616163953Srrs			/* no need to unlock on tcb its gone */
1617163953Srrs			goto out_decr;
1618163953Srrs		}
1619163953Srrs		SCTP_STAT_INCR(sctps_timoshutdown);
1620166675Srrs		stcb->asoc.timoshutdown++;
1621163953Srrs#ifdef SCTP_AUDITING_ENABLED
1622163953Srrs		sctp_auditing(4, inp, stcb, net);
1623163953Srrs#endif
1624172090Srrs		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_TMR, SCTP_SO_NOT_LOCKED);
1625163953Srrs		break;
1626163953Srrs	case SCTP_TIMER_TYPE_HEARTBEAT:
1627224641Stuexen		if ((stcb == NULL) || (inp == NULL) || (net == NULL)) {
1628224641Stuexen			break;
1629224641Stuexen		}
1630224641Stuexen		SCTP_STAT_INCR(sctps_timoheartbeat);
1631224641Stuexen		stcb->asoc.timoheartbeat++;
1632224641Stuexen		if (sctp_heartbeat_timer(inp, stcb, net)) {
1633224641Stuexen			/* no need to unlock on tcb its gone */
1634224641Stuexen			goto out_decr;
1635224641Stuexen		}
1636163953Srrs#ifdef SCTP_AUDITING_ENABLED
1637224641Stuexen		sctp_auditing(4, inp, stcb, net);
1638163953Srrs#endif
1639224641Stuexen		if (!(net->dest_state & SCTP_ADDR_NOHB)) {
1640226267Stuexen			sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
1641172090Srrs			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_HB_TMR, SCTP_SO_NOT_LOCKED);
1642163953Srrs		}
1643163953Srrs		break;
1644163953Srrs	case SCTP_TIMER_TYPE_COOKIE:
1645169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1646169420Srrs			break;
1647169420Srrs		}
1648163953Srrs		if (sctp_cookie_timer(inp, stcb, net)) {
1649163953Srrs			/* no need to unlock on tcb its gone */
1650163953Srrs			goto out_decr;
1651163953Srrs		}
1652163953Srrs		SCTP_STAT_INCR(sctps_timocookie);
1653166675Srrs		stcb->asoc.timocookie++;
1654163953Srrs#ifdef SCTP_AUDITING_ENABLED
1655163953Srrs		sctp_auditing(4, inp, stcb, net);
1656163953Srrs#endif
1657163953Srrs		/*
1658163953Srrs		 * We consider T3 and Cookie timer pretty much the same with
1659163953Srrs		 * respect to where from in chunk_output.
1660163953Srrs		 */
1661172090Srrs		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
1662163953Srrs		break;
1663163953Srrs	case SCTP_TIMER_TYPE_NEWCOOKIE:
1664163953Srrs		{
1665163953Srrs			struct timeval tv;
1666163953Srrs			int i, secret;
1667163953Srrs
1668169420Srrs			if (inp == NULL) {
1669169420Srrs				break;
1670169420Srrs			}
1671163953Srrs			SCTP_STAT_INCR(sctps_timosecret);
1672169378Srrs			(void)SCTP_GETTIME_TIMEVAL(&tv);
1673163953Srrs			SCTP_INP_WLOCK(inp);
1674163953Srrs			inp->sctp_ep.time_of_secret_change = tv.tv_sec;
1675163953Srrs			inp->sctp_ep.last_secret_number =
1676163953Srrs			    inp->sctp_ep.current_secret_number;
1677163953Srrs			inp->sctp_ep.current_secret_number++;
1678163953Srrs			if (inp->sctp_ep.current_secret_number >=
1679163953Srrs			    SCTP_HOW_MANY_SECRETS) {
1680163953Srrs				inp->sctp_ep.current_secret_number = 0;
1681163953Srrs			}
1682163953Srrs			secret = (int)inp->sctp_ep.current_secret_number;
1683163953Srrs			for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) {
1684163953Srrs				inp->sctp_ep.secret_key[secret][i] =
1685163953Srrs				    sctp_select_initial_TSN(&inp->sctp_ep);
1686163953Srrs			}
1687163953Srrs			SCTP_INP_WUNLOCK(inp);
1688163953Srrs			sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net);
1689163953Srrs		}
1690163953Srrs		did_output = 0;
1691163953Srrs		break;
1692163953Srrs	case SCTP_TIMER_TYPE_PATHMTURAISE:
1693169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1694169420Srrs			break;
1695169420Srrs		}
1696163953Srrs		SCTP_STAT_INCR(sctps_timopathmtu);
1697163953Srrs		sctp_pathmtu_timer(inp, stcb, net);
1698163953Srrs		did_output = 0;
1699163953Srrs		break;
1700163953Srrs	case SCTP_TIMER_TYPE_SHUTDOWNACK:
1701169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1702169420Srrs			break;
1703169420Srrs		}
1704163953Srrs		if (sctp_shutdownack_timer(inp, stcb, net)) {
1705163953Srrs			/* no need to unlock on tcb its gone */
1706163953Srrs			goto out_decr;
1707163953Srrs		}
1708163953Srrs		SCTP_STAT_INCR(sctps_timoshutdownack);
1709166675Srrs		stcb->asoc.timoshutdownack++;
1710163953Srrs#ifdef SCTP_AUDITING_ENABLED
1711163953Srrs		sctp_auditing(4, inp, stcb, net);
1712163953Srrs#endif
1713172090Srrs		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SHUT_ACK_TMR, SCTP_SO_NOT_LOCKED);
1714163953Srrs		break;
1715163953Srrs	case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
1716169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1717169420Srrs			break;
1718169420Srrs		}
1719163953Srrs		SCTP_STAT_INCR(sctps_timoshutdownguard);
1720237884Stuexen		sctp_abort_an_association(inp, stcb, NULL, SCTP_SO_NOT_LOCKED);
1721163953Srrs		/* no need to unlock on tcb its gone */
1722163953Srrs		goto out_decr;
1723163953Srrs
1724163953Srrs	case SCTP_TIMER_TYPE_STRRESET:
1725169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1726169420Srrs			break;
1727169420Srrs		}
1728163953Srrs		if (sctp_strreset_timer(inp, stcb, net)) {
1729163953Srrs			/* no need to unlock on tcb its gone */
1730163953Srrs			goto out_decr;
1731163953Srrs		}
1732163953Srrs		SCTP_STAT_INCR(sctps_timostrmrst);
1733172090Srrs		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_TMR, SCTP_SO_NOT_LOCKED);
1734163953Srrs		break;
1735163953Srrs	case SCTP_TIMER_TYPE_ASCONF:
1736169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1737169420Srrs			break;
1738169420Srrs		}
1739163953Srrs		if (sctp_asconf_timer(inp, stcb, net)) {
1740163953Srrs			/* no need to unlock on tcb its gone */
1741163953Srrs			goto out_decr;
1742163953Srrs		}
1743163953Srrs		SCTP_STAT_INCR(sctps_timoasconf);
1744163953Srrs#ifdef SCTP_AUDITING_ENABLED
1745163953Srrs		sctp_auditing(4, inp, stcb, net);
1746163953Srrs#endif
1747172090Srrs		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_ASCONF_TMR, SCTP_SO_NOT_LOCKED);
1748163953Srrs		break;
1749172091Srrs	case SCTP_TIMER_TYPE_PRIM_DELETED:
1750172091Srrs		if ((stcb == NULL) || (inp == NULL)) {
1751172091Srrs			break;
1752172091Srrs		}
1753172156Srrs		sctp_delete_prim_timer(inp, stcb, net);
1754172091Srrs		SCTP_STAT_INCR(sctps_timodelprim);
1755172091Srrs		break;
1756163953Srrs
1757163953Srrs	case SCTP_TIMER_TYPE_AUTOCLOSE:
1758169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1759169420Srrs			break;
1760169420Srrs		}
1761163953Srrs		SCTP_STAT_INCR(sctps_timoautoclose);
1762163953Srrs		sctp_autoclose_timer(inp, stcb, net);
1763172090Srrs		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_AUTOCLOSE_TMR, SCTP_SO_NOT_LOCKED);
1764163953Srrs		did_output = 0;
1765163953Srrs		break;
1766163953Srrs	case SCTP_TIMER_TYPE_ASOCKILL:
1767169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
1768169420Srrs			break;
1769169420Srrs		}
1770163953Srrs		SCTP_STAT_INCR(sctps_timoassockill);
1771163953Srrs		/* Can we free it yet? */
1772163953Srrs		SCTP_INP_DECR_REF(inp);
1773165220Srrs		sctp_timer_stop(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_1);
1774252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1775172090Srrs		so = SCTP_INP_SO(inp);
1776172090Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
1777172090Srrs		SCTP_TCB_UNLOCK(stcb);
1778172090Srrs		SCTP_SOCKET_LOCK(so, 1);
1779172090Srrs		SCTP_TCB_LOCK(stcb);
1780172090Srrs		atomic_subtract_int(&stcb->asoc.refcnt, 1);
1781172090Srrs#endif
1782171943Srrs		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_2);
1783252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1784172090Srrs		SCTP_SOCKET_UNLOCK(so, 1);
1785172090Srrs#endif
1786163953Srrs		/*
1787163953Srrs		 * free asoc, always unlocks (or destroy's) so prevent
1788163953Srrs		 * duplicate unlock or unlock of a free mtx :-0
1789163953Srrs		 */
1790163953Srrs		stcb = NULL;
1791163953Srrs		goto out_no_decr;
1792163953Srrs	case SCTP_TIMER_TYPE_INPKILL:
1793163953Srrs		SCTP_STAT_INCR(sctps_timoinpkill);
1794169420Srrs		if (inp == NULL) {
1795169420Srrs			break;
1796169420Srrs		}
1797163953Srrs		/*
1798163953Srrs		 * special case, take away our increment since WE are the
1799163953Srrs		 * killer
1800163953Srrs		 */
1801163953Srrs		SCTP_INP_DECR_REF(inp);
1802165220Srrs		sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_3);
1803169380Srrs		sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
1804208878Srrs		    SCTP_CALLED_FROM_INPKILL_TIMER);
1805179180Srrs		inp = NULL;
1806163953Srrs		goto out_no_decr;
1807163953Srrs	default:
1808169420Srrs		SCTPDBG(SCTP_DEBUG_TIMER1, "sctp_timeout_handler:unknown timer %d\n",
1809169420Srrs		    tmr->type);
1810163953Srrs		break;
1811231039Stuexen	}
1812163953Srrs#ifdef SCTP_AUDITING_ENABLED
1813163953Srrs	sctp_audit_log(0xF1, (uint8_t) tmr->type);
1814163953Srrs	if (inp)
1815163953Srrs		sctp_auditing(5, inp, stcb, net);
1816163953Srrs#endif
1817163953Srrs	if ((did_output) && stcb) {
1818163953Srrs		/*
1819163953Srrs		 * Now we need to clean up the control chunk chain if an
1820163953Srrs		 * ECNE is on it. It must be marked as UNSENT again so next
1821163953Srrs		 * call will continue to send it until such time that we get
1822163953Srrs		 * a CWR, to remove it. It is, however, less likely that we
1823163953Srrs		 * will find a ecn echo on the chain though.
1824163953Srrs		 */
1825163953Srrs		sctp_fix_ecn_echo(&stcb->asoc);
1826163953Srrs	}
1827166023Srrsget_out:
1828163953Srrs	if (stcb) {
1829163953Srrs		SCTP_TCB_UNLOCK(stcb);
1830163953Srrs	}
1831163953Srrsout_decr:
1832163953Srrs	if (inp) {
1833163953Srrs		SCTP_INP_DECR_REF(inp);
1834163953Srrs	}
1835163953Srrsout_no_decr:
1836169420Srrs	SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type %d)\n",
1837179180Srrs	    type);
1838197326Stuexen	CURVNET_RESTORE();
1839163953Srrs}
1840163953Srrs
1841169420Srrsvoid
1842163953Srrssctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1843163953Srrs    struct sctp_nets *net)
1844163953Srrs{
1845224641Stuexen	uint32_t to_ticks;
1846163953Srrs	struct sctp_timer *tmr;
1847163953Srrs
1848165647Srrs	if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) && (inp == NULL))
1849169420Srrs		return;
1850163953Srrs
1851163953Srrs	tmr = NULL;
1852163953Srrs	if (stcb) {
1853163953Srrs		SCTP_TCB_LOCK_ASSERT(stcb);
1854163953Srrs	}
1855163953Srrs	switch (t_type) {
1856170056Srrs	case SCTP_TIMER_TYPE_ZERO_COPY:
1857170056Srrs		tmr = &inp->sctp_ep.zero_copy_timer;
1858170056Srrs		to_ticks = SCTP_ZERO_COPY_TICK_DELAY;
1859170056Srrs		break;
1860170181Srrs	case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
1861170181Srrs		tmr = &inp->sctp_ep.zero_copy_sendq_timer;
1862170181Srrs		to_ticks = SCTP_ZERO_COPY_SENDQ_TICK_DELAY;
1863170181Srrs		break;
1864163953Srrs	case SCTP_TIMER_TYPE_ADDR_WQ:
1865163953Srrs		/* Only 1 tick away :-) */
1866179783Srrs		tmr = &SCTP_BASE_INFO(addr_wq_timer);
1867167598Srrs		to_ticks = SCTP_ADDRESS_TICK_DELAY;
1868163953Srrs		break;
1869163953Srrs	case SCTP_TIMER_TYPE_SEND:
1870163953Srrs		/* Here we use the RTO timer */
1871163953Srrs		{
1872163953Srrs			int rto_val;
1873163953Srrs
1874163953Srrs			if ((stcb == NULL) || (net == NULL)) {
1875169420Srrs				return;
1876163953Srrs			}
1877163953Srrs			tmr = &net->rxt_timer;
1878163953Srrs			if (net->RTO == 0) {
1879163953Srrs				rto_val = stcb->asoc.initial_rto;
1880163953Srrs			} else {
1881163953Srrs				rto_val = net->RTO;
1882163953Srrs			}
1883163953Srrs			to_ticks = MSEC_TO_TICKS(rto_val);
1884163953Srrs		}
1885163953Srrs		break;
1886163953Srrs	case SCTP_TIMER_TYPE_INIT:
1887163953Srrs		/*
1888163953Srrs		 * Here we use the INIT timer default usually about 1
1889163953Srrs		 * minute.
1890163953Srrs		 */
1891163953Srrs		if ((stcb == NULL) || (net == NULL)) {
1892169420Srrs			return;
1893163953Srrs		}
1894163953Srrs		tmr = &net->rxt_timer;
1895163953Srrs		if (net->RTO == 0) {
1896163953Srrs			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1897163953Srrs		} else {
1898163953Srrs			to_ticks = MSEC_TO_TICKS(net->RTO);
1899163953Srrs		}
1900163953Srrs		break;
1901163953Srrs	case SCTP_TIMER_TYPE_RECV:
1902163953Srrs		/*
1903163953Srrs		 * Here we use the Delayed-Ack timer value from the inp
1904163953Srrs		 * ususually about 200ms.
1905163953Srrs		 */
1906163953Srrs		if (stcb == NULL) {
1907169420Srrs			return;
1908163953Srrs		}
1909163953Srrs		tmr = &stcb->asoc.dack_timer;
1910163953Srrs		to_ticks = MSEC_TO_TICKS(stcb->asoc.delayed_ack);
1911163953Srrs		break;
1912163953Srrs	case SCTP_TIMER_TYPE_SHUTDOWN:
1913163953Srrs		/* Here we use the RTO of the destination. */
1914163953Srrs		if ((stcb == NULL) || (net == NULL)) {
1915169420Srrs			return;
1916163953Srrs		}
1917163953Srrs		if (net->RTO == 0) {
1918163953Srrs			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1919163953Srrs		} else {
1920163953Srrs			to_ticks = MSEC_TO_TICKS(net->RTO);
1921163953Srrs		}
1922163953Srrs		tmr = &net->rxt_timer;
1923163953Srrs		break;
1924163953Srrs	case SCTP_TIMER_TYPE_HEARTBEAT:
1925163953Srrs		/*
1926163953Srrs		 * the net is used here so that we can add in the RTO. Even
1927163953Srrs		 * though we use a different timer. We also add the HB timer
1928163953Srrs		 * PLUS a random jitter.
1929163953Srrs		 */
1930224641Stuexen		if ((inp == NULL) || (stcb == NULL) || (net == NULL)) {
1931169420Srrs			return;
1932169420Srrs		} else {
1933163953Srrs			uint32_t rndval;
1934224641Stuexen			uint32_t jitter;
1935163953Srrs
1936224641Stuexen			if ((net->dest_state & SCTP_ADDR_NOHB) &&
1937224641Stuexen			    !(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
1938224641Stuexen				return;
1939163953Srrs			}
1940224641Stuexen			if (net->RTO == 0) {
1941224641Stuexen				to_ticks = stcb->asoc.initial_rto;
1942224641Stuexen			} else {
1943224641Stuexen				to_ticks = net->RTO;
1944163953Srrs			}
1945224641Stuexen			rndval = sctp_select_initial_TSN(&inp->sctp_ep);
1946224641Stuexen			jitter = rndval % to_ticks;
1947224641Stuexen			if (jitter >= (to_ticks >> 1)) {
1948224641Stuexen				to_ticks = to_ticks + (jitter - (to_ticks >> 1));
1949224641Stuexen			} else {
1950224641Stuexen				to_ticks = to_ticks - jitter;
1951163953Srrs			}
1952224641Stuexen			if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
1953224641Stuexen			    !(net->dest_state & SCTP_ADDR_PF)) {
1954224641Stuexen				to_ticks += net->heart_beat_delay;
1955163953Srrs			}
1956163953Srrs			/*
1957163953Srrs			 * Now we must convert the to_ticks that are now in
1958163953Srrs			 * ms to ticks.
1959163953Srrs			 */
1960163953Srrs			to_ticks = MSEC_TO_TICKS(to_ticks);
1961224641Stuexen			tmr = &net->hb_timer;
1962163953Srrs		}
1963163953Srrs		break;
1964163953Srrs	case SCTP_TIMER_TYPE_COOKIE:
1965163953Srrs		/*
1966163953Srrs		 * Here we can use the RTO timer from the network since one
1967163953Srrs		 * RTT was compelete. If a retran happened then we will be
1968163953Srrs		 * using the RTO initial value.
1969163953Srrs		 */
1970163953Srrs		if ((stcb == NULL) || (net == NULL)) {
1971169420Srrs			return;
1972163953Srrs		}
1973163953Srrs		if (net->RTO == 0) {
1974163953Srrs			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
1975163953Srrs		} else {
1976163953Srrs			to_ticks = MSEC_TO_TICKS(net->RTO);
1977163953Srrs		}
1978163953Srrs		tmr = &net->rxt_timer;
1979163953Srrs		break;
1980163953Srrs	case SCTP_TIMER_TYPE_NEWCOOKIE:
1981163953Srrs		/*
1982163953Srrs		 * nothing needed but the endpoint here ususually about 60
1983163953Srrs		 * minutes.
1984163953Srrs		 */
1985169420Srrs		if (inp == NULL) {
1986169420Srrs			return;
1987169420Srrs		}
1988163953Srrs		tmr = &inp->sctp_ep.signature_change;
1989163953Srrs		to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE];
1990163953Srrs		break;
1991163953Srrs	case SCTP_TIMER_TYPE_ASOCKILL:
1992163953Srrs		if (stcb == NULL) {
1993169420Srrs			return;
1994163953Srrs		}
1995163953Srrs		tmr = &stcb->asoc.strreset_timer;
1996163953Srrs		to_ticks = MSEC_TO_TICKS(SCTP_ASOC_KILL_TIMEOUT);
1997163953Srrs		break;
1998163953Srrs	case SCTP_TIMER_TYPE_INPKILL:
1999163953Srrs		/*
2000163953Srrs		 * The inp is setup to die. We re-use the signature_chage
2001163953Srrs		 * timer since that has stopped and we are in the GONE
2002163953Srrs		 * state.
2003163953Srrs		 */
2004169420Srrs		if (inp == NULL) {
2005169420Srrs			return;
2006169420Srrs		}
2007163953Srrs		tmr = &inp->sctp_ep.signature_change;
2008163953Srrs		to_ticks = MSEC_TO_TICKS(SCTP_INP_KILL_TIMEOUT);
2009163953Srrs		break;
2010163953Srrs	case SCTP_TIMER_TYPE_PATHMTURAISE:
2011163953Srrs		/*
2012163953Srrs		 * Here we use the value found in the EP for PMTU ususually
2013163953Srrs		 * about 10 minutes.
2014163953Srrs		 */
2015169420Srrs		if ((stcb == NULL) || (inp == NULL)) {
2016169420Srrs			return;
2017163953Srrs		}
2018163953Srrs		if (net == NULL) {
2019169420Srrs			return;
2020163953Srrs		}
2021225635Stuexen		if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
2022225635Stuexen			return;
2023225635Stuexen		}
2024163953Srrs		to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU];
2025163953Srrs		tmr = &net->pmtu_timer;
2026163953Srrs		break;
2027163953Srrs	case SCTP_TIMER_TYPE_SHUTDOWNACK:
2028163953Srrs		/* Here we use the RTO of the destination */
2029163953Srrs		if ((stcb == NULL) || (net == NULL)) {
2030169420Srrs			return;
2031163953Srrs		}
2032163953Srrs		if (net->RTO == 0) {
2033163953Srrs			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
2034163953Srrs		} else {
2035163953Srrs			to_ticks = MSEC_TO_TICKS(net->RTO);
2036163953Srrs		}
2037163953Srrs		tmr = &net->rxt_timer;
2038163953Srrs		break;
2039163953Srrs	case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
2040163953Srrs		/*
2041163953Srrs		 * Here we use the endpoints shutdown guard timer usually
2042163953Srrs		 * about 3 minutes.
2043163953Srrs		 */
2044169420Srrs		if ((inp == NULL) || (stcb == NULL)) {
2045169420Srrs			return;
2046163953Srrs		}
2047163953Srrs		to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN];
2048163953Srrs		tmr = &stcb->asoc.shut_guard_timer;
2049163953Srrs		break;
2050163953Srrs	case SCTP_TIMER_TYPE_STRRESET:
2051163953Srrs		/*
2052171572Srrs		 * Here the timer comes from the stcb but its value is from
2053171572Srrs		 * the net's RTO.
2054163953Srrs		 */
2055163953Srrs		if ((stcb == NULL) || (net == NULL)) {
2056169420Srrs			return;
2057163953Srrs		}
2058163953Srrs		if (net->RTO == 0) {
2059163953Srrs			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
2060163953Srrs		} else {
2061163953Srrs			to_ticks = MSEC_TO_TICKS(net->RTO);
2062163953Srrs		}
2063163953Srrs		tmr = &stcb->asoc.strreset_timer;
2064163953Srrs		break;
2065163953Srrs	case SCTP_TIMER_TYPE_ASCONF:
2066163953Srrs		/*
2067171572Srrs		 * Here the timer comes from the stcb but its value is from
2068171572Srrs		 * the net's RTO.
2069163953Srrs		 */
2070163953Srrs		if ((stcb == NULL) || (net == NULL)) {
2071169420Srrs			return;
2072163953Srrs		}
2073163953Srrs		if (net->RTO == 0) {
2074163953Srrs			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
2075163953Srrs		} else {
2076163953Srrs			to_ticks = MSEC_TO_TICKS(net->RTO);
2077163953Srrs		}
2078163953Srrs		tmr = &stcb->asoc.asconf_timer;
2079163953Srrs		break;
2080172091Srrs	case SCTP_TIMER_TYPE_PRIM_DELETED:
2081172091Srrs		if ((stcb == NULL) || (net != NULL)) {
2082172091Srrs			return;
2083172091Srrs		}
2084172091Srrs		to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
2085172091Srrs		tmr = &stcb->asoc.delete_prim_timer;
2086172091Srrs		break;
2087163953Srrs	case SCTP_TIMER_TYPE_AUTOCLOSE:
2088163953Srrs		if (stcb == NULL) {
2089169420Srrs			return;
2090163953Srrs		}
2091163953Srrs		if (stcb->asoc.sctp_autoclose_ticks == 0) {
2092163953Srrs			/*
2093163953Srrs			 * Really an error since stcb is NOT set to
2094163953Srrs			 * autoclose
2095163953Srrs			 */
2096169420Srrs			return;
2097163953Srrs		}
2098163953Srrs		to_ticks = stcb->asoc.sctp_autoclose_ticks;
2099163953Srrs		tmr = &stcb->asoc.autoclose_timer;
2100163953Srrs		break;
2101163953Srrs	default:
2102169420Srrs		SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n",
2103169420Srrs		    __FUNCTION__, t_type);
2104169420Srrs		return;
2105163953Srrs		break;
2106231039Stuexen	}
2107163953Srrs	if ((to_ticks <= 0) || (tmr == NULL)) {
2108169420Srrs		SCTPDBG(SCTP_DEBUG_TIMER1, "%s: %d:software error to_ticks:%d tmr:%p not set ??\n",
2109252927Stuexen		    __FUNCTION__, t_type, to_ticks, (void *)tmr);
2110169420Srrs		return;
2111163953Srrs	}
2112165647Srrs	if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
2113163953Srrs		/*
2114163953Srrs		 * we do NOT allow you to have it already running. if it is
2115163953Srrs		 * we leave the current one up unchanged
2116163953Srrs		 */
2117169420Srrs		return;
2118163953Srrs	}
2119163953Srrs	/* At this point we can proceed */
2120163953Srrs	if (t_type == SCTP_TIMER_TYPE_SEND) {
2121163953Srrs		stcb->asoc.num_send_timers_up++;
2122163953Srrs	}
2123165220Srrs	tmr->stopped_from = 0;
2124163953Srrs	tmr->type = t_type;
2125163953Srrs	tmr->ep = (void *)inp;
2126163953Srrs	tmr->tcb = (void *)stcb;
2127163953Srrs	tmr->net = (void *)net;
2128163953Srrs	tmr->self = (void *)tmr;
2129197326Stuexen	tmr->vnet = (void *)curvnet;
2130171943Srrs	tmr->ticks = sctp_get_tick_count();
2131169420Srrs	(void)SCTP_OS_TIMER_START(&tmr->timer, to_ticks, sctp_timeout_handler, tmr);
2132169420Srrs	return;
2133163953Srrs}
2134163953Srrs
2135169378Srrsvoid
2136163953Srrssctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
2137165220Srrs    struct sctp_nets *net, uint32_t from)
2138163953Srrs{
2139163953Srrs	struct sctp_timer *tmr;
2140163953Srrs
2141163953Srrs	if ((t_type != SCTP_TIMER_TYPE_ADDR_WQ) &&
2142163953Srrs	    (inp == NULL))
2143169378Srrs		return;
2144163953Srrs
2145163953Srrs	tmr = NULL;
2146163953Srrs	if (stcb) {
2147163953Srrs		SCTP_TCB_LOCK_ASSERT(stcb);
2148163953Srrs	}
2149163953Srrs	switch (t_type) {
2150170056Srrs	case SCTP_TIMER_TYPE_ZERO_COPY:
2151170056Srrs		tmr = &inp->sctp_ep.zero_copy_timer;
2152170056Srrs		break;
2153170181Srrs	case SCTP_TIMER_TYPE_ZCOPY_SENDQ:
2154170181Srrs		tmr = &inp->sctp_ep.zero_copy_sendq_timer;
2155170181Srrs		break;
2156163953Srrs	case SCTP_TIMER_TYPE_ADDR_WQ:
2157179783Srrs		tmr = &SCTP_BASE_INFO(addr_wq_timer);
2158163953Srrs		break;
2159163953Srrs	case SCTP_TIMER_TYPE_SEND:
2160163953Srrs		if ((stcb == NULL) || (net == NULL)) {
2161169378Srrs			return;
2162163953Srrs		}
2163163953Srrs		tmr = &net->rxt_timer;
2164163953Srrs		break;
2165163953Srrs	case SCTP_TIMER_TYPE_INIT:
2166163953Srrs		if ((stcb == NULL) || (net == NULL)) {
2167169378Srrs			return;
2168163953Srrs		}
2169163953Srrs		tmr = &net->rxt_timer;
2170163953Srrs		break;
2171163953Srrs	case SCTP_TIMER_TYPE_RECV:
2172163953Srrs		if (stcb == NULL) {
2173169378Srrs			return;
2174163953Srrs		}
2175163953Srrs		tmr = &stcb->asoc.dack_timer;
2176163953Srrs		break;
2177163953Srrs	case SCTP_TIMER_TYPE_SHUTDOWN:
2178163953Srrs		if ((stcb == NULL) || (net == NULL)) {
2179169378Srrs			return;
2180163953Srrs		}
2181163953Srrs		tmr = &net->rxt_timer;
2182163953Srrs		break;
2183163953Srrs	case SCTP_TIMER_TYPE_HEARTBEAT:
2184224641Stuexen		if ((stcb == NULL) || (net == NULL)) {
2185169378Srrs			return;
2186163953Srrs		}
2187224641Stuexen		tmr = &net->hb_timer;
2188163953Srrs		break;
2189163953Srrs	case SCTP_TIMER_TYPE_COOKIE:
2190163953Srrs		if ((stcb == NULL) || (net == NULL)) {
2191169378Srrs			return;
2192163953Srrs		}
2193163953Srrs		tmr = &net->rxt_timer;
2194163953Srrs		break;
2195163953Srrs	case SCTP_TIMER_TYPE_NEWCOOKIE:
2196163953Srrs		/* nothing needed but the endpoint here */
2197163953Srrs		tmr = &inp->sctp_ep.signature_change;
2198163953Srrs		/*
2199163953Srrs		 * We re-use the newcookie timer for the INP kill timer. We
2200163953Srrs		 * must assure that we do not kill it by accident.
2201163953Srrs		 */
2202163953Srrs		break;
2203163953Srrs	case SCTP_TIMER_TYPE_ASOCKILL:
2204163953Srrs		/*
2205163953Srrs		 * Stop the asoc kill timer.
2206163953Srrs		 */
2207163953Srrs		if (stcb == NULL) {
2208169378Srrs			return;
2209163953Srrs		}
2210163953Srrs		tmr = &stcb->asoc.strreset_timer;
2211163953Srrs		break;
2212163953Srrs
2213163953Srrs	case SCTP_TIMER_TYPE_INPKILL:
2214163953Srrs		/*
2215163953Srrs		 * The inp is setup to die. We re-use the signature_chage
2216163953Srrs		 * timer since that has stopped and we are in the GONE
2217163953Srrs		 * state.
2218163953Srrs		 */
2219163953Srrs		tmr = &inp->sctp_ep.signature_change;
2220163953Srrs		break;
2221163953Srrs	case SCTP_TIMER_TYPE_PATHMTURAISE:
2222163953Srrs		if ((stcb == NULL) || (net == NULL)) {
2223169378Srrs			return;
2224163953Srrs		}
2225163953Srrs		tmr = &net->pmtu_timer;
2226163953Srrs		break;
2227163953Srrs	case SCTP_TIMER_TYPE_SHUTDOWNACK:
2228163953Srrs		if ((stcb == NULL) || (net == NULL)) {
2229169378Srrs			return;
2230163953Srrs		}
2231163953Srrs		tmr = &net->rxt_timer;
2232163953Srrs		break;
2233163953Srrs	case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
2234163953Srrs		if (stcb == NULL) {
2235169378Srrs			return;
2236163953Srrs		}
2237163953Srrs		tmr = &stcb->asoc.shut_guard_timer;
2238163953Srrs		break;
2239163953Srrs	case SCTP_TIMER_TYPE_STRRESET:
2240163953Srrs		if (stcb == NULL) {
2241169378Srrs			return;
2242163953Srrs		}
2243163953Srrs		tmr = &stcb->asoc.strreset_timer;
2244163953Srrs		break;
2245163953Srrs	case SCTP_TIMER_TYPE_ASCONF:
2246163953Srrs		if (stcb == NULL) {
2247169378Srrs			return;
2248163953Srrs		}
2249163953Srrs		tmr = &stcb->asoc.asconf_timer;
2250163953Srrs		break;
2251172091Srrs	case SCTP_TIMER_TYPE_PRIM_DELETED:
2252172091Srrs		if (stcb == NULL) {
2253172091Srrs			return;
2254172091Srrs		}
2255172091Srrs		tmr = &stcb->asoc.delete_prim_timer;
2256172091Srrs		break;
2257163953Srrs	case SCTP_TIMER_TYPE_AUTOCLOSE:
2258163953Srrs		if (stcb == NULL) {
2259169378Srrs			return;
2260163953Srrs		}
2261163953Srrs		tmr = &stcb->asoc.autoclose_timer;
2262163953Srrs		break;
2263163953Srrs	default:
2264169420Srrs		SCTPDBG(SCTP_DEBUG_TIMER1, "%s: Unknown timer type %d\n",
2265169420Srrs		    __FUNCTION__, t_type);
2266163953Srrs		break;
2267231039Stuexen	}
2268163953Srrs	if (tmr == NULL) {
2269169378Srrs		return;
2270163953Srrs	}
2271163953Srrs	if ((tmr->type != t_type) && tmr->type) {
2272163953Srrs		/*
2273163953Srrs		 * Ok we have a timer that is under joint use. Cookie timer
2274163953Srrs		 * per chance with the SEND timer. We therefore are NOT
2275163953Srrs		 * running the timer that the caller wants stopped.  So just
2276163953Srrs		 * return.
2277163953Srrs		 */
2278169378Srrs		return;
2279163953Srrs	}
2280169420Srrs	if ((t_type == SCTP_TIMER_TYPE_SEND) && (stcb != NULL)) {
2281163953Srrs		stcb->asoc.num_send_timers_up--;
2282163953Srrs		if (stcb->asoc.num_send_timers_up < 0) {
2283163953Srrs			stcb->asoc.num_send_timers_up = 0;
2284163953Srrs		}
2285163953Srrs	}
2286163953Srrs	tmr->self = NULL;
2287165220Srrs	tmr->stopped_from = from;
2288169378Srrs	(void)SCTP_OS_TIMER_STOP(&tmr->timer);
2289169378Srrs	return;
2290163953Srrs}
2291163953Srrs
2292163953Srrsuint32_t
2293163953Srrssctp_calculate_len(struct mbuf *m)
2294163953Srrs{
2295163953Srrs	uint32_t tlen = 0;
2296163953Srrs	struct mbuf *at;
2297163953Srrs
2298163953Srrs	at = m;
2299163953Srrs	while (at) {
2300165647Srrs		tlen += SCTP_BUF_LEN(at);
2301165647Srrs		at = SCTP_BUF_NEXT(at);
2302163953Srrs	}
2303163953Srrs	return (tlen);
2304163953Srrs}
2305163953Srrs
2306163953Srrsvoid
2307163953Srrssctp_mtu_size_reset(struct sctp_inpcb *inp,
2308166023Srrs    struct sctp_association *asoc, uint32_t mtu)
2309163953Srrs{
2310163953Srrs	/*
2311163953Srrs	 * Reset the P-MTU size on this association, this involves changing
2312163953Srrs	 * the asoc MTU, going through ANY chunk+overhead larger than mtu to
2313163953Srrs	 * allow the DF flag to be cleared.
2314163953Srrs	 */
2315163953Srrs	struct sctp_tmit_chunk *chk;
2316163953Srrs	unsigned int eff_mtu, ovh;
2317163953Srrs
2318163953Srrs	asoc->smallest_mtu = mtu;
2319163953Srrs	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2320163953Srrs		ovh = SCTP_MIN_OVERHEAD;
2321163953Srrs	} else {
2322163953Srrs		ovh = SCTP_MIN_V4_OVERHEAD;
2323163953Srrs	}
2324163953Srrs	eff_mtu = mtu - ovh;
2325163953Srrs	TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
2326163953Srrs		if (chk->send_size > eff_mtu) {
2327163953Srrs			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
2328163953Srrs		}
2329163953Srrs	}
2330163953Srrs	TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
2331163953Srrs		if (chk->send_size > eff_mtu) {
2332163953Srrs			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
2333163953Srrs		}
2334163953Srrs	}
2335163953Srrs}
2336163953Srrs
2337163953Srrs
2338163953Srrs/*
2339163953Srrs * given an association and starting time of the current RTT period return
2340166675Srrs * RTO in number of msecs net should point to the current network
2341163953Srrs */
2342218186Srrs
2343163953Srrsuint32_t
2344163953Srrssctp_calculate_rto(struct sctp_tcb *stcb,
2345163953Srrs    struct sctp_association *asoc,
2346163953Srrs    struct sctp_nets *net,
2347171477Srrs    struct timeval *told,
2348219397Srrs    int safe, int rtt_from_sack)
2349163953Srrs{
2350171477Srrs	/*-
2351163953Srrs	 * given an association and the starting time of the current RTT
2352166675Srrs	 * period (in value1/value2) return RTO in number of msecs.
2353163953Srrs	 */
2354219013Stuexen	int32_t rtt;		/* RTT in ms */
2355219013Stuexen	uint32_t new_rto;
2356163953Srrs	int first_measure = 0;
2357171477Srrs	struct timeval now, then, *old;
2358163953Srrs
2359171477Srrs	/* Copy it out for sparc64 */
2360171477Srrs	if (safe == sctp_align_unsafe_makecopy) {
2361171477Srrs		old = &then;
2362171477Srrs		memcpy(&then, told, sizeof(struct timeval));
2363171477Srrs	} else if (safe == sctp_align_safe_nocopy) {
2364171477Srrs		old = told;
2365171477Srrs	} else {
2366171477Srrs		/* error */
2367171477Srrs		SCTP_PRINTF("Huh, bad rto calc call\n");
2368171477Srrs		return (0);
2369171477Srrs	}
2370163953Srrs	/************************/
2371163953Srrs	/* 1. calculate new RTT */
2372163953Srrs	/************************/
2373163953Srrs	/* get the current time */
2374219057Srrs	if (stcb->asoc.use_precise_time) {
2375219057Srrs		(void)SCTP_GETPTIME_TIMEVAL(&now);
2376219057Srrs	} else {
2377219057Srrs		(void)SCTP_GETTIME_TIMEVAL(&now);
2378219057Srrs	}
2379219013Stuexen	timevalsub(&now, old);
2380219013Stuexen	/* store the current RTT in us */
2381240129Stuexen	net->rtt = (uint64_t) 1000000 *(uint64_t) now.tv_sec +
2382252925Stuexen	        (uint64_t) now.tv_usec;
2383218039Srrs
2384219013Stuexen	/* computer rtt in ms */
2385219013Stuexen	rtt = net->rtt / 1000;
2386219397Srrs	if ((asoc->cc_functions.sctp_rtt_calculated) && (rtt_from_sack == SCTP_RTT_FROM_DATA)) {
2387219397Srrs		/*
2388219397Srrs		 * Tell the CC module that a new update has just occurred
2389219397Srrs		 * from a sack
2390219397Srrs		 */
2391219397Srrs		(*asoc->cc_functions.sctp_rtt_calculated) (stcb, net, &now);
2392219397Srrs	}
2393219397Srrs	/*
2394219397Srrs	 * Do we need to determine the lan? We do this only on sacks i.e.
2395219397Srrs	 * RTT being determined from data not non-data (HB/INIT->INITACK).
2396219397Srrs	 */
2397219397Srrs	if ((rtt_from_sack == SCTP_RTT_FROM_DATA) &&
2398219013Stuexen	    (net->lan_type == SCTP_LAN_UNKNOWN)) {
2399219013Stuexen		if (net->rtt > SCTP_LOCAL_LAN_RTT) {
2400218186Srrs			net->lan_type = SCTP_LAN_INTERNET;
2401218186Srrs		} else {
2402218186Srrs			net->lan_type = SCTP_LAN_LOCAL;
2403218186Srrs		}
2404218186Srrs	}
2405163953Srrs	/***************************/
2406163953Srrs	/* 2. update RTTVAR & SRTT */
2407163953Srrs	/***************************/
2408219013Stuexen	/*-
2409219013Stuexen	 * Compute the scaled average lastsa and the
2410219013Stuexen	 * scaled variance lastsv as described in van Jacobson
2411219013Stuexen	 * Paper "Congestion Avoidance and Control", Annex A.
2412219013Stuexen	 *
2413219013Stuexen	 * (net->lastsa >> SCTP_RTT_SHIFT) is the srtt
2414219013Stuexen	 * (net->lastsa >> SCTP_RTT_VAR_SHIFT) is the rttvar
2415219013Stuexen	 */
2416170642Srrs	if (net->RTO_measured) {
2417219013Stuexen		rtt -= (net->lastsa >> SCTP_RTT_SHIFT);
2418219013Stuexen		net->lastsa += rtt;
2419219013Stuexen		if (rtt < 0) {
2420219013Stuexen			rtt = -rtt;
2421219013Stuexen		}
2422219013Stuexen		rtt -= (net->lastsv >> SCTP_RTT_VAR_SHIFT);
2423219013Stuexen		net->lastsv += rtt;
2424179783Srrs		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) {
2425170744Srrs			rto_logging(net, SCTP_LOG_RTTVAR);
2426170744Srrs		}
2427163953Srrs	} else {
2428163953Srrs		/* First RTO measurment */
2429170642Srrs		net->RTO_measured = 1;
2430163953Srrs		first_measure = 1;
2431219013Stuexen		net->lastsa = rtt << SCTP_RTT_SHIFT;
2432219013Stuexen		net->lastsv = (rtt / 2) << SCTP_RTT_VAR_SHIFT;
2433179783Srrs		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RTTVAR_LOGGING_ENABLE) {
2434170744Srrs			rto_logging(net, SCTP_LOG_INITIAL_RTT);
2435170744Srrs		}
2436163953Srrs	}
2437219013Stuexen	if (net->lastsv == 0) {
2438219013Stuexen		net->lastsv = SCTP_CLOCK_GRANULARITY;
2439219013Stuexen	}
2440170428Srrs	new_rto = (net->lastsa >> SCTP_RTT_SHIFT) + net->lastsv;
2441163953Srrs	if ((new_rto > SCTP_SAT_NETWORK_MIN) &&
2442163953Srrs	    (stcb->asoc.sat_network_lockout == 0)) {
2443163953Srrs		stcb->asoc.sat_network = 1;
2444163953Srrs	} else if ((!first_measure) && stcb->asoc.sat_network) {
2445163953Srrs		stcb->asoc.sat_network = 0;
2446163953Srrs		stcb->asoc.sat_network_lockout = 1;
2447163953Srrs	}
2448163953Srrs	/* bound it, per C6/C7 in Section 5.3.1 */
2449163953Srrs	if (new_rto < stcb->asoc.minrto) {
2450163953Srrs		new_rto = stcb->asoc.minrto;
2451163953Srrs	}
2452163953Srrs	if (new_rto > stcb->asoc.maxrto) {
2453163953Srrs		new_rto = stcb->asoc.maxrto;
2454163953Srrs	}
2455168124Srrs	/* we are now returning the RTO */
2456168124Srrs	return (new_rto);
2457163953Srrs}
2458163953Srrs
2459163953Srrs/*
2460163953Srrs * return a pointer to a contiguous piece of data from the given mbuf chain
2461163953Srrs * starting at 'off' for 'len' bytes.  If the desired piece spans more than
2462163953Srrs * one mbuf, a copy is made at 'ptr'. caller must ensure that the buffer size
2463163953Srrs * is >= 'len' returns NULL if there there isn't 'len' bytes in the chain.
2464163953Srrs */
2465170806Srrscaddr_t
2466163953Srrssctp_m_getptr(struct mbuf *m, int off, int len, uint8_t * in_ptr)
2467163953Srrs{
2468163953Srrs	uint32_t count;
2469163953Srrs	uint8_t *ptr;
2470163953Srrs
2471163953Srrs	ptr = in_ptr;
2472163953Srrs	if ((off < 0) || (len <= 0))
2473163953Srrs		return (NULL);
2474163953Srrs
2475163953Srrs	/* find the desired start location */
2476163953Srrs	while ((m != NULL) && (off > 0)) {
2477165647Srrs		if (off < SCTP_BUF_LEN(m))
2478163953Srrs			break;
2479165647Srrs		off -= SCTP_BUF_LEN(m);
2480165647Srrs		m = SCTP_BUF_NEXT(m);
2481163953Srrs	}
2482163953Srrs	if (m == NULL)
2483163953Srrs		return (NULL);
2484163953Srrs
2485163953Srrs	/* is the current mbuf large enough (eg. contiguous)? */
2486165647Srrs	if ((SCTP_BUF_LEN(m) - off) >= len) {
2487163953Srrs		return (mtod(m, caddr_t)+off);
2488163953Srrs	} else {
2489163953Srrs		/* else, it spans more than one mbuf, so save a temp copy... */
2490163953Srrs		while ((m != NULL) && (len > 0)) {
2491165647Srrs			count = min(SCTP_BUF_LEN(m) - off, len);
2492163953Srrs			bcopy(mtod(m, caddr_t)+off, ptr, count);
2493163953Srrs			len -= count;
2494163953Srrs			ptr += count;
2495163953Srrs			off = 0;
2496165647Srrs			m = SCTP_BUF_NEXT(m);
2497163953Srrs		}
2498163953Srrs		if ((m == NULL) && (len > 0))
2499163953Srrs			return (NULL);
2500163953Srrs		else
2501163953Srrs			return ((caddr_t)in_ptr);
2502163953Srrs	}
2503163953Srrs}
2504163953Srrs
2505163953Srrs
2506166023Srrs
2507163953Srrsstruct sctp_paramhdr *
2508163953Srrssctp_get_next_param(struct mbuf *m,
2509163953Srrs    int offset,
2510163953Srrs    struct sctp_paramhdr *pull,
2511163953Srrs    int pull_limit)
2512163953Srrs{
2513163953Srrs	/* This just provides a typed signature to Peter's Pull routine */
2514163953Srrs	return ((struct sctp_paramhdr *)sctp_m_getptr(m, offset, pull_limit,
2515163953Srrs	    (uint8_t *) pull));
2516163953Srrs}
2517163953Srrs
2518163953Srrs
2519163953Srrsint
2520163953Srrssctp_add_pad_tombuf(struct mbuf *m, int padlen)
2521163953Srrs{
2522163953Srrs	/*
2523163953Srrs	 * add padlen bytes of 0 filled padding to the end of the mbuf. If
2524163953Srrs	 * padlen is > 3 this routine will fail.
2525163953Srrs	 */
2526163953Srrs	uint8_t *dp;
2527163953Srrs	int i;
2528163953Srrs
2529163953Srrs	if (padlen > 3) {
2530171943Srrs		SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
2531163953Srrs		return (ENOBUFS);
2532163953Srrs	}
2533174387Srrs	if (padlen <= M_TRAILINGSPACE(m)) {
2534163953Srrs		/*
2535163953Srrs		 * The easy way. We hope the majority of the time we hit
2536163953Srrs		 * here :)
2537163953Srrs		 */
2538165647Srrs		dp = (uint8_t *) (mtod(m, caddr_t)+SCTP_BUF_LEN(m));
2539165647Srrs		SCTP_BUF_LEN(m) += padlen;
2540163953Srrs	} else {
2541163953Srrs		/* Hard way we must grow the mbuf */
2542163953Srrs		struct mbuf *tmp;
2543163953Srrs
2544163953Srrs		tmp = sctp_get_mbuf_for_msg(padlen, 0, M_DONTWAIT, 1, MT_DATA);
2545163953Srrs		if (tmp == NULL) {
2546163953Srrs			/* Out of space GAK! we are in big trouble. */
2547234796Stuexen			SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
2548234796Stuexen			return (ENOBUFS);
2549163953Srrs		}
2550163953Srrs		/* setup and insert in middle */
2551165647Srrs		SCTP_BUF_LEN(tmp) = padlen;
2552174387Srrs		SCTP_BUF_NEXT(tmp) = NULL;
2553165647Srrs		SCTP_BUF_NEXT(m) = tmp;
2554163953Srrs		dp = mtod(tmp, uint8_t *);
2555163953Srrs	}
2556163953Srrs	/* zero out the pad */
2557163953Srrs	for (i = 0; i < padlen; i++) {
2558163953Srrs		*dp = 0;
2559163953Srrs		dp++;
2560163953Srrs	}
2561163953Srrs	return (0);
2562163953Srrs}
2563163953Srrs
2564163953Srrsint
2565163953Srrssctp_pad_lastmbuf(struct mbuf *m, int padval, struct mbuf *last_mbuf)
2566163953Srrs{
2567163953Srrs	/* find the last mbuf in chain and pad it */
2568163953Srrs	struct mbuf *m_at;
2569163953Srrs
2570163953Srrs	if (last_mbuf) {
2571163953Srrs		return (sctp_add_pad_tombuf(last_mbuf, padval));
2572163953Srrs	} else {
2573237908Stuexen		for (m_at = m; m_at; m_at = SCTP_BUF_NEXT(m_at)) {
2574165647Srrs			if (SCTP_BUF_NEXT(m_at) == NULL) {
2575163953Srrs				return (sctp_add_pad_tombuf(m_at, padval));
2576163953Srrs			}
2577163953Srrs		}
2578163953Srrs	}
2579171943Srrs	SCTP_LTRACE_ERR_RET_PKT(m, NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT);
2580163953Srrs	return (EFAULT);
2581163953Srrs}
2582163953Srrs
2583163953Srrsstatic void
2584235431Stuexensctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
2585237886Stuexen    uint16_t error, struct sctp_abort_chunk *abort, uint8_t from_peer, int so_locked
2586172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
2587172090Srrs    SCTP_UNUSED
2588172090Srrs#endif
2589172090Srrs)
2590163953Srrs{
2591163953Srrs	struct mbuf *m_notify;
2592163953Srrs	struct sctp_assoc_change *sac;
2593163953Srrs	struct sctp_queued_to_read *control;
2594237884Stuexen	size_t notif_len, abort_len;
2595235175Stuexen	unsigned int i;
2596163953Srrs
2597252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2598172090Srrs	struct socket *so;
2599172090Srrs
2600172090Srrs#endif
2601172090Srrs
2602237885Stuexen	if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
2603237885Stuexen		notif_len = sizeof(struct sctp_assoc_change);
2604237885Stuexen		if (abort != NULL) {
2605266056Stuexen			abort_len = ntohs(abort->ch.chunk_length);
2606237885Stuexen		} else {
2607237885Stuexen			abort_len = 0;
2608237885Stuexen		}
2609237885Stuexen		if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
2610237885Stuexen			notif_len += SCTP_ASSOC_SUPPORTS_MAX;
2611237885Stuexen		} else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) {
2612237885Stuexen			notif_len += abort_len;
2613237885Stuexen		}
2614237885Stuexen		m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA);
2615237885Stuexen		if (m_notify == NULL) {
2616237885Stuexen			/* Retry with smaller value. */
2617237885Stuexen			notif_len = sizeof(struct sctp_assoc_change);
2618237885Stuexen			m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA);
2619237885Stuexen			if (m_notify == NULL) {
2620237885Stuexen				goto set_error;
2621237885Stuexen			}
2622237885Stuexen		}
2623237885Stuexen		SCTP_BUF_NEXT(m_notify) = NULL;
2624237885Stuexen		sac = mtod(m_notify, struct sctp_assoc_change *);
2625268433Sdelphij		memset(sac, 0, notif_len);
2626237885Stuexen		sac->sac_type = SCTP_ASSOC_CHANGE;
2627237885Stuexen		sac->sac_flags = 0;
2628237885Stuexen		sac->sac_length = sizeof(struct sctp_assoc_change);
2629237885Stuexen		sac->sac_state = state;
2630237885Stuexen		sac->sac_error = error;
2631237885Stuexen		/* XXX verify these stream counts */
2632237885Stuexen		sac->sac_outbound_streams = stcb->asoc.streamoutcnt;
2633237885Stuexen		sac->sac_inbound_streams = stcb->asoc.streamincnt;
2634237885Stuexen		sac->sac_assoc_id = sctp_get_associd(stcb);
2635237885Stuexen		if (notif_len > sizeof(struct sctp_assoc_change)) {
2636237885Stuexen			if ((state == SCTP_COMM_UP) || (state == SCTP_RESTART)) {
2637237885Stuexen				i = 0;
2638237885Stuexen				if (stcb->asoc.peer_supports_prsctp) {
2639237885Stuexen					sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_PR;
2640237885Stuexen				}
2641237885Stuexen				if (stcb->asoc.peer_supports_auth) {
2642237885Stuexen					sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_AUTH;
2643237885Stuexen				}
2644237885Stuexen				if (stcb->asoc.peer_supports_asconf) {
2645237885Stuexen					sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF;
2646237885Stuexen				}
2647237885Stuexen				sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF;
2648237885Stuexen				if (stcb->asoc.peer_supports_strreset) {
2649237885Stuexen					sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG;
2650237885Stuexen				}
2651237885Stuexen				sac->sac_length += i;
2652237885Stuexen			} else if ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC)) {
2653237885Stuexen				memcpy(sac->sac_info, abort, abort_len);
2654237885Stuexen				sac->sac_length += abort_len;
2655237885Stuexen			}
2656237885Stuexen		}
2657237885Stuexen		SCTP_BUF_LEN(m_notify) = sac->sac_length;
2658237885Stuexen		control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
2659237885Stuexen		    0, 0, stcb->asoc.context, 0, 0, 0,
2660237885Stuexen		    m_notify);
2661237885Stuexen		if (control != NULL) {
2662237885Stuexen			control->length = SCTP_BUF_LEN(m_notify);
2663237885Stuexen			/* not that we need this */
2664237885Stuexen			control->tail_mbuf = m_notify;
2665237885Stuexen			control->spec_flags = M_NOTIFICATION;
2666237885Stuexen			sctp_add_to_readq(stcb->sctp_ep, stcb,
2667237885Stuexen			    control,
2668237885Stuexen			    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD,
2669237885Stuexen			    so_locked);
2670237885Stuexen		} else {
2671237885Stuexen			sctp_m_freem(m_notify);
2672237885Stuexen		}
2673237885Stuexen	}
2674163953Srrs	/*
2675237885Stuexen	 * For 1-to-1 style sockets, we send up and error when an ABORT
2676237885Stuexen	 * comes in.
2677163953Srrs	 */
2678237885Stuexenset_error:
2679163953Srrs	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2680163953Srrs	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
2681235431Stuexen	    ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
2682252967Stuexen		SOCK_LOCK(stcb->sctp_socket);
2683237886Stuexen		if (from_peer) {
2684237886Stuexen			if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
2685237886Stuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNREFUSED);
2686237886Stuexen				stcb->sctp_socket->so_error = ECONNREFUSED;
2687237886Stuexen			} else {
2688237886Stuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
2689237886Stuexen				stcb->sctp_socket->so_error = ECONNRESET;
2690237886Stuexen			}
2691171943Srrs		} else {
2692252973Stuexen			if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) ||
2693252973Stuexen			    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
2694252973Stuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ETIMEDOUT);
2695252973Stuexen				stcb->sctp_socket->so_error = ETIMEDOUT;
2696252973Stuexen			} else {
2697252973Stuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ECONNABORTED);
2698252973Stuexen				stcb->sctp_socket->so_error = ECONNABORTED;
2699252973Stuexen			}
2700171943Srrs		}
2701237885Stuexen	}
2702237885Stuexen	/* Wake ANY sleepers */
2703252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2704237885Stuexen	so = SCTP_INP_SO(stcb->sctp_ep);
2705237885Stuexen	if (!so_locked) {
2706237885Stuexen		atomic_add_int(&stcb->asoc.refcnt, 1);
2707237885Stuexen		SCTP_TCB_UNLOCK(stcb);
2708237885Stuexen		SCTP_SOCKET_LOCK(so, 1);
2709237885Stuexen		SCTP_TCB_LOCK(stcb);
2710237885Stuexen		atomic_subtract_int(&stcb->asoc.refcnt, 1);
2711237885Stuexen		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
2712172090Srrs			SCTP_SOCKET_UNLOCK(so, 1);
2713237884Stuexen			return;
2714237884Stuexen		}
2715237884Stuexen	}
2716237885Stuexen#endif
2717237885Stuexen	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2718237885Stuexen	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
2719237885Stuexen	    ((state == SCTP_COMM_LOST) || (state == SCTP_CANT_STR_ASSOC))) {
2720252967Stuexen		socantrcvmore_locked(stcb->sctp_socket);
2721235175Stuexen	}
2722237885Stuexen	sorwakeup(stcb->sctp_socket);
2723237885Stuexen	sowwakeup(stcb->sctp_socket);
2724252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2725237885Stuexen	if (!so_locked) {
2726237885Stuexen		SCTP_SOCKET_UNLOCK(so, 1);
2727163953Srrs	}
2728172090Srrs#endif
2729163953Srrs}
2730163953Srrs
2731163953Srrsstatic void
2732163953Srrssctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
2733163953Srrs    struct sockaddr *sa, uint32_t error)
2734163953Srrs{
2735163953Srrs	struct mbuf *m_notify;
2736163953Srrs	struct sctp_paddr_change *spc;
2737163953Srrs	struct sctp_queued_to_read *control;
2738163953Srrs
2739231039Stuexen	if ((stcb == NULL) ||
2740231039Stuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) {
2741163953Srrs		/* event not enabled */
2742163953Srrs		return;
2743185694Srrs	}
2744165647Srrs	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_paddr_change), 0, M_DONTWAIT, 1, MT_DATA);
2745163953Srrs	if (m_notify == NULL)
2746163953Srrs		return;
2747165647Srrs	SCTP_BUF_LEN(m_notify) = 0;
2748163953Srrs	spc = mtod(m_notify, struct sctp_paddr_change *);
2749163953Srrs	spc->spc_type = SCTP_PEER_ADDR_CHANGE;
2750163953Srrs	spc->spc_flags = 0;
2751163953Srrs	spc->spc_length = sizeof(struct sctp_paddr_change);
2752178251Srrs	switch (sa->sa_family) {
2753221328Stuexen#ifdef INET
2754178251Srrs	case AF_INET:
2755163953Srrs		memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
2756178251Srrs		break;
2757221328Stuexen#endif
2758178251Srrs#ifdef INET6
2759178251Srrs	case AF_INET6:
2760178251Srrs		{
2761178251Srrs			struct sockaddr_in6 *sin6;
2762166675Srrs
2763178251Srrs			memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6));
2764166675Srrs
2765178251Srrs			sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
2766178251Srrs			if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
2767178251Srrs				if (sin6->sin6_scope_id == 0) {
2768178251Srrs					/* recover scope_id for user */
2769178251Srrs					(void)sa6_recoverscope(sin6);
2770178251Srrs				} else {
2771178251Srrs					/* clear embedded scope_id for user */
2772178251Srrs					in6_clearscope(&sin6->sin6_addr);
2773178251Srrs				}
2774167598Srrs			}
2775178251Srrs			break;
2776166675Srrs		}
2777178251Srrs#endif
2778178251Srrs	default:
2779178251Srrs		/* TSNH */
2780178251Srrs		break;
2781163953Srrs	}
2782163953Srrs	spc->spc_state = state;
2783163953Srrs	spc->spc_error = error;
2784163953Srrs	spc->spc_assoc_id = sctp_get_associd(stcb);
2785163953Srrs
2786165647Srrs	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_paddr_change);
2787165647Srrs	SCTP_BUF_NEXT(m_notify) = NULL;
2788163953Srrs
2789163953Srrs	/* append to socket */
2790163953Srrs	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
2791231038Stuexen	    0, 0, stcb->asoc.context, 0, 0, 0,
2792163953Srrs	    m_notify);
2793163953Srrs	if (control == NULL) {
2794163953Srrs		/* no memory */
2795163953Srrs		sctp_m_freem(m_notify);
2796163953Srrs		return;
2797163953Srrs	}
2798165647Srrs	control->length = SCTP_BUF_LEN(m_notify);
2799165647Srrs	control->spec_flags = M_NOTIFICATION;
2800163953Srrs	/* not that we need this */
2801163953Srrs	control->tail_mbuf = m_notify;
2802163953Srrs	sctp_add_to_readq(stcb->sctp_ep, stcb,
2803163953Srrs	    control,
2804195918Srrs	    &stcb->sctp_socket->so_rcv, 1,
2805195918Srrs	    SCTP_READ_LOCK_NOT_HELD,
2806195918Srrs	    SCTP_SO_NOT_LOCKED);
2807163953Srrs}
2808163953Srrs
2809163953Srrs
2810163953Srrsstatic void
2811237889Stuexensctp_notify_send_failed(struct sctp_tcb *stcb, uint8_t sent, uint32_t error,
2812172090Srrs    struct sctp_tmit_chunk *chk, int so_locked
2813172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
2814172090Srrs    SCTP_UNUSED
2815172090Srrs#endif
2816172090Srrs)
2817163953Srrs{
2818185694Srrs	struct mbuf *m_notify;
2819163953Srrs	struct sctp_send_failed *ssf;
2820235172Stuexen	struct sctp_send_failed_event *ssfe;
2821163953Srrs	struct sctp_queued_to_read *control;
2822163953Srrs	int length;
2823163953Srrs
2824231039Stuexen	if ((stcb == NULL) ||
2825235172Stuexen	    (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
2826235172Stuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
2827163953Srrs		/* event not enabled */
2828163953Srrs		return;
2829185694Srrs	}
2830235172Stuexen	if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
2831235172Stuexen		length = sizeof(struct sctp_send_failed_event);
2832235172Stuexen	} else {
2833235172Stuexen		length = sizeof(struct sctp_send_failed);
2834235172Stuexen	}
2835235172Stuexen	m_notify = sctp_get_mbuf_for_msg(length, 0, M_DONTWAIT, 1, MT_DATA);
2836163953Srrs	if (m_notify == NULL)
2837163953Srrs		/* no space left */
2838163953Srrs		return;
2839165647Srrs	SCTP_BUF_LEN(m_notify) = 0;
2840235172Stuexen	if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
2841235172Stuexen		ssfe = mtod(m_notify, struct sctp_send_failed_event *);
2842268433Sdelphij		memset(ssfe, 0, length);
2843235172Stuexen		ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
2844237889Stuexen		if (sent) {
2845237889Stuexen			ssfe->ssfe_flags = SCTP_DATA_SENT;
2846237889Stuexen		} else {
2847235172Stuexen			ssfe->ssfe_flags = SCTP_DATA_UNSENT;
2848237889Stuexen		}
2849268433Sdelphij		length += chk->send_size;
2850268433Sdelphij		length -= sizeof(struct sctp_data_chunk);
2851235172Stuexen		ssfe->ssfe_length = length;
2852235172Stuexen		ssfe->ssfe_error = error;
2853235172Stuexen		/* not exactly what the user sent in, but should be close :) */
2854235172Stuexen		ssfe->ssfe_info.snd_sid = chk->rec.data.stream_number;
2855235172Stuexen		ssfe->ssfe_info.snd_flags = chk->rec.data.rcv_flags;
2856235172Stuexen		ssfe->ssfe_info.snd_ppid = chk->rec.data.payloadtype;
2857235172Stuexen		ssfe->ssfe_info.snd_context = chk->rec.data.context;
2858235172Stuexen		ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
2859235172Stuexen		ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
2860235172Stuexen		SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
2861235172Stuexen	} else {
2862235172Stuexen		ssf = mtod(m_notify, struct sctp_send_failed *);
2863268433Sdelphij		memset(ssf, 0, length);
2864235172Stuexen		ssf->ssf_type = SCTP_SEND_FAILED;
2865237889Stuexen		if (sent) {
2866237889Stuexen			ssf->ssf_flags = SCTP_DATA_SENT;
2867237889Stuexen		} else {
2868235172Stuexen			ssf->ssf_flags = SCTP_DATA_UNSENT;
2869237889Stuexen		}
2870268433Sdelphij		length += chk->send_size;
2871268433Sdelphij		length -= sizeof(struct sctp_data_chunk);
2872235172Stuexen		ssf->ssf_length = length;
2873235172Stuexen		ssf->ssf_error = error;
2874235172Stuexen		/* not exactly what the user sent in, but should be close :) */
2875235172Stuexen		bzero(&ssf->ssf_info, sizeof(ssf->ssf_info));
2876235172Stuexen		ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
2877235172Stuexen		ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
2878235172Stuexen		ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
2879235172Stuexen		ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
2880235172Stuexen		ssf->ssf_info.sinfo_context = chk->rec.data.context;
2881235172Stuexen		ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
2882235172Stuexen		ssf->ssf_assoc_id = sctp_get_associd(stcb);
2883235172Stuexen		SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
2884235172Stuexen	}
2885185694Srrs	if (chk->data) {
2886185694Srrs		/*
2887185694Srrs		 * trim off the sctp chunk header(it should be there)
2888185694Srrs		 */
2889185694Srrs		if (chk->send_size >= sizeof(struct sctp_data_chunk)) {
2890185694Srrs			m_adj(chk->data, sizeof(struct sctp_data_chunk));
2891185694Srrs			sctp_mbuf_crush(chk->data);
2892185694Srrs			chk->send_size -= sizeof(struct sctp_data_chunk);
2893185694Srrs		}
2894185694Srrs	}
2895196260Stuexen	SCTP_BUF_NEXT(m_notify) = chk->data;
2896163953Srrs	/* Steal off the mbuf */
2897163953Srrs	chk->data = NULL;
2898163953Srrs	/*
2899163953Srrs	 * For this case, we check the actual socket buffer, since the assoc
2900163953Srrs	 * is going away we don't want to overfill the socket buffer for a
2901163953Srrs	 * non-reader
2902163953Srrs	 */
2903165647Srrs	if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
2904163953Srrs		sctp_m_freem(m_notify);
2905163953Srrs		return;
2906163953Srrs	}
2907163953Srrs	/* append to socket */
2908163953Srrs	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
2909231038Stuexen	    0, 0, stcb->asoc.context, 0, 0, 0,
2910163953Srrs	    m_notify);
2911163953Srrs	if (control == NULL) {
2912163953Srrs		/* no memory */
2913163953Srrs		sctp_m_freem(m_notify);
2914163953Srrs		return;
2915163953Srrs	}
2916165647Srrs	control->spec_flags = M_NOTIFICATION;
2917163953Srrs	sctp_add_to_readq(stcb->sctp_ep, stcb,
2918163953Srrs	    control,
2919195918Srrs	    &stcb->sctp_socket->so_rcv, 1,
2920195918Srrs	    SCTP_READ_LOCK_NOT_HELD,
2921195918Srrs	    so_locked);
2922163953Srrs}
2923163953Srrs
2924163953Srrs
2925163953Srrsstatic void
2926163953Srrssctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
2927172090Srrs    struct sctp_stream_queue_pending *sp, int so_locked
2928172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
2929172090Srrs    SCTP_UNUSED
2930172090Srrs#endif
2931172090Srrs)
2932163953Srrs{
2933163953Srrs	struct mbuf *m_notify;
2934163953Srrs	struct sctp_send_failed *ssf;
2935235172Stuexen	struct sctp_send_failed_event *ssfe;
2936163953Srrs	struct sctp_queued_to_read *control;
2937163953Srrs	int length;
2938163953Srrs
2939231039Stuexen	if ((stcb == NULL) ||
2940235172Stuexen	    (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT) &&
2941235172Stuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT))) {
2942163953Srrs		/* event not enabled */
2943163953Srrs		return;
2944185694Srrs	}
2945235172Stuexen	if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
2946235172Stuexen		length = sizeof(struct sctp_send_failed_event);
2947235172Stuexen	} else {
2948235172Stuexen		length = sizeof(struct sctp_send_failed);
2949235172Stuexen	}
2950235172Stuexen	m_notify = sctp_get_mbuf_for_msg(length, 0, M_DONTWAIT, 1, MT_DATA);
2951235172Stuexen	if (m_notify == NULL) {
2952163953Srrs		/* no space left */
2953163953Srrs		return;
2954235172Stuexen	}
2955165647Srrs	SCTP_BUF_LEN(m_notify) = 0;
2956235172Stuexen	if (sctp_stcb_is_feature_on(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVNSENDFAILEVNT)) {
2957235172Stuexen		ssfe = mtod(m_notify, struct sctp_send_failed_event *);
2958268433Sdelphij		memset(ssfe, 0, length);
2959238549Stuexen		ssfe->ssfe_type = SCTP_SEND_FAILED_EVENT;
2960237889Stuexen		ssfe->ssfe_flags = SCTP_DATA_UNSENT;
2961268433Sdelphij		length += sp->length;
2962235172Stuexen		ssfe->ssfe_length = length;
2963235172Stuexen		ssfe->ssfe_error = error;
2964235172Stuexen		/* not exactly what the user sent in, but should be close :) */
2965235172Stuexen		ssfe->ssfe_info.snd_sid = sp->stream;
2966235172Stuexen		if (sp->some_taken) {
2967235172Stuexen			ssfe->ssfe_info.snd_flags = SCTP_DATA_LAST_FRAG;
2968235172Stuexen		} else {
2969235172Stuexen			ssfe->ssfe_info.snd_flags = SCTP_DATA_NOT_FRAG;
2970235172Stuexen		}
2971235172Stuexen		ssfe->ssfe_info.snd_ppid = sp->ppid;
2972235172Stuexen		ssfe->ssfe_info.snd_context = sp->context;
2973235172Stuexen		ssfe->ssfe_info.snd_assoc_id = sctp_get_associd(stcb);
2974235172Stuexen		ssfe->ssfe_assoc_id = sctp_get_associd(stcb);
2975235172Stuexen		SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed_event);
2976180387Srrs	} else {
2977235172Stuexen		ssf = mtod(m_notify, struct sctp_send_failed *);
2978268433Sdelphij		memset(ssf, 0, length);
2979235172Stuexen		ssf->ssf_type = SCTP_SEND_FAILED;
2980237889Stuexen		ssf->ssf_flags = SCTP_DATA_UNSENT;
2981268433Sdelphij		length += sp->length;
2982235172Stuexen		ssf->ssf_length = length;
2983235172Stuexen		ssf->ssf_error = error;
2984235172Stuexen		/* not exactly what the user sent in, but should be close :) */
2985235172Stuexen		ssf->ssf_info.sinfo_stream = sp->stream;
2986252940Stuexen		ssf->ssf_info.sinfo_ssn = 0;
2987235172Stuexen		if (sp->some_taken) {
2988235172Stuexen			ssf->ssf_info.sinfo_flags = SCTP_DATA_LAST_FRAG;
2989235172Stuexen		} else {
2990235172Stuexen			ssf->ssf_info.sinfo_flags = SCTP_DATA_NOT_FRAG;
2991235172Stuexen		}
2992235172Stuexen		ssf->ssf_info.sinfo_ppid = sp->ppid;
2993235172Stuexen		ssf->ssf_info.sinfo_context = sp->context;
2994235172Stuexen		ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
2995235172Stuexen		ssf->ssf_assoc_id = sctp_get_associd(stcb);
2996235172Stuexen		SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_send_failed);
2997180387Srrs	}
2998165647Srrs	SCTP_BUF_NEXT(m_notify) = sp->data;
2999163953Srrs
3000163953Srrs	/* Steal off the mbuf */
3001163953Srrs	sp->data = NULL;
3002163953Srrs	/*
3003163953Srrs	 * For this case, we check the actual socket buffer, since the assoc
3004163953Srrs	 * is going away we don't want to overfill the socket buffer for a
3005163953Srrs	 * non-reader
3006163953Srrs	 */
3007165647Srrs	if (sctp_sbspace_failedmsgs(&stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
3008163953Srrs		sctp_m_freem(m_notify);
3009163953Srrs		return;
3010163953Srrs	}
3011163953Srrs	/* append to socket */
3012163953Srrs	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
3013231038Stuexen	    0, 0, stcb->asoc.context, 0, 0, 0,
3014163953Srrs	    m_notify);
3015163953Srrs	if (control == NULL) {
3016163953Srrs		/* no memory */
3017163953Srrs		sctp_m_freem(m_notify);
3018163953Srrs		return;
3019163953Srrs	}
3020165647Srrs	control->spec_flags = M_NOTIFICATION;
3021163953Srrs	sctp_add_to_readq(stcb->sctp_ep, stcb,
3022163953Srrs	    control,
3023195918Srrs	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked);
3024163953Srrs}
3025163953Srrs
3026163953Srrs
3027163953Srrs
3028163953Srrsstatic void
3029231038Stuexensctp_notify_adaptation_layer(struct sctp_tcb *stcb)
3030163953Srrs{
3031163953Srrs	struct mbuf *m_notify;
3032163953Srrs	struct sctp_adaptation_event *sai;
3033163953Srrs	struct sctp_queued_to_read *control;
3034163953Srrs
3035231039Stuexen	if ((stcb == NULL) ||
3036231039Stuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) {
3037163953Srrs		/* event not enabled */
3038163953Srrs		return;
3039185694Srrs	}
3040165647Srrs	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_adaption_event), 0, M_DONTWAIT, 1, MT_DATA);
3041163953Srrs	if (m_notify == NULL)
3042163953Srrs		/* no space left */
3043163953Srrs		return;
3044165647Srrs	SCTP_BUF_LEN(m_notify) = 0;
3045163953Srrs	sai = mtod(m_notify, struct sctp_adaptation_event *);
3046268433Sdelphij	memset(sai, 0, sizeof(struct sctp_adaptation_event));
3047163953Srrs	sai->sai_type = SCTP_ADAPTATION_INDICATION;
3048163953Srrs	sai->sai_flags = 0;
3049163953Srrs	sai->sai_length = sizeof(struct sctp_adaptation_event);
3050171990Srrs	sai->sai_adaptation_ind = stcb->asoc.peers_adaptation;
3051163953Srrs	sai->sai_assoc_id = sctp_get_associd(stcb);
3052163953Srrs
3053165647Srrs	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_adaptation_event);
3054165647Srrs	SCTP_BUF_NEXT(m_notify) = NULL;
3055163953Srrs
3056163953Srrs	/* append to socket */
3057163953Srrs	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
3058231038Stuexen	    0, 0, stcb->asoc.context, 0, 0, 0,
3059163953Srrs	    m_notify);
3060163953Srrs	if (control == NULL) {
3061163953Srrs		/* no memory */
3062163953Srrs		sctp_m_freem(m_notify);
3063163953Srrs		return;
3064163953Srrs	}
3065165647Srrs	control->length = SCTP_BUF_LEN(m_notify);
3066165647Srrs	control->spec_flags = M_NOTIFICATION;
3067163953Srrs	/* not that we need this */
3068163953Srrs	control->tail_mbuf = m_notify;
3069163953Srrs	sctp_add_to_readq(stcb->sctp_ep, stcb,
3070163953Srrs	    control,
3071195918Srrs	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
3072163953Srrs}
3073163953Srrs
3074164085Srrs/* This always must be called with the read-queue LOCKED in the INP */
3075196260Stuexenstatic void
3076171858Srrssctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
3077196260Stuexen    uint32_t val, int so_locked
3078196260Stuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
3079196260Stuexen    SCTP_UNUSED
3080196260Stuexen#endif
3081196260Stuexen)
3082163953Srrs{
3083163953Srrs	struct mbuf *m_notify;
3084163953Srrs	struct sctp_pdapi_event *pdapi;
3085163953Srrs	struct sctp_queued_to_read *control;
3086164085Srrs	struct sockbuf *sb;
3087163953Srrs
3088231039Stuexen	if ((stcb == NULL) ||
3089231039Stuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_PDAPIEVNT)) {
3090163953Srrs		/* event not enabled */
3091163953Srrs		return;
3092185694Srrs	}
3093209289Stuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) {
3094209289Stuexen		return;
3095209289Stuexen	}
3096165647Srrs	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_pdapi_event), 0, M_DONTWAIT, 1, MT_DATA);
3097163953Srrs	if (m_notify == NULL)
3098163953Srrs		/* no space left */
3099163953Srrs		return;
3100165647Srrs	SCTP_BUF_LEN(m_notify) = 0;
3101163953Srrs	pdapi = mtod(m_notify, struct sctp_pdapi_event *);
3102268433Sdelphij	memset(pdapi, 0, sizeof(struct sctp_pdapi_event));
3103163953Srrs	pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT;
3104163953Srrs	pdapi->pdapi_flags = 0;
3105163953Srrs	pdapi->pdapi_length = sizeof(struct sctp_pdapi_event);
3106163953Srrs	pdapi->pdapi_indication = error;
3107168943Srrs	pdapi->pdapi_stream = (val >> 16);
3108168943Srrs	pdapi->pdapi_seq = (val & 0x0000ffff);
3109163953Srrs	pdapi->pdapi_assoc_id = sctp_get_associd(stcb);
3110163953Srrs
3111165647Srrs	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_pdapi_event);
3112165647Srrs	SCTP_BUF_NEXT(m_notify) = NULL;
3113164085Srrs	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
3114231038Stuexen	    0, 0, stcb->asoc.context, 0, 0, 0,
3115164085Srrs	    m_notify);
3116164085Srrs	if (control == NULL) {
3117164085Srrs		/* no memory */
3118164085Srrs		sctp_m_freem(m_notify);
3119164085Srrs		return;
3120164085Srrs	}
3121165647Srrs	control->spec_flags = M_NOTIFICATION;
3122165647Srrs	control->length = SCTP_BUF_LEN(m_notify);
3123164085Srrs	/* not that we need this */
3124164085Srrs	control->tail_mbuf = m_notify;
3125164085Srrs	control->held_length = 0;
3126164085Srrs	control->length = 0;
3127164085Srrs	sb = &stcb->sctp_socket->so_rcv;
3128179783Srrs	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
3129170744Srrs		sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m_notify));
3130170744Srrs	}
3131164085Srrs	sctp_sballoc(stcb, sb, m_notify);
3132179783Srrs	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
3133170744Srrs		sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0);
3134170744Srrs	}
3135165647Srrs	atomic_add_int(&control->length, SCTP_BUF_LEN(m_notify));
3136164085Srrs	control->end_added = 1;
3137164085Srrs	if (stcb->asoc.control_pdapi)
3138164085Srrs		TAILQ_INSERT_AFTER(&stcb->sctp_ep->read_queue, stcb->asoc.control_pdapi, control, next);
3139164085Srrs	else {
3140164085Srrs		/* we really should not see this case */
3141164085Srrs		TAILQ_INSERT_TAIL(&stcb->sctp_ep->read_queue, control, next);
3142164085Srrs	}
3143164085Srrs	if (stcb->sctp_ep && stcb->sctp_socket) {
3144164085Srrs		/* This should always be the case */
3145252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3146196260Stuexen		struct socket *so;
3147196260Stuexen
3148196260Stuexen		so = SCTP_INP_SO(stcb->sctp_ep);
3149196260Stuexen		if (!so_locked) {
3150196260Stuexen			atomic_add_int(&stcb->asoc.refcnt, 1);
3151196260Stuexen			SCTP_TCB_UNLOCK(stcb);
3152196260Stuexen			SCTP_SOCKET_LOCK(so, 1);
3153196260Stuexen			SCTP_TCB_LOCK(stcb);
3154196260Stuexen			atomic_subtract_int(&stcb->asoc.refcnt, 1);
3155196260Stuexen			if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
3156196260Stuexen				SCTP_SOCKET_UNLOCK(so, 1);
3157196260Stuexen				return;
3158196260Stuexen			}
3159196260Stuexen		}
3160196260Stuexen#endif
3161163996Srrs		sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
3162252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3163196260Stuexen		if (!so_locked) {
3164196260Stuexen			SCTP_SOCKET_UNLOCK(so, 1);
3165196260Stuexen		}
3166196260Stuexen#endif
3167163953Srrs	}
3168163953Srrs}
3169163953Srrs
3170163953Srrsstatic void
3171163953Srrssctp_notify_shutdown_event(struct sctp_tcb *stcb)
3172163953Srrs{
3173163953Srrs	struct mbuf *m_notify;
3174163953Srrs	struct sctp_shutdown_event *sse;
3175163953Srrs	struct sctp_queued_to_read *control;
3176163953Srrs
3177163953Srrs	/*
3178163953Srrs	 * For TCP model AND UDP connected sockets we will send an error up
3179163953Srrs	 * when an SHUTDOWN completes
3180163953Srrs	 */
3181163953Srrs	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3182163953Srrs	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3183163953Srrs		/* mark socket closed for read/write and wakeup! */
3184252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3185172090Srrs		struct socket *so;
3186172090Srrs
3187172090Srrs		so = SCTP_INP_SO(stcb->sctp_ep);
3188172090Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
3189172090Srrs		SCTP_TCB_UNLOCK(stcb);
3190172090Srrs		SCTP_SOCKET_LOCK(so, 1);
3191172090Srrs		SCTP_TCB_LOCK(stcb);
3192172090Srrs		atomic_subtract_int(&stcb->asoc.refcnt, 1);
3193172090Srrs		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
3194172090Srrs			SCTP_SOCKET_UNLOCK(so, 1);
3195172090Srrs			return;
3196172090Srrs		}
3197172090Srrs#endif
3198163953Srrs		socantsendmore(stcb->sctp_socket);
3199252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3200172090Srrs		SCTP_SOCKET_UNLOCK(so, 1);
3201172090Srrs#endif
3202163953Srrs	}
3203223132Stuexen	if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)) {
3204163953Srrs		/* event not enabled */
3205163953Srrs		return;
3206185694Srrs	}
3207165647Srrs	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_event), 0, M_DONTWAIT, 1, MT_DATA);
3208163953Srrs	if (m_notify == NULL)
3209163953Srrs		/* no space left */
3210163953Srrs		return;
3211163953Srrs	sse = mtod(m_notify, struct sctp_shutdown_event *);
3212268433Sdelphij	memset(sse, 0, sizeof(struct sctp_shutdown_event));
3213163953Srrs	sse->sse_type = SCTP_SHUTDOWN_EVENT;
3214163953Srrs	sse->sse_flags = 0;
3215163953Srrs	sse->sse_length = sizeof(struct sctp_shutdown_event);
3216163953Srrs	sse->sse_assoc_id = sctp_get_associd(stcb);
3217163953Srrs
3218165647Srrs	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_shutdown_event);
3219165647Srrs	SCTP_BUF_NEXT(m_notify) = NULL;
3220163953Srrs
3221163953Srrs	/* append to socket */
3222163953Srrs	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
3223231038Stuexen	    0, 0, stcb->asoc.context, 0, 0, 0,
3224163953Srrs	    m_notify);
3225163953Srrs	if (control == NULL) {
3226163953Srrs		/* no memory */
3227163953Srrs		sctp_m_freem(m_notify);
3228163953Srrs		return;
3229163953Srrs	}
3230165647Srrs	control->spec_flags = M_NOTIFICATION;
3231165647Srrs	control->length = SCTP_BUF_LEN(m_notify);
3232163953Srrs	/* not that we need this */
3233163953Srrs	control->tail_mbuf = m_notify;
3234163953Srrs	sctp_add_to_readq(stcb->sctp_ep, stcb,
3235163953Srrs	    control,
3236195918Srrs	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
3237163953Srrs}
3238163953Srrs
3239163953Srrsstatic void
3240185694Srrssctp_notify_sender_dry_event(struct sctp_tcb *stcb,
3241185694Srrs    int so_locked
3242185694Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
3243185694Srrs    SCTP_UNUSED
3244185694Srrs#endif
3245185694Srrs)
3246185694Srrs{
3247185694Srrs	struct mbuf *m_notify;
3248185694Srrs	struct sctp_sender_dry_event *event;
3249185694Srrs	struct sctp_queued_to_read *control;
3250185694Srrs
3251231039Stuexen	if ((stcb == NULL) ||
3252231039Stuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DRYEVNT)) {
3253185694Srrs		/* event not enabled */
3254185694Srrs		return;
3255185694Srrs	}
3256185694Srrs	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_sender_dry_event), 0, M_DONTWAIT, 1, MT_DATA);
3257185694Srrs	if (m_notify == NULL) {
3258185694Srrs		/* no space left */
3259185694Srrs		return;
3260185694Srrs	}
3261185694Srrs	SCTP_BUF_LEN(m_notify) = 0;
3262185694Srrs	event = mtod(m_notify, struct sctp_sender_dry_event *);
3263268433Sdelphij	memset(event, 0, sizeof(struct sctp_sender_dry_event));
3264185694Srrs	event->sender_dry_type = SCTP_SENDER_DRY_EVENT;
3265185694Srrs	event->sender_dry_flags = 0;
3266185694Srrs	event->sender_dry_length = sizeof(struct sctp_sender_dry_event);
3267185694Srrs	event->sender_dry_assoc_id = sctp_get_associd(stcb);
3268185694Srrs
3269185694Srrs	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_sender_dry_event);
3270185694Srrs	SCTP_BUF_NEXT(m_notify) = NULL;
3271185694Srrs
3272185694Srrs	/* append to socket */
3273185694Srrs	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
3274231038Stuexen	    0, 0, stcb->asoc.context, 0, 0, 0,
3275231038Stuexen	    m_notify);
3276185694Srrs	if (control == NULL) {
3277185694Srrs		/* no memory */
3278185694Srrs		sctp_m_freem(m_notify);
3279185694Srrs		return;
3280185694Srrs	}
3281185694Srrs	control->length = SCTP_BUF_LEN(m_notify);
3282185694Srrs	control->spec_flags = M_NOTIFICATION;
3283185694Srrs	/* not that we need this */
3284185694Srrs	control->tail_mbuf = m_notify;
3285185694Srrs	sctp_add_to_readq(stcb->sctp_ep, stcb, control,
3286195918Srrs	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, so_locked);
3287185694Srrs}
3288185694Srrs
3289188854Srrs
3290234790Stuexenvoid
3291234790Stuexensctp_notify_stream_reset_add(struct sctp_tcb *stcb, uint16_t numberin, uint16_t numberout, int flag)
3292188854Srrs{
3293188854Srrs	struct mbuf *m_notify;
3294188854Srrs	struct sctp_queued_to_read *control;
3295234790Stuexen	struct sctp_stream_change_event *stradd;
3296188854Srrs
3297235176Stuexen	if ((stcb == NULL) ||
3298235176Stuexen	    (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_CHANGEEVNT))) {
3299188854Srrs		/* event not enabled */
3300188854Srrs		return;
3301188854Srrs	}
3302234790Stuexen	if ((stcb->asoc.peer_req_out) && flag) {
3303234790Stuexen		/* Peer made the request, don't tell the local user */
3304234790Stuexen		stcb->asoc.peer_req_out = 0;
3305234790Stuexen		return;
3306234790Stuexen	}
3307234790Stuexen	stcb->asoc.peer_req_out = 0;
3308268433Sdelphij	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_stream_change_event), 0, M_DONTWAIT, 1, MT_DATA);
3309188854Srrs	if (m_notify == NULL)
3310188854Srrs		/* no space left */
3311188854Srrs		return;
3312188854Srrs	SCTP_BUF_LEN(m_notify) = 0;
3313234790Stuexen	stradd = mtod(m_notify, struct sctp_stream_change_event *);
3314268433Sdelphij	memset(stradd, 0, sizeof(struct sctp_stream_change_event));
3315234790Stuexen	stradd->strchange_type = SCTP_STREAM_CHANGE_EVENT;
3316234790Stuexen	stradd->strchange_flags = flag;
3317268433Sdelphij	stradd->strchange_length = sizeof(struct sctp_stream_change_event);
3318234790Stuexen	stradd->strchange_assoc_id = sctp_get_associd(stcb);
3319234790Stuexen	stradd->strchange_instrms = numberin;
3320234790Stuexen	stradd->strchange_outstrms = numberout;
3321268433Sdelphij	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_stream_change_event);
3322234790Stuexen	SCTP_BUF_NEXT(m_notify) = NULL;
3323234790Stuexen	if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
3324234790Stuexen		/* no space */
3325234790Stuexen		sctp_m_freem(m_notify);
3326234790Stuexen		return;
3327234790Stuexen	}
3328234790Stuexen	/* append to socket */
3329234790Stuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
3330234790Stuexen	    0, 0, stcb->asoc.context, 0, 0, 0,
3331234790Stuexen	    m_notify);
3332234790Stuexen	if (control == NULL) {
3333234790Stuexen		/* no memory */
3334234790Stuexen		sctp_m_freem(m_notify);
3335234790Stuexen		return;
3336234790Stuexen	}
3337234790Stuexen	control->spec_flags = M_NOTIFICATION;
3338234790Stuexen	control->length = SCTP_BUF_LEN(m_notify);
3339234790Stuexen	/* not that we need this */
3340234790Stuexen	control->tail_mbuf = m_notify;
3341234790Stuexen	sctp_add_to_readq(stcb->sctp_ep, stcb,
3342234790Stuexen	    control,
3343234790Stuexen	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
3344234790Stuexen}
3345188854Srrs
3346234790Stuexenvoid
3347234790Stuexensctp_notify_stream_reset_tsn(struct sctp_tcb *stcb, uint32_t sending_tsn, uint32_t recv_tsn, int flag)
3348234790Stuexen{
3349234790Stuexen	struct mbuf *m_notify;
3350234790Stuexen	struct sctp_queued_to_read *control;
3351234790Stuexen	struct sctp_assoc_reset_event *strasoc;
3352234790Stuexen
3353235176Stuexen	if ((stcb == NULL) ||
3354235176Stuexen	    (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ASSOC_RESETEVNT))) {
3355234790Stuexen		/* event not enabled */
3356234790Stuexen		return;
3357234790Stuexen	}
3358268433Sdelphij	m_notify = sctp_get_mbuf_for_msg(sizeof(struct sctp_assoc_reset_event), 0, M_DONTWAIT, 1, MT_DATA);
3359234790Stuexen	if (m_notify == NULL)
3360234790Stuexen		/* no space left */
3361234790Stuexen		return;
3362234790Stuexen	SCTP_BUF_LEN(m_notify) = 0;
3363234790Stuexen	strasoc = mtod(m_notify, struct sctp_assoc_reset_event *);
3364268433Sdelphij	memset(strasoc, 0, sizeof(struct sctp_assoc_reset_event));
3365234790Stuexen	strasoc->assocreset_type = SCTP_ASSOC_RESET_EVENT;
3366234790Stuexen	strasoc->assocreset_flags = flag;
3367268433Sdelphij	strasoc->assocreset_length = sizeof(struct sctp_assoc_reset_event);
3368234790Stuexen	strasoc->assocreset_assoc_id = sctp_get_associd(stcb);
3369234790Stuexen	strasoc->assocreset_local_tsn = sending_tsn;
3370234790Stuexen	strasoc->assocreset_remote_tsn = recv_tsn;
3371268433Sdelphij	SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_assoc_reset_event);
3372188854Srrs	SCTP_BUF_NEXT(m_notify) = NULL;
3373188854Srrs	if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
3374188854Srrs		/* no space */
3375188854Srrs		sctp_m_freem(m_notify);
3376188854Srrs		return;
3377188854Srrs	}
3378188854Srrs	/* append to socket */
3379188854Srrs	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
3380231038Stuexen	    0, 0, stcb->asoc.context, 0, 0, 0,
3381188854Srrs	    m_notify);
3382188854Srrs	if (control == NULL) {
3383188854Srrs		/* no memory */
3384188854Srrs		sctp_m_freem(m_notify);
3385188854Srrs		return;
3386188854Srrs	}
3387188854Srrs	control->spec_flags = M_NOTIFICATION;
3388188854Srrs	control->length = SCTP_BUF_LEN(m_notify);
3389188854Srrs	/* not that we need this */
3390188854Srrs	control->tail_mbuf = m_notify;
3391188854Srrs	sctp_add_to_readq(stcb->sctp_ep, stcb,
3392188854Srrs	    control,
3393195918Srrs	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
3394188854Srrs}
3395188854Srrs
3396188854Srrs
3397234790Stuexen
3398188854Srrsstatic void
3399163953Srrssctp_notify_stream_reset(struct sctp_tcb *stcb,
3400163953Srrs    int number_entries, uint16_t * list, int flag)
3401163953Srrs{
3402163953Srrs	struct mbuf *m_notify;
3403163953Srrs	struct sctp_queued_to_read *control;
3404163953Srrs	struct sctp_stream_reset_event *strreset;
3405163953Srrs	int len;
3406163953Srrs
3407235176Stuexen	if ((stcb == NULL) ||
3408235176Stuexen	    (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT))) {
3409185694Srrs		/* event not enabled */
3410169420Srrs		return;
3411169420Srrs	}
3412165647Srrs	m_notify = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
3413163953Srrs	if (m_notify == NULL)
3414163953Srrs		/* no space left */
3415163953Srrs		return;
3416165647Srrs	SCTP_BUF_LEN(m_notify) = 0;
3417163953Srrs	len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t));
3418163953Srrs	if (len > M_TRAILINGSPACE(m_notify)) {
3419163953Srrs		/* never enough room */
3420163953Srrs		sctp_m_freem(m_notify);
3421163953Srrs		return;
3422163953Srrs	}
3423163953Srrs	strreset = mtod(m_notify, struct sctp_stream_reset_event *);
3424268433Sdelphij	memset(strreset, 0, len);
3425163953Srrs	strreset->strreset_type = SCTP_STREAM_RESET_EVENT;
3426234790Stuexen	strreset->strreset_flags = flag;
3427163953Srrs	strreset->strreset_length = len;
3428163953Srrs	strreset->strreset_assoc_id = sctp_get_associd(stcb);
3429163953Srrs	if (number_entries) {
3430163953Srrs		int i;
3431163953Srrs
3432163953Srrs		for (i = 0; i < number_entries; i++) {
3433234790Stuexen			strreset->strreset_stream_list[i] = ntohs(list[i]);
3434163953Srrs		}
3435163953Srrs	}
3436165647Srrs	SCTP_BUF_LEN(m_notify) = len;
3437165647Srrs	SCTP_BUF_NEXT(m_notify) = NULL;
3438165647Srrs	if (sctp_sbspace(&stcb->asoc, &stcb->sctp_socket->so_rcv) < SCTP_BUF_LEN(m_notify)) {
3439163953Srrs		/* no space */
3440163953Srrs		sctp_m_freem(m_notify);
3441163953Srrs		return;
3442163953Srrs	}
3443163953Srrs	/* append to socket */
3444163953Srrs	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
3445231038Stuexen	    0, 0, stcb->asoc.context, 0, 0, 0,
3446163953Srrs	    m_notify);
3447163953Srrs	if (control == NULL) {
3448163953Srrs		/* no memory */
3449163953Srrs		sctp_m_freem(m_notify);
3450163953Srrs		return;
3451163953Srrs	}
3452165647Srrs	control->spec_flags = M_NOTIFICATION;
3453165647Srrs	control->length = SCTP_BUF_LEN(m_notify);
3454163953Srrs	/* not that we need this */
3455163953Srrs	control->tail_mbuf = m_notify;
3456163953Srrs	sctp_add_to_readq(stcb->sctp_ep, stcb,
3457163953Srrs	    control,
3458195918Srrs	    &stcb->sctp_socket->so_rcv, 1, SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
3459163953Srrs}
3460163953Srrs
3461163953Srrs
3462237890Stuexenstatic void
3463237890Stuexensctp_notify_remote_error(struct sctp_tcb *stcb, uint16_t error, struct sctp_error_chunk *chunk)
3464237890Stuexen{
3465237890Stuexen	struct mbuf *m_notify;
3466237890Stuexen	struct sctp_remote_error *sre;
3467237890Stuexen	struct sctp_queued_to_read *control;
3468237890Stuexen	size_t notif_len, chunk_len;
3469237890Stuexen
3470237890Stuexen	if ((stcb == NULL) ||
3471237890Stuexen	    sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPEERERR)) {
3472237890Stuexen		return;
3473237890Stuexen	}
3474237890Stuexen	if (chunk != NULL) {
3475266056Stuexen		chunk_len = ntohs(chunk->ch.chunk_length);
3476237890Stuexen	} else {
3477237890Stuexen		chunk_len = 0;
3478237890Stuexen	}
3479237890Stuexen	notif_len = sizeof(struct sctp_remote_error) + chunk_len;
3480237890Stuexen	m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA);
3481237890Stuexen	if (m_notify == NULL) {
3482237890Stuexen		/* Retry with smaller value. */
3483237890Stuexen		notif_len = sizeof(struct sctp_remote_error);
3484237890Stuexen		m_notify = sctp_get_mbuf_for_msg(notif_len, 0, M_DONTWAIT, 1, MT_DATA);
3485237890Stuexen		if (m_notify == NULL) {
3486237890Stuexen			return;
3487237890Stuexen		}
3488237890Stuexen	}
3489237890Stuexen	SCTP_BUF_NEXT(m_notify) = NULL;
3490237890Stuexen	sre = mtod(m_notify, struct sctp_remote_error *);
3491237890Stuexen	sre->sre_type = SCTP_REMOTE_ERROR;
3492237890Stuexen	sre->sre_flags = 0;
3493237890Stuexen	sre->sre_length = sizeof(struct sctp_remote_error);
3494237890Stuexen	sre->sre_error = error;
3495237890Stuexen	sre->sre_assoc_id = sctp_get_associd(stcb);
3496237890Stuexen	if (notif_len > sizeof(struct sctp_remote_error)) {
3497237890Stuexen		memcpy(sre->sre_data, chunk, chunk_len);
3498237890Stuexen		sre->sre_length += chunk_len;
3499237890Stuexen	}
3500237890Stuexen	SCTP_BUF_LEN(m_notify) = sre->sre_length;
3501237890Stuexen	control = sctp_build_readq_entry(stcb, stcb->asoc.primary_destination,
3502237890Stuexen	    0, 0, stcb->asoc.context, 0, 0, 0,
3503237890Stuexen	    m_notify);
3504237890Stuexen	if (control != NULL) {
3505237890Stuexen		control->length = SCTP_BUF_LEN(m_notify);
3506237890Stuexen		/* not that we need this */
3507237890Stuexen		control->tail_mbuf = m_notify;
3508237890Stuexen		control->spec_flags = M_NOTIFICATION;
3509237890Stuexen		sctp_add_to_readq(stcb->sctp_ep, stcb,
3510237890Stuexen		    control,
3511237890Stuexen		    &stcb->sctp_socket->so_rcv, 1,
3512237890Stuexen		    SCTP_READ_LOCK_NOT_HELD, SCTP_SO_NOT_LOCKED);
3513237890Stuexen	} else {
3514237890Stuexen		sctp_m_freem(m_notify);
3515237890Stuexen	}
3516237890Stuexen}
3517237890Stuexen
3518237890Stuexen
3519163953Srrsvoid
3520163953Srrssctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
3521172090Srrs    uint32_t error, void *data, int so_locked
3522172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
3523172090Srrs    SCTP_UNUSED
3524172090Srrs#endif
3525172090Srrs)
3526163953Srrs{
3527185694Srrs	if ((stcb == NULL) ||
3528185694Srrs	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
3529163953Srrs	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
3530185694Srrs	    (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
3531185694Srrs		/* If the socket is gone we are out of here */
3532163953Srrs		return;
3533163953Srrs	}
3534188067Srrs	if (stcb->sctp_socket->so_rcv.sb_state & SBS_CANTRCVMORE) {
3535188067Srrs		return;
3536188067Srrs	}
3537252974Stuexen	if ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) ||
3538252974Stuexen	    (stcb->asoc.state & SCTP_STATE_COOKIE_ECHOED)) {
3539169352Srrs		if ((notification == SCTP_NOTIFY_INTERFACE_DOWN) ||
3540169352Srrs		    (notification == SCTP_NOTIFY_INTERFACE_UP) ||
3541169352Srrs		    (notification == SCTP_NOTIFY_INTERFACE_CONFIRMED)) {
3542169352Srrs			/* Don't report these in front states */
3543169352Srrs			return;
3544169352Srrs		}
3545169352Srrs	}
3546163953Srrs	switch (notification) {
3547163953Srrs	case SCTP_NOTIFY_ASSOC_UP:
3548163953Srrs		if (stcb->asoc.assoc_up_sent == 0) {
3549237886Stuexen			sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error, NULL, 0, so_locked);
3550163953Srrs			stcb->asoc.assoc_up_sent = 1;
3551163953Srrs		}
3552171990Srrs		if (stcb->asoc.adaptation_needed && (stcb->asoc.adaptation_sent == 0)) {
3553231038Stuexen			sctp_notify_adaptation_layer(stcb);
3554171990Srrs		}
3555185694Srrs		if (stcb->asoc.peer_supports_auth == 0) {
3556185694Srrs			sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
3557185694Srrs			    NULL, so_locked);
3558185694Srrs		}
3559163953Srrs		break;
3560163953Srrs	case SCTP_NOTIFY_ASSOC_DOWN:
3561237886Stuexen		sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error, NULL, 0, so_locked);
3562163953Srrs		break;
3563163953Srrs	case SCTP_NOTIFY_INTERFACE_DOWN:
3564163953Srrs		{
3565163953Srrs			struct sctp_nets *net;
3566163953Srrs
3567163953Srrs			net = (struct sctp_nets *)data;
3568163953Srrs			sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE,
3569163953Srrs			    (struct sockaddr *)&net->ro._l_addr, error);
3570163953Srrs			break;
3571163953Srrs		}
3572163953Srrs	case SCTP_NOTIFY_INTERFACE_UP:
3573163953Srrs		{
3574163953Srrs			struct sctp_nets *net;
3575163953Srrs
3576163953Srrs			net = (struct sctp_nets *)data;
3577163953Srrs			sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE,
3578163953Srrs			    (struct sockaddr *)&net->ro._l_addr, error);
3579163953Srrs			break;
3580163953Srrs		}
3581163953Srrs	case SCTP_NOTIFY_INTERFACE_CONFIRMED:
3582163953Srrs		{
3583163953Srrs			struct sctp_nets *net;
3584163953Srrs
3585163953Srrs			net = (struct sctp_nets *)data;
3586163953Srrs			sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED,
3587163953Srrs			    (struct sockaddr *)&net->ro._l_addr, error);
3588163953Srrs			break;
3589163953Srrs		}
3590163953Srrs	case SCTP_NOTIFY_SPECIAL_SP_FAIL:
3591163953Srrs		sctp_notify_send_failed2(stcb, error,
3592172090Srrs		    (struct sctp_stream_queue_pending *)data, so_locked);
3593163953Srrs		break;
3594237889Stuexen	case SCTP_NOTIFY_SENT_DG_FAIL:
3595237889Stuexen		sctp_notify_send_failed(stcb, 1, error,
3596172090Srrs		    (struct sctp_tmit_chunk *)data, so_locked);
3597163953Srrs		break;
3598237889Stuexen	case SCTP_NOTIFY_UNSENT_DG_FAIL:
3599237889Stuexen		sctp_notify_send_failed(stcb, 0, error,
3600237889Stuexen		    (struct sctp_tmit_chunk *)data, so_locked);
3601237889Stuexen		break;
3602163953Srrs	case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION:
3603168943Srrs		{
3604168943Srrs			uint32_t val;
3605168943Srrs
3606168943Srrs			val = *((uint32_t *) data);
3607168943Srrs
3608196260Stuexen			sctp_notify_partial_delivery_indication(stcb, error, val, so_locked);
3609196260Stuexen			break;
3610168943Srrs		}
3611237886Stuexen	case SCTP_NOTIFY_ASSOC_LOC_ABORTED:
3612252974Stuexen		if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
3613252974Stuexen		    ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) {
3614237886Stuexen			sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 0, so_locked);
3615168709Srrs		} else {
3616237886Stuexen			sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 0, so_locked);
3617168709Srrs		}
3618163953Srrs		break;
3619237886Stuexen	case SCTP_NOTIFY_ASSOC_REM_ABORTED:
3620252974Stuexen		if (((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_WAIT) ||
3621252974Stuexen		    ((stcb->asoc.state & SCTP_STATE_MASK) == SCTP_STATE_COOKIE_ECHOED)) {
3622237886Stuexen			sctp_notify_assoc_change(SCTP_CANT_STR_ASSOC, stcb, error, data, 1, so_locked);
3623237886Stuexen		} else {
3624237886Stuexen			sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error, data, 1, so_locked);
3625237886Stuexen		}
3626237886Stuexen		break;
3627163953Srrs	case SCTP_NOTIFY_ASSOC_RESTART:
3628237886Stuexen		sctp_notify_assoc_change(SCTP_RESTART, stcb, error, NULL, 0, so_locked);
3629185694Srrs		if (stcb->asoc.peer_supports_auth == 0) {
3630185694Srrs			sctp_ulp_notify(SCTP_NOTIFY_NO_PEER_AUTH, stcb, 0,
3631185694Srrs			    NULL, so_locked);
3632185694Srrs		}
3633163953Srrs		break;
3634163953Srrs	case SCTP_NOTIFY_STR_RESET_SEND:
3635234801Stuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_OUTGOING_SSN);
3636163953Srrs		break;
3637163953Srrs	case SCTP_NOTIFY_STR_RESET_RECV:
3638234801Stuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data), SCTP_STREAM_RESET_INCOMING);
3639163953Srrs		break;
3640163953Srrs	case SCTP_NOTIFY_STR_RESET_FAILED_OUT:
3641234790Stuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
3642234801Stuexen		    (SCTP_STREAM_RESET_OUTGOING_SSN | SCTP_STREAM_RESET_FAILED));
3643163953Srrs		break;
3644235171Stuexen	case SCTP_NOTIFY_STR_RESET_DENIED_OUT:
3645235171Stuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
3646235171Stuexen		    (SCTP_STREAM_RESET_OUTGOING_SSN | SCTP_STREAM_RESET_DENIED));
3647235171Stuexen		break;
3648163953Srrs	case SCTP_NOTIFY_STR_RESET_FAILED_IN:
3649234790Stuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
3650234801Stuexen		    (SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_FAILED));
3651163953Srrs		break;
3652235171Stuexen	case SCTP_NOTIFY_STR_RESET_DENIED_IN:
3653235171Stuexen		sctp_notify_stream_reset(stcb, error, ((uint16_t *) data),
3654235171Stuexen		    (SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_DENIED));
3655235171Stuexen		break;
3656163953Srrs	case SCTP_NOTIFY_ASCONF_ADD_IP:
3657163953Srrs		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data,
3658163953Srrs		    error);
3659163953Srrs		break;
3660163953Srrs	case SCTP_NOTIFY_ASCONF_DELETE_IP:
3661163953Srrs		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data,
3662163953Srrs		    error);
3663163953Srrs		break;
3664163953Srrs	case SCTP_NOTIFY_ASCONF_SET_PRIMARY:
3665163953Srrs		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data,
3666163953Srrs		    error);
3667163953Srrs		break;
3668163953Srrs	case SCTP_NOTIFY_PEER_SHUTDOWN:
3669163953Srrs		sctp_notify_shutdown_event(stcb);
3670163953Srrs		break;
3671163953Srrs	case SCTP_NOTIFY_AUTH_NEW_KEY:
3672234802Stuexen		sctp_notify_authentication(stcb, SCTP_AUTH_NEW_KEY, error,
3673185694Srrs		    (uint16_t) (uintptr_t) data,
3674185694Srrs		    so_locked);
3675163953Srrs		break;
3676185694Srrs	case SCTP_NOTIFY_AUTH_FREE_KEY:
3677185694Srrs		sctp_notify_authentication(stcb, SCTP_AUTH_FREE_KEY, error,
3678185694Srrs		    (uint16_t) (uintptr_t) data,
3679185694Srrs		    so_locked);
3680163953Srrs		break;
3681185694Srrs	case SCTP_NOTIFY_NO_PEER_AUTH:
3682185694Srrs		sctp_notify_authentication(stcb, SCTP_AUTH_NO_AUTH, error,
3683185694Srrs		    (uint16_t) (uintptr_t) data,
3684185694Srrs		    so_locked);
3685185694Srrs		break;
3686185694Srrs	case SCTP_NOTIFY_SENDER_DRY:
3687185694Srrs		sctp_notify_sender_dry_event(stcb, so_locked);
3688185694Srrs		break;
3689237890Stuexen	case SCTP_NOTIFY_REMOTE_ERROR:
3690237890Stuexen		sctp_notify_remote_error(stcb, error, data);
3691237890Stuexen		break;
3692163953Srrs	default:
3693169420Srrs		SCTPDBG(SCTP_DEBUG_UTIL1, "%s: unknown notification %xh (%u)\n",
3694169420Srrs		    __FUNCTION__, notification, notification);
3695163953Srrs		break;
3696163953Srrs	}			/* end switch */
3697163953Srrs}
3698163953Srrs
3699163953Srrsvoid
3700237889Stuexensctp_report_all_outbound(struct sctp_tcb *stcb, uint16_t error, int holds_lock, int so_locked
3701172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
3702172090Srrs    SCTP_UNUSED
3703172090Srrs#endif
3704172090Srrs)
3705163953Srrs{
3706163953Srrs	struct sctp_association *asoc;
3707163953Srrs	struct sctp_stream_out *outs;
3708216822Stuexen	struct sctp_tmit_chunk *chk, *nchk;
3709216822Stuexen	struct sctp_stream_queue_pending *sp, *nsp;
3710164205Srrs	int i;
3711163953Srrs
3712169420Srrs	if (stcb == NULL) {
3713169420Srrs		return;
3714169420Srrs	}
3715216822Stuexen	asoc = &stcb->asoc;
3716216822Stuexen	if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
3717209663Srrs		/* already being freed */
3718209663Srrs		return;
3719209663Srrs	}
3720163953Srrs	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
3721163953Srrs	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
3722216822Stuexen	    (asoc->state & SCTP_STATE_CLOSED_SOCKET)) {
3723163953Srrs		return;
3724163953Srrs	}
3725163953Srrs	/* now through all the gunk freeing chunks */
3726169420Srrs	if (holds_lock == 0) {
3727164205Srrs		SCTP_TCB_SEND_LOCK(stcb);
3728169420Srrs	}
3729170462Srrs	/* sent queue SHOULD be empty */
3730216822Stuexen	TAILQ_FOREACH_SAFE(chk, &asoc->sent_queue, sctp_next, nchk) {
3731216822Stuexen		TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
3732216822Stuexen		asoc->sent_queue_cnt--;
3733252943Stuexen		if (chk->sent != SCTP_DATAGRAM_NR_ACKED) {
3734252942Stuexen			if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
3735252942Stuexen				asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
3736252942Stuexen#ifdef INVARIANTS
3737252942Stuexen			} else {
3738252942Stuexen				panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
3739252942Stuexen#endif
3740252942Stuexen			}
3741252942Stuexen		}
3742216822Stuexen		if (chk->data != NULL) {
3743216822Stuexen			sctp_free_bufspace(stcb, asoc, chk, 1);
3744237889Stuexen			sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb,
3745237889Stuexen			    error, chk, so_locked);
3746216822Stuexen			if (chk->data) {
3747216822Stuexen				sctp_m_freem(chk->data);
3748216822Stuexen				chk->data = NULL;
3749163953Srrs			}
3750163953Srrs		}
3751221627Stuexen		sctp_free_a_chunk(stcb, chk, so_locked);
3752216822Stuexen		/* sa_ignore FREED_MEMORY */
3753163953Srrs	}
3754170462Srrs	/* pending send queue SHOULD be empty */
3755216822Stuexen	TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
3756216822Stuexen		TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
3757216822Stuexen		asoc->send_queue_cnt--;
3758252942Stuexen		if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
3759252942Stuexen			asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
3760252942Stuexen#ifdef INVARIANTS
3761252942Stuexen		} else {
3762252942Stuexen			panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
3763252942Stuexen#endif
3764252942Stuexen		}
3765216822Stuexen		if (chk->data != NULL) {
3766216822Stuexen			sctp_free_bufspace(stcb, asoc, chk, 1);
3767237889Stuexen			sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb,
3768237889Stuexen			    error, chk, so_locked);
3769216822Stuexen			if (chk->data) {
3770216822Stuexen				sctp_m_freem(chk->data);
3771216822Stuexen				chk->data = NULL;
3772163953Srrs			}
3773163953Srrs		}
3774221627Stuexen		sctp_free_a_chunk(stcb, chk, so_locked);
3775216822Stuexen		/* sa_ignore FREED_MEMORY */
3776163953Srrs	}
3777216822Stuexen	for (i = 0; i < asoc->streamoutcnt; i++) {
3778170462Srrs		/* For each stream */
3779216822Stuexen		outs = &asoc->strmout[i];
3780170462Srrs		/* clean up any sends there */
3781216822Stuexen		asoc->locked_on_sending = NULL;
3782216822Stuexen		TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
3783216822Stuexen			asoc->stream_queue_cnt--;
3784170462Srrs			TAILQ_REMOVE(&outs->outqueue, sp, next);
3785170462Srrs			sctp_free_spbufspace(stcb, asoc, sp);
3786170462Srrs			if (sp->data) {
3787209663Srrs				sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL, stcb,
3788237889Stuexen				    error, (void *)sp, so_locked);
3789209663Srrs				if (sp->data) {
3790209663Srrs					sctp_m_freem(sp->data);
3791209663Srrs					sp->data = NULL;
3792238655Stuexen					sp->tail_mbuf = NULL;
3793238655Stuexen					sp->length = 0;
3794209663Srrs				}
3795170462Srrs			}
3796212712Stuexen			if (sp->net) {
3797170462Srrs				sctp_free_remote_addr(sp->net);
3798212712Stuexen				sp->net = NULL;
3799212712Stuexen			}
3800170462Srrs			/* Free the chunk */
3801221627Stuexen			sctp_free_a_strmoq(stcb, sp, so_locked);
3802170462Srrs			/* sa_ignore FREED_MEMORY */
3803170462Srrs		}
3804170462Srrs	}
3805170462Srrs
3806169420Srrs	if (holds_lock == 0) {
3807164205Srrs		SCTP_TCB_SEND_UNLOCK(stcb);
3808169420Srrs	}
3809163953Srrs}
3810163953Srrs
3811163953Srrsvoid
3812237886Stuexensctp_abort_notification(struct sctp_tcb *stcb, uint8_t from_peer, uint16_t error,
3813237884Stuexen    struct sctp_abort_chunk *abort, int so_locked
3814172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
3815172090Srrs    SCTP_UNUSED
3816172090Srrs#endif
3817172090Srrs)
3818163953Srrs{
3819169420Srrs	if (stcb == NULL) {
3820169420Srrs		return;
3821169420Srrs	}
3822225559Stuexen	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3823225559Stuexen	    ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
3824225559Stuexen	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
3825225559Stuexen		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_WAS_ABORTED;
3826225559Stuexen	}
3827163953Srrs	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
3828163953Srrs	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
3829163953Srrs	    (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
3830163953Srrs		return;
3831163953Srrs	}
3832163953Srrs	/* Tell them we lost the asoc */
3833237889Stuexen	sctp_report_all_outbound(stcb, error, 1, so_locked);
3834237886Stuexen	if (from_peer) {
3835237886Stuexen		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked);
3836237886Stuexen	} else {
3837237886Stuexen		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_LOC_ABORTED, stcb, error, abort, so_locked);
3838237886Stuexen	}
3839163953Srrs}
3840163953Srrs
3841163953Srrsvoid
3842163953Srrssctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
3843252889Stuexen    struct mbuf *m, int iphlen,
3844252889Stuexen    struct sockaddr *src, struct sockaddr *dst,
3845252889Stuexen    struct sctphdr *sh, struct mbuf *op_err,
3846238253Stuexen    uint8_t use_mflowid, uint32_t mflowid,
3847179157Srrs    uint32_t vrf_id, uint16_t port)
3848163953Srrs{
3849163953Srrs	uint32_t vtag;
3850163953Srrs
3851252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3852172090Srrs	struct socket *so;
3853172090Srrs
3854172090Srrs#endif
3855172090Srrs
3856163953Srrs	vtag = 0;
3857163953Srrs	if (stcb != NULL) {
3858163953Srrs		/* We have a TCB to abort, send notification too */
3859163953Srrs		vtag = stcb->asoc.peer_vtag;
3860237886Stuexen		sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
3861169352Srrs		/* get the assoc vrf id and table id */
3862169352Srrs		vrf_id = stcb->asoc.vrf_id;
3863171745Srrs		stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
3864163953Srrs	}
3865252889Stuexen	sctp_send_abort(m, iphlen, src, dst, sh, vtag, op_err,
3866238253Stuexen	    use_mflowid, mflowid,
3867238253Stuexen	    vrf_id, port);
3868163953Srrs	if (stcb != NULL) {
3869163953Srrs		/* Ok, now lets free it */
3870252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3871172090Srrs		so = SCTP_INP_SO(inp);
3872172090Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
3873172090Srrs		SCTP_TCB_UNLOCK(stcb);
3874172090Srrs		SCTP_SOCKET_LOCK(so, 1);
3875172090Srrs		SCTP_TCB_LOCK(stcb);
3876172090Srrs		atomic_subtract_int(&stcb->asoc.refcnt, 1);
3877172090Srrs#endif
3878216397Stuexen		SCTP_STAT_INCR_COUNTER32(sctps_aborted);
3879216397Stuexen		if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
3880216397Stuexen		    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
3881216397Stuexen			SCTP_STAT_DECR_GAUGE32(sctps_currestab);
3882216397Stuexen		}
3883171943Srrs		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_4);
3884252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3885172090Srrs		SCTP_SOCKET_UNLOCK(so, 1);
3886172090Srrs#endif
3887163953Srrs	}
3888163953Srrs}
3889163953Srrs
3890168859Srrs#ifdef SCTP_ASOCLOG_OF_TSNS
3891163953Srrsvoid
3892168859Srrssctp_print_out_track_log(struct sctp_tcb *stcb)
3893168859Srrs{
3894171477Srrs#ifdef NOSIY_PRINTS
3895168859Srrs	int i;
3896168859Srrs
3897169420Srrs	SCTP_PRINTF("Last ep reason:%x\n", stcb->sctp_ep->last_abort_code);
3898169420Srrs	SCTP_PRINTF("IN bound TSN log-aaa\n");
3899168859Srrs	if ((stcb->asoc.tsn_in_at == 0) && (stcb->asoc.tsn_in_wrapped == 0)) {
3900169420Srrs		SCTP_PRINTF("None rcvd\n");
3901168859Srrs		goto none_in;
3902168859Srrs	}
3903168859Srrs	if (stcb->asoc.tsn_in_wrapped) {
3904168859Srrs		for (i = stcb->asoc.tsn_in_at; i < SCTP_TSN_LOG_SIZE; i++) {
3905169420Srrs			SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
3906168859Srrs			    stcb->asoc.in_tsnlog[i].tsn,
3907168859Srrs			    stcb->asoc.in_tsnlog[i].strm,
3908168859Srrs			    stcb->asoc.in_tsnlog[i].seq,
3909168859Srrs			    stcb->asoc.in_tsnlog[i].flgs,
3910168859Srrs			    stcb->asoc.in_tsnlog[i].sz);
3911168859Srrs		}
3912168859Srrs	}
3913168859Srrs	if (stcb->asoc.tsn_in_at) {
3914168859Srrs		for (i = 0; i < stcb->asoc.tsn_in_at; i++) {
3915169420Srrs			SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
3916168859Srrs			    stcb->asoc.in_tsnlog[i].tsn,
3917168859Srrs			    stcb->asoc.in_tsnlog[i].strm,
3918168859Srrs			    stcb->asoc.in_tsnlog[i].seq,
3919168859Srrs			    stcb->asoc.in_tsnlog[i].flgs,
3920168859Srrs			    stcb->asoc.in_tsnlog[i].sz);
3921168859Srrs		}
3922168859Srrs	}
3923168859Srrsnone_in:
3924169420Srrs	SCTP_PRINTF("OUT bound TSN log-aaa\n");
3925169420Srrs	if ((stcb->asoc.tsn_out_at == 0) &&
3926169420Srrs	    (stcb->asoc.tsn_out_wrapped == 0)) {
3927169420Srrs		SCTP_PRINTF("None sent\n");
3928168859Srrs	}
3929168859Srrs	if (stcb->asoc.tsn_out_wrapped) {
3930168859Srrs		for (i = stcb->asoc.tsn_out_at; i < SCTP_TSN_LOG_SIZE; i++) {
3931169420Srrs			SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
3932168859Srrs			    stcb->asoc.out_tsnlog[i].tsn,
3933168859Srrs			    stcb->asoc.out_tsnlog[i].strm,
3934168859Srrs			    stcb->asoc.out_tsnlog[i].seq,
3935168859Srrs			    stcb->asoc.out_tsnlog[i].flgs,
3936168859Srrs			    stcb->asoc.out_tsnlog[i].sz);
3937168859Srrs		}
3938168859Srrs	}
3939168859Srrs	if (stcb->asoc.tsn_out_at) {
3940168859Srrs		for (i = 0; i < stcb->asoc.tsn_out_at; i++) {
3941169420Srrs			SCTP_PRINTF("TSN:%x strm:%d seq:%d flags:%x sz:%d\n",
3942168859Srrs			    stcb->asoc.out_tsnlog[i].tsn,
3943168859Srrs			    stcb->asoc.out_tsnlog[i].strm,
3944168859Srrs			    stcb->asoc.out_tsnlog[i].seq,
3945168859Srrs			    stcb->asoc.out_tsnlog[i].flgs,
3946168859Srrs			    stcb->asoc.out_tsnlog[i].sz);
3947168859Srrs		}
3948168859Srrs	}
3949171477Srrs#endif
3950168859Srrs}
3951168859Srrs
3952168859Srrs#endif
3953168859Srrs
3954168859Srrsvoid
3955163953Srrssctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
3956237884Stuexen    struct mbuf *op_err,
3957172090Srrs    int so_locked
3958172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
3959172090Srrs    SCTP_UNUSED
3960172090Srrs#endif
3961172090Srrs)
3962163953Srrs{
3963252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3964172090Srrs	struct socket *so;
3965172090Srrs
3966172090Srrs#endif
3967172090Srrs
3968252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3969172090Srrs	so = SCTP_INP_SO(inp);
3970172090Srrs#endif
3971163953Srrs	if (stcb == NULL) {
3972163953Srrs		/* Got to have a TCB */
3973163953Srrs		if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
3974252975Stuexen			if (LIST_EMPTY(&inp->sctp_asoc_list)) {
3975169380Srrs				sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
3976169380Srrs				    SCTP_CALLED_DIRECTLY_NOCMPSET);
3977163953Srrs			}
3978163953Srrs		}
3979163953Srrs		return;
3980171745Srrs	} else {
3981171745Srrs		stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
3982163953Srrs	}
3983163953Srrs	/* notify the ulp */
3984237884Stuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
3985237886Stuexen		sctp_abort_notification(stcb, 0, 0, NULL, so_locked);
3986237884Stuexen	}
3987163953Srrs	/* notify the peer */
3988172090Srrs	sctp_send_abort_tcb(stcb, op_err, so_locked);
3989163953Srrs	SCTP_STAT_INCR_COUNTER32(sctps_aborted);
3990163953Srrs	if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
3991163953Srrs	    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
3992163953Srrs		SCTP_STAT_DECR_GAUGE32(sctps_currestab);
3993163953Srrs	}
3994163953Srrs	/* now free the asoc */
3995168859Srrs#ifdef SCTP_ASOCLOG_OF_TSNS
3996168859Srrs	sctp_print_out_track_log(stcb);
3997168859Srrs#endif
3998252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3999172090Srrs	if (!so_locked) {
4000172090Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
4001172090Srrs		SCTP_TCB_UNLOCK(stcb);
4002172090Srrs		SCTP_SOCKET_LOCK(so, 1);
4003172090Srrs		SCTP_TCB_LOCK(stcb);
4004172090Srrs		atomic_subtract_int(&stcb->asoc.refcnt, 1);
4005172090Srrs	}
4006172090Srrs#endif
4007171943Srrs	(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTPUTIL + SCTP_LOC_5);
4008252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4009172090Srrs	if (!so_locked) {
4010172090Srrs		SCTP_SOCKET_UNLOCK(so, 1);
4011172090Srrs	}
4012172090Srrs#endif
4013163953Srrs}
4014163953Srrs
4015163953Srrsvoid
4016252889Stuexensctp_handle_ootb(struct mbuf *m, int iphlen, int offset,
4017252889Stuexen    struct sockaddr *src, struct sockaddr *dst,
4018252889Stuexen    struct sctphdr *sh, struct sctp_inpcb *inp,
4019266181Stuexen    struct mbuf *cause,
4020238253Stuexen    uint8_t use_mflowid, uint32_t mflowid,
4021238253Stuexen    uint32_t vrf_id, uint16_t port)
4022163953Srrs{
4023163953Srrs	struct sctp_chunkhdr *ch, chunk_buf;
4024163953Srrs	unsigned int chk_length;
4025231045Stuexen	int contains_init_chunk;
4026163953Srrs
4027163953Srrs	SCTP_STAT_INCR_COUNTER32(sctps_outoftheblue);
4028163953Srrs	/* Generate a TO address for future reference */
4029163953Srrs	if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
4030252975Stuexen		if (LIST_EMPTY(&inp->sctp_asoc_list)) {
4031169380Srrs			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
4032169380Srrs			    SCTP_CALLED_DIRECTLY_NOCMPSET);
4033163953Srrs		}
4034163953Srrs	}
4035231045Stuexen	contains_init_chunk = 0;
4036163953Srrs	ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
4037163953Srrs	    sizeof(*ch), (uint8_t *) & chunk_buf);
4038163953Srrs	while (ch != NULL) {
4039163953Srrs		chk_length = ntohs(ch->chunk_length);
4040163953Srrs		if (chk_length < sizeof(*ch)) {
4041163953Srrs			/* break to abort land */
4042163953Srrs			break;
4043163953Srrs		}
4044163953Srrs		switch (ch->chunk_type) {
4045231045Stuexen		case SCTP_INIT:
4046231045Stuexen			contains_init_chunk = 1;
4047231045Stuexen			break;
4048163953Srrs		case SCTP_PACKET_DROPPED:
4049163953Srrs			/* we don't respond to pkt-dropped */
4050163953Srrs			return;
4051163953Srrs		case SCTP_ABORT_ASSOCIATION:
4052163953Srrs			/* we don't respond with an ABORT to an ABORT */
4053163953Srrs			return;
4054163953Srrs		case SCTP_SHUTDOWN_COMPLETE:
4055163953Srrs			/*
4056163953Srrs			 * we ignore it since we are not waiting for it and
4057163953Srrs			 * peer is gone
4058163953Srrs			 */
4059163953Srrs			return;
4060163953Srrs		case SCTP_SHUTDOWN_ACK:
4061252889Stuexen			sctp_send_shutdown_complete2(src, dst, sh,
4062238253Stuexen			    use_mflowid, mflowid,
4063238253Stuexen			    vrf_id, port);
4064163953Srrs			return;
4065163953Srrs		default:
4066163953Srrs			break;
4067163953Srrs		}
4068163953Srrs		offset += SCTP_SIZE32(chk_length);
4069163953Srrs		ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
4070163953Srrs		    sizeof(*ch), (uint8_t *) & chunk_buf);
4071163953Srrs	}
4072231045Stuexen	if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
4073231045Stuexen	    ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
4074231045Stuexen	    (contains_init_chunk == 0))) {
4075266181Stuexen		sctp_send_abort(m, iphlen, src, dst, sh, 0, cause,
4076238253Stuexen		    use_mflowid, mflowid,
4077238253Stuexen		    vrf_id, port);
4078231045Stuexen	}
4079163953Srrs}
4080163953Srrs
4081163953Srrs/*
4082163953Srrs * check the inbound datagram to make sure there is not an abort inside it,
4083163953Srrs * if there is return 1, else return 0.
4084163953Srrs */
4085163953Srrsint
4086163953Srrssctp_is_there_an_abort_here(struct mbuf *m, int iphlen, uint32_t * vtagfill)
4087163953Srrs{
4088163953Srrs	struct sctp_chunkhdr *ch;
4089163953Srrs	struct sctp_init_chunk *init_chk, chunk_buf;
4090163953Srrs	int offset;
4091163953Srrs	unsigned int chk_length;
4092163953Srrs
4093163953Srrs	offset = iphlen + sizeof(struct sctphdr);
4094163953Srrs	ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, sizeof(*ch),
4095163953Srrs	    (uint8_t *) & chunk_buf);
4096163953Srrs	while (ch != NULL) {
4097163953Srrs		chk_length = ntohs(ch->chunk_length);
4098163953Srrs		if (chk_length < sizeof(*ch)) {
4099163953Srrs			/* packet is probably corrupt */
4100163953Srrs			break;
4101163953Srrs		}
4102163953Srrs		/* we seem to be ok, is it an abort? */
4103163953Srrs		if (ch->chunk_type == SCTP_ABORT_ASSOCIATION) {
4104163953Srrs			/* yep, tell them */
4105163953Srrs			return (1);
4106163953Srrs		}
4107163953Srrs		if (ch->chunk_type == SCTP_INITIATION) {
4108163953Srrs			/* need to update the Vtag */
4109163953Srrs			init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
4110163953Srrs			    offset, sizeof(*init_chk), (uint8_t *) & chunk_buf);
4111163953Srrs			if (init_chk != NULL) {
4112163953Srrs				*vtagfill = ntohl(init_chk->init.initiate_tag);
4113163953Srrs			}
4114163953Srrs		}
4115163953Srrs		/* Nope, move to the next chunk */
4116163953Srrs		offset += SCTP_SIZE32(chk_length);
4117163953Srrs		ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
4118163953Srrs		    sizeof(*ch), (uint8_t *) & chunk_buf);
4119163953Srrs	}
4120163953Srrs	return (0);
4121163953Srrs}
4122163953Srrs
4123163953Srrs/*
4124163953Srrs * currently (2/02), ifa_addr embeds scope_id's and don't have sin6_scope_id
4125163953Srrs * set (i.e. it's 0) so, create this function to compare link local scopes
4126163953Srrs */
4127178251Srrs#ifdef INET6
4128163953Srrsuint32_t
4129163953Srrssctp_is_same_scope(struct sockaddr_in6 *addr1, struct sockaddr_in6 *addr2)
4130163953Srrs{
4131163953Srrs	struct sockaddr_in6 a, b;
4132163953Srrs
4133163953Srrs	/* save copies */
4134163953Srrs	a = *addr1;
4135163953Srrs	b = *addr2;
4136163953Srrs
4137163953Srrs	if (a.sin6_scope_id == 0)
4138163953Srrs		if (sa6_recoverscope(&a)) {
4139163953Srrs			/* can't get scope, so can't match */
4140163953Srrs			return (0);
4141163953Srrs		}
4142163953Srrs	if (b.sin6_scope_id == 0)
4143163953Srrs		if (sa6_recoverscope(&b)) {
4144163953Srrs			/* can't get scope, so can't match */
4145163953Srrs			return (0);
4146163953Srrs		}
4147163953Srrs	if (a.sin6_scope_id != b.sin6_scope_id)
4148163953Srrs		return (0);
4149163953Srrs
4150163953Srrs	return (1);
4151163953Srrs}
4152163953Srrs
4153163953Srrs/*
4154163953Srrs * returns a sockaddr_in6 with embedded scope recovered and removed
4155163953Srrs */
4156163953Srrsstruct sockaddr_in6 *
4157163953Srrssctp_recover_scope(struct sockaddr_in6 *addr, struct sockaddr_in6 *store)
4158163953Srrs{
4159163953Srrs	/* check and strip embedded scope junk */
4160163953Srrs	if (addr->sin6_family == AF_INET6) {
4161163953Srrs		if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) {
4162163953Srrs			if (addr->sin6_scope_id == 0) {
4163163953Srrs				*store = *addr;
4164163953Srrs				if (!sa6_recoverscope(store)) {
4165163953Srrs					/* use the recovered scope */
4166163953Srrs					addr = store;
4167163953Srrs				}
4168166675Srrs			} else {
4169163953Srrs				/* else, return the original "to" addr */
4170166675Srrs				in6_clearscope(&addr->sin6_addr);
4171163953Srrs			}
4172163953Srrs		}
4173163953Srrs	}
4174163953Srrs	return (addr);
4175163953Srrs}
4176163953Srrs
4177178251Srrs#endif
4178178251Srrs
4179163953Srrs/*
4180163953Srrs * are the two addresses the same?  currently a "scopeless" check returns: 1
4181163953Srrs * if same, 0 if not
4182163953Srrs */
4183170806Srrsint
4184163953Srrssctp_cmpaddr(struct sockaddr *sa1, struct sockaddr *sa2)
4185163953Srrs{
4186163953Srrs
4187163953Srrs	/* must be valid */
4188163953Srrs	if (sa1 == NULL || sa2 == NULL)
4189163953Srrs		return (0);
4190163953Srrs
4191163953Srrs	/* must be the same family */
4192163953Srrs	if (sa1->sa_family != sa2->sa_family)
4193163953Srrs		return (0);
4194163953Srrs
4195178251Srrs	switch (sa1->sa_family) {
4196178251Srrs#ifdef INET6
4197178251Srrs	case AF_INET6:
4198178251Srrs		{
4199178251Srrs			/* IPv6 addresses */
4200178251Srrs			struct sockaddr_in6 *sin6_1, *sin6_2;
4201163953Srrs
4202178251Srrs			sin6_1 = (struct sockaddr_in6 *)sa1;
4203178251Srrs			sin6_2 = (struct sockaddr_in6 *)sa2;
4204179157Srrs			return (SCTP6_ARE_ADDR_EQUAL(sin6_1,
4205179157Srrs			    sin6_2));
4206178251Srrs		}
4207178251Srrs#endif
4208221328Stuexen#ifdef INET
4209178251Srrs	case AF_INET:
4210178251Srrs		{
4211178251Srrs			/* IPv4 addresses */
4212178251Srrs			struct sockaddr_in *sin_1, *sin_2;
4213163953Srrs
4214178251Srrs			sin_1 = (struct sockaddr_in *)sa1;
4215178251Srrs			sin_2 = (struct sockaddr_in *)sa2;
4216178251Srrs			return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr);
4217178251Srrs		}
4218221328Stuexen#endif
4219178251Srrs	default:
4220163953Srrs		/* we don't do these... */
4221163953Srrs		return (0);
4222163953Srrs	}
4223163953Srrs}
4224163953Srrs
4225163953Srrsvoid
4226163953Srrssctp_print_address(struct sockaddr *sa)
4227163953Srrs{
4228178251Srrs#ifdef INET6
4229169420Srrs	char ip6buf[INET6_ADDRSTRLEN];
4230163953Srrs
4231178251Srrs#endif
4232163953Srrs
4233178251Srrs	switch (sa->sa_family) {
4234178251Srrs#ifdef INET6
4235178251Srrs	case AF_INET6:
4236178251Srrs		{
4237178251Srrs			struct sockaddr_in6 *sin6;
4238163953Srrs
4239178251Srrs			sin6 = (struct sockaddr_in6 *)sa;
4240178251Srrs			SCTP_PRINTF("IPv6 address: %s:port:%d scope:%u\n",
4241178251Srrs			    ip6_sprintf(ip6buf, &sin6->sin6_addr),
4242178251Srrs			    ntohs(sin6->sin6_port),
4243178251Srrs			    sin6->sin6_scope_id);
4244178251Srrs			break;
4245178251Srrs		}
4246178251Srrs#endif
4247221328Stuexen#ifdef INET
4248178251Srrs	case AF_INET:
4249178251Srrs		{
4250178251Srrs			struct sockaddr_in *sin;
4251178251Srrs			unsigned char *p;
4252178251Srrs
4253178251Srrs			sin = (struct sockaddr_in *)sa;
4254178251Srrs			p = (unsigned char *)&sin->sin_addr;
4255178251Srrs			SCTP_PRINTF("IPv4 address: %u.%u.%u.%u:%d\n",
4256178251Srrs			    p[0], p[1], p[2], p[3], ntohs(sin->sin_port));
4257178251Srrs			break;
4258178251Srrs		}
4259221328Stuexen#endif
4260178251Srrs	default:
4261169420Srrs		SCTP_PRINTF("?\n");
4262178251Srrs		break;
4263163953Srrs	}
4264163953Srrs}
4265163953Srrs
4266163953Srrsvoid
4267163953Srrssctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
4268163953Srrs    struct sctp_inpcb *new_inp,
4269169208Srrs    struct sctp_tcb *stcb,
4270169208Srrs    int waitflags)
4271163953Srrs{
4272163953Srrs	/*
4273163953Srrs	 * go through our old INP and pull off any control structures that
4274163953Srrs	 * belong to stcb and move then to the new inp.
4275163953Srrs	 */
4276163953Srrs	struct socket *old_so, *new_so;
4277163953Srrs	struct sctp_queued_to_read *control, *nctl;
4278163953Srrs	struct sctp_readhead tmp_queue;
4279163953Srrs	struct mbuf *m;
4280168299Srrs	int error = 0;
4281163953Srrs
4282163953Srrs	old_so = old_inp->sctp_socket;
4283163953Srrs	new_so = new_inp->sctp_socket;
4284163953Srrs	TAILQ_INIT(&tmp_queue);
4285169208Srrs	error = sblock(&old_so->so_rcv, waitflags);
4286163953Srrs	if (error) {
4287163953Srrs		/*
4288163953Srrs		 * Gak, can't get sblock, we have a problem. data will be
4289163953Srrs		 * left stranded.. and we don't dare look at it since the
4290163953Srrs		 * other thread may be reading something. Oh well, its a
4291163953Srrs		 * screwed up app that does a peeloff OR a accept while
4292163953Srrs		 * reading from the main socket... actually its only the
4293163953Srrs		 * peeloff() case, since I think read will fail on a
4294163953Srrs		 * listening socket..
4295163953Srrs		 */
4296163953Srrs		return;
4297163953Srrs	}
4298163953Srrs	/* lock the socket buffers */
4299163953Srrs	SCTP_INP_READ_LOCK(old_inp);
4300216822Stuexen	TAILQ_FOREACH_SAFE(control, &old_inp->read_queue, next, nctl) {
4301216822Stuexen		/* Pull off all for out target stcb */
4302163953Srrs		if (control->stcb == stcb) {
4303163953Srrs			/* remove it we want it */
4304163953Srrs			TAILQ_REMOVE(&old_inp->read_queue, control, next);
4305163953Srrs			TAILQ_INSERT_TAIL(&tmp_queue, control, next);
4306163953Srrs			m = control->data;
4307163953Srrs			while (m) {
4308179783Srrs				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
4309170744Srrs					sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m));
4310170744Srrs				}
4311163953Srrs				sctp_sbfree(control, stcb, &old_so->so_rcv, m);
4312179783Srrs				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
4313170744Srrs					sctp_sblog(&old_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0);
4314170744Srrs				}
4315165647Srrs				m = SCTP_BUF_NEXT(m);
4316163953Srrs			}
4317163953Srrs		}
4318163953Srrs	}
4319163953Srrs	SCTP_INP_READ_UNLOCK(old_inp);
4320163953Srrs	/* Remove the sb-lock on the old socket */
4321163953Srrs
4322163953Srrs	sbunlock(&old_so->so_rcv);
4323163953Srrs	/* Now we move them over to the new socket buffer */
4324163953Srrs	SCTP_INP_READ_LOCK(new_inp);
4325216822Stuexen	TAILQ_FOREACH_SAFE(control, &tmp_queue, next, nctl) {
4326163953Srrs		TAILQ_INSERT_TAIL(&new_inp->read_queue, control, next);
4327163953Srrs		m = control->data;
4328163953Srrs		while (m) {
4329179783Srrs			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
4330170744Srrs				sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m));
4331170744Srrs			}
4332163953Srrs			sctp_sballoc(stcb, &new_so->so_rcv, m);
4333179783Srrs			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
4334170744Srrs				sctp_sblog(&new_so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0);
4335170744Srrs			}
4336165647Srrs			m = SCTP_BUF_NEXT(m);
4337163953Srrs		}
4338163953Srrs	}
4339163953Srrs	SCTP_INP_READ_UNLOCK(new_inp);
4340163953Srrs}
4341163953Srrs
4342163953Srrsvoid
4343163953Srrssctp_add_to_readq(struct sctp_inpcb *inp,
4344163953Srrs    struct sctp_tcb *stcb,
4345163953Srrs    struct sctp_queued_to_read *control,
4346163953Srrs    struct sockbuf *sb,
4347172090Srrs    int end,
4348195918Srrs    int inp_read_lock_held,
4349172090Srrs    int so_locked
4350172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
4351172090Srrs    SCTP_UNUSED
4352172090Srrs#endif
4353172090Srrs)
4354163953Srrs{
4355163953Srrs	/*
4356163953Srrs	 * Here we must place the control on the end of the socket read
4357163953Srrs	 * queue AND increment sb_cc so that select will work properly on
4358163953Srrs	 * read.
4359163953Srrs	 */
4360163953Srrs	struct mbuf *m, *prev = NULL;
4361163953Srrs
4362164085Srrs	if (inp == NULL) {
4363164085Srrs		/* Gak, TSNH!! */
4364165220Srrs#ifdef INVARIANTS
4365164085Srrs		panic("Gak, inp NULL on add_to_readq");
4366164085Srrs#endif
4367164085Srrs		return;
4368164085Srrs	}
4369195918Srrs	if (inp_read_lock_held == 0)
4370195918Srrs		SCTP_INP_READ_LOCK(inp);
4371209289Stuexen	if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ) {
4372209289Stuexen		sctp_free_remote_addr(control->whoFrom);
4373209289Stuexen		if (control->data) {
4374209289Stuexen			sctp_m_freem(control->data);
4375209289Stuexen			control->data = NULL;
4376209289Stuexen		}
4377209289Stuexen		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
4378209289Stuexen		if (inp_read_lock_held == 0)
4379209289Stuexen			SCTP_INP_READ_UNLOCK(inp);
4380209289Stuexen		return;
4381209289Stuexen	}
4382167598Srrs	if (!(control->spec_flags & M_NOTIFICATION)) {
4383167598Srrs		atomic_add_int(&inp->total_recvs, 1);
4384167598Srrs		if (!control->do_not_ref_stcb) {
4385167598Srrs			atomic_add_int(&stcb->total_recvs, 1);
4386167598Srrs		}
4387167598Srrs	}
4388163953Srrs	m = control->data;
4389163953Srrs	control->held_length = 0;
4390163953Srrs	control->length = 0;
4391163953Srrs	while (m) {
4392165647Srrs		if (SCTP_BUF_LEN(m) == 0) {
4393163953Srrs			/* Skip mbufs with NO length */
4394163953Srrs			if (prev == NULL) {
4395163953Srrs				/* First one */
4396163953Srrs				control->data = sctp_m_free(m);
4397163953Srrs				m = control->data;
4398163953Srrs			} else {
4399165647Srrs				SCTP_BUF_NEXT(prev) = sctp_m_free(m);
4400165647Srrs				m = SCTP_BUF_NEXT(prev);
4401163953Srrs			}
4402163953Srrs			if (m == NULL) {
4403201758Smbr				control->tail_mbuf = prev;
4404163953Srrs			}
4405163953Srrs			continue;
4406163953Srrs		}
4407163953Srrs		prev = m;
4408179783Srrs		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
4409170744Srrs			sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(m));
4410170744Srrs		}
4411163953Srrs		sctp_sballoc(stcb, sb, m);
4412179783Srrs		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
4413170744Srrs			sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0);
4414170744Srrs		}
4415165647Srrs		atomic_add_int(&control->length, SCTP_BUF_LEN(m));
4416165647Srrs		m = SCTP_BUF_NEXT(m);
4417163953Srrs	}
4418163953Srrs	if (prev != NULL) {
4419163953Srrs		control->tail_mbuf = prev;
4420163953Srrs	} else {
4421165647Srrs		/* Everything got collapsed out?? */
4422209289Stuexen		sctp_free_remote_addr(control->whoFrom);
4423209289Stuexen		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
4424195918Srrs		if (inp_read_lock_held == 0)
4425195918Srrs			SCTP_INP_READ_UNLOCK(inp);
4426163953Srrs		return;
4427163953Srrs	}
4428163953Srrs	if (end) {
4429163953Srrs		control->end_added = 1;
4430163953Srrs	}
4431163953Srrs	TAILQ_INSERT_TAIL(&inp->read_queue, control, next);
4432195918Srrs	if (inp_read_lock_held == 0)
4433195918Srrs		SCTP_INP_READ_UNLOCK(inp);
4434163953Srrs	if (inp && inp->sctp_socket) {
4435169352Srrs		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
4436169352Srrs			SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
4437172090Srrs		} else {
4438252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4439172090Srrs			struct socket *so;
4440172090Srrs
4441172090Srrs			so = SCTP_INP_SO(inp);
4442172090Srrs			if (!so_locked) {
4443231039Stuexen				if (stcb) {
4444231039Stuexen					atomic_add_int(&stcb->asoc.refcnt, 1);
4445231039Stuexen					SCTP_TCB_UNLOCK(stcb);
4446231039Stuexen				}
4447172090Srrs				SCTP_SOCKET_LOCK(so, 1);
4448231039Stuexen				if (stcb) {
4449231039Stuexen					SCTP_TCB_LOCK(stcb);
4450231039Stuexen					atomic_subtract_int(&stcb->asoc.refcnt, 1);
4451231039Stuexen				}
4452172090Srrs				if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
4453172090Srrs					SCTP_SOCKET_UNLOCK(so, 1);
4454172090Srrs					return;
4455172090Srrs				}
4456172090Srrs			}
4457172090Srrs#endif
4458169352Srrs			sctp_sorwakeup(inp, inp->sctp_socket);
4459252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4460172090Srrs			if (!so_locked) {
4461172090Srrs				SCTP_SOCKET_UNLOCK(so, 1);
4462172090Srrs			}
4463172090Srrs#endif
4464172090Srrs		}
4465163953Srrs	}
4466163953Srrs}
4467163953Srrs
4468163953Srrs
4469163953Srrsint
4470163953Srrssctp_append_to_readq(struct sctp_inpcb *inp,
4471163953Srrs    struct sctp_tcb *stcb,
4472163953Srrs    struct sctp_queued_to_read *control,
4473163953Srrs    struct mbuf *m,
4474163953Srrs    int end,
4475163953Srrs    int ctls_cumack,
4476163953Srrs    struct sockbuf *sb)
4477163953Srrs{
4478163953Srrs	/*
4479163953Srrs	 * A partial delivery API event is underway. OR we are appending on
4480163953Srrs	 * the reassembly queue.
4481163953Srrs	 *
4482163953Srrs	 * If PDAPI this means we need to add m to the end of the data.
4483163953Srrs	 * Increase the length in the control AND increment the sb_cc.
4484163953Srrs	 * Otherwise sb is NULL and all we need to do is put it at the end
4485163953Srrs	 * of the mbuf chain.
4486163953Srrs	 */
4487163953Srrs	int len = 0;
4488163953Srrs	struct mbuf *mm, *tail = NULL, *prev = NULL;
4489163953Srrs
4490163953Srrs	if (inp) {
4491163953Srrs		SCTP_INP_READ_LOCK(inp);
4492163953Srrs	}
4493163953Srrs	if (control == NULL) {
4494163953Srrsget_out:
4495163953Srrs		if (inp) {
4496163953Srrs			SCTP_INP_READ_UNLOCK(inp);
4497163953Srrs		}
4498163953Srrs		return (-1);
4499163953Srrs	}
4500209289Stuexen	if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_CANT_READ)) {
4501209289Stuexen		SCTP_INP_READ_UNLOCK(inp);
4502231039Stuexen		return (0);
4503209289Stuexen	}
4504165647Srrs	if (control->end_added) {
4505163953Srrs		/* huh this one is complete? */
4506163953Srrs		goto get_out;
4507163953Srrs	}
4508163953Srrs	mm = m;
4509163953Srrs	if (mm == NULL) {
4510163953Srrs		goto get_out;
4511163953Srrs	}
4512163953Srrs	while (mm) {
4513165647Srrs		if (SCTP_BUF_LEN(mm) == 0) {
4514163953Srrs			/* Skip mbufs with NO lenght */
4515163953Srrs			if (prev == NULL) {
4516163953Srrs				/* First one */
4517163953Srrs				m = sctp_m_free(mm);
4518163953Srrs				mm = m;
4519163953Srrs			} else {
4520165647Srrs				SCTP_BUF_NEXT(prev) = sctp_m_free(mm);
4521165647Srrs				mm = SCTP_BUF_NEXT(prev);
4522163953Srrs			}
4523163953Srrs			continue;
4524163953Srrs		}
4525163953Srrs		prev = mm;
4526165647Srrs		len += SCTP_BUF_LEN(mm);
4527163953Srrs		if (sb) {
4528179783Srrs			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
4529170744Srrs				sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBALLOC, SCTP_BUF_LEN(mm));
4530170744Srrs			}
4531163953Srrs			sctp_sballoc(stcb, sb, mm);
4532179783Srrs			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
4533170744Srrs				sctp_sblog(sb, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0);
4534170744Srrs			}
4535163953Srrs		}
4536165647Srrs		mm = SCTP_BUF_NEXT(mm);
4537163953Srrs	}
4538163953Srrs	if (prev) {
4539163953Srrs		tail = prev;
4540163953Srrs	} else {
4541163953Srrs		/* Really there should always be a prev */
4542163953Srrs		if (m == NULL) {
4543163953Srrs			/* Huh nothing left? */
4544165220Srrs#ifdef INVARIANTS
4545163953Srrs			panic("Nothing left to add?");
4546163953Srrs#else
4547163953Srrs			goto get_out;
4548163953Srrs#endif
4549163953Srrs		}
4550163953Srrs		tail = m;
4551163953Srrs	}
4552163953Srrs	if (control->tail_mbuf) {
4553163953Srrs		/* append */
4554165647Srrs		SCTP_BUF_NEXT(control->tail_mbuf) = m;
4555163953Srrs		control->tail_mbuf = tail;
4556163953Srrs	} else {
4557163953Srrs		/* nothing there */
4558165220Srrs#ifdef INVARIANTS
4559163953Srrs		if (control->data != NULL) {
4560163953Srrs			panic("This should NOT happen");
4561163953Srrs		}
4562163953Srrs#endif
4563163953Srrs		control->data = m;
4564163953Srrs		control->tail_mbuf = tail;
4565163953Srrs	}
4566171477Srrs	atomic_add_int(&control->length, len);
4567171477Srrs	if (end) {
4568171477Srrs		/* message is complete */
4569171477Srrs		if (stcb && (control == stcb->asoc.control_pdapi)) {
4570171477Srrs			stcb->asoc.control_pdapi = NULL;
4571171477Srrs		}
4572171477Srrs		control->held_length = 0;
4573171477Srrs		control->end_added = 1;
4574171477Srrs	}
4575169420Srrs	if (stcb == NULL) {
4576169420Srrs		control->do_not_ref_stcb = 1;
4577169420Srrs	}
4578163953Srrs	/*
4579163953Srrs	 * When we are appending in partial delivery, the cum-ack is used
4580163953Srrs	 * for the actual pd-api highest tsn on this mbuf. The true cum-ack
4581163953Srrs	 * is populated in the outbound sinfo structure from the true cumack
4582163953Srrs	 * if the association exists...
4583163953Srrs	 */
4584163953Srrs	control->sinfo_tsn = control->sinfo_cumtsn = ctls_cumack;
4585163953Srrs	if (inp) {
4586163953Srrs		SCTP_INP_READ_UNLOCK(inp);
4587163953Srrs	}
4588163953Srrs	if (inp && inp->sctp_socket) {
4589169352Srrs		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
4590169352Srrs			SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
4591172090Srrs		} else {
4592252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4593172090Srrs			struct socket *so;
4594172090Srrs
4595172090Srrs			so = SCTP_INP_SO(inp);
4596231039Stuexen			if (stcb) {
4597231039Stuexen				atomic_add_int(&stcb->asoc.refcnt, 1);
4598231039Stuexen				SCTP_TCB_UNLOCK(stcb);
4599231039Stuexen			}
4600172090Srrs			SCTP_SOCKET_LOCK(so, 1);
4601231039Stuexen			if (stcb) {
4602231039Stuexen				SCTP_TCB_LOCK(stcb);
4603231039Stuexen				atomic_subtract_int(&stcb->asoc.refcnt, 1);
4604231039Stuexen			}
4605172090Srrs			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
4606172090Srrs				SCTP_SOCKET_UNLOCK(so, 1);
4607172090Srrs				return (0);
4608172090Srrs			}
4609172090Srrs#endif
4610169352Srrs			sctp_sorwakeup(inp, inp->sctp_socket);
4611252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4612172090Srrs			SCTP_SOCKET_UNLOCK(so, 1);
4613172090Srrs#endif
4614172090Srrs		}
4615163953Srrs	}
4616163953Srrs	return (0);
4617163953Srrs}
4618163953Srrs
4619163953Srrs
4620163953Srrs
4621163953Srrs/*************HOLD THIS COMMENT FOR PATCH FILE OF
4622163953Srrs *************ALTERNATE ROUTING CODE
4623163953Srrs */
4624163953Srrs
4625163953Srrs/*************HOLD THIS COMMENT FOR END OF PATCH FILE OF
4626163953Srrs *************ALTERNATE ROUTING CODE
4627163953Srrs */
4628163953Srrs
4629163953Srrsstruct mbuf *
4630266181Stuexensctp_generate_cause(uint16_t code, char *info)
4631163953Srrs{
4632163953Srrs	struct mbuf *m;
4633266181Stuexen	struct sctp_gen_error_cause *cause;
4634266181Stuexen	size_t info_len, len;
4635163953Srrs
4636266181Stuexen	if ((code == 0) || (info == NULL)) {
4637266181Stuexen		return (NULL);
4638163953Srrs	}
4639266181Stuexen	info_len = strlen(info);
4640266181Stuexen	len = sizeof(struct sctp_paramhdr) + info_len;
4641266181Stuexen	m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
4642266181Stuexen	if (m != NULL) {
4643266181Stuexen		SCTP_BUF_LEN(m) = len;
4644266181Stuexen		cause = mtod(m, struct sctp_gen_error_cause *);
4645266181Stuexen		cause->code = htons(code);
4646266181Stuexen		cause->length = htons((uint16_t) len);
4647266181Stuexen		memcpy(cause->info, info, info_len);
4648266181Stuexen	}
4649163953Srrs	return (m);
4650163953Srrs}
4651163953Srrs
4652266186Stuexenstruct mbuf *
4653266186Stuexensctp_generate_no_user_data_cause(uint32_t tsn)
4654266186Stuexen{
4655266186Stuexen	struct mbuf *m;
4656266186Stuexen	struct sctp_error_no_user_data *no_user_data_cause;
4657266186Stuexen	size_t len;
4658266186Stuexen
4659266186Stuexen	len = sizeof(struct sctp_error_no_user_data);
4660266186Stuexen	m = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
4661266186Stuexen	if (m != NULL) {
4662266186Stuexen		SCTP_BUF_LEN(m) = len;
4663266186Stuexen		no_user_data_cause = mtod(m, struct sctp_error_no_user_data *);
4664266186Stuexen		no_user_data_cause->cause.code = htons(SCTP_CAUSE_NO_USER_DATA);
4665266186Stuexen		no_user_data_cause->cause.length = htons((uint16_t) len);
4666266186Stuexen		no_user_data_cause->tsn = tsn;	/* tsn is passed in as NBO */
4667266186Stuexen	}
4668266186Stuexen	return (m);
4669266186Stuexen}
4670266186Stuexen
4671163953Srrs#ifdef SCTP_MBCNT_LOGGING
4672163953Srrsvoid
4673163953Srrssctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
4674163953Srrs    struct sctp_tmit_chunk *tp1, int chk_cnt)
4675163953Srrs{
4676163953Srrs	if (tp1->data == NULL) {
4677163953Srrs		return;
4678163953Srrs	}
4679163953Srrs	asoc->chunks_on_out_queue -= chk_cnt;
4680179783Srrs	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBCNT_LOGGING_ENABLE) {
4681170744Srrs		sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE,
4682170744Srrs		    asoc->total_output_queue_size,
4683170744Srrs		    tp1->book_size,
4684170744Srrs		    0,
4685170744Srrs		    tp1->mbcnt);
4686170744Srrs	}
4687163953Srrs	if (asoc->total_output_queue_size >= tp1->book_size) {
4688166023Srrs		atomic_add_int(&asoc->total_output_queue_size, -tp1->book_size);
4689163953Srrs	} else {
4690163953Srrs		asoc->total_output_queue_size = 0;
4691163953Srrs	}
4692163953Srrs
4693163953Srrs	if (stcb->sctp_socket && (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) ||
4694163953Srrs	    ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE)))) {
4695163953Srrs		if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) {
4696163953Srrs			stcb->sctp_socket->so_snd.sb_cc -= tp1->book_size;
4697163953Srrs		} else {
4698163953Srrs			stcb->sctp_socket->so_snd.sb_cc = 0;
4699163953Srrs
4700163953Srrs		}
4701163953Srrs	}
4702163953Srrs}
4703163953Srrs
4704163953Srrs#endif
4705163953Srrs
4706163953Srrsint
4707163953Srrssctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
4708237889Stuexen    uint8_t sent, int so_locked
4709172090Srrs#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
4710172090Srrs    SCTP_UNUSED
4711172090Srrs#endif
4712172090Srrs)
4713163953Srrs{
4714189790Srrs	struct sctp_stream_out *strq;
4715216822Stuexen	struct sctp_tmit_chunk *chk = NULL, *tp2;
4716189790Srrs	struct sctp_stream_queue_pending *sp;
4717189790Srrs	uint16_t stream = 0, seq = 0;
4718189790Srrs	uint8_t foundeom = 0;
4719163953Srrs	int ret_sz = 0;
4720163953Srrs	int notdone;
4721189790Srrs	int do_wakeup_routine = 0;
4722163953Srrs
4723189790Srrs	stream = tp1->rec.data.stream_number;
4724189790Srrs	seq = tp1->rec.data.stream_seq;
4725163953Srrs	do {
4726163953Srrs		ret_sz += tp1->book_size;
4727189790Srrs		if (tp1->data != NULL) {
4728190689Srrs			if (tp1->sent < SCTP_DATAGRAM_RESEND) {
4729190689Srrs				sctp_flight_size_decrease(tp1);
4730190689Srrs				sctp_total_flight_decrease(stcb, tp1);
4731190689Srrs			}
4732163953Srrs			sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
4733189790Srrs			stcb->asoc.peers_rwnd += tp1->send_size;
4734189790Srrs			stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh);
4735237889Stuexen			if (sent) {
4736237889Stuexen				sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked);
4737237889Stuexen			} else {
4738237889Stuexen				sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked);
4739237889Stuexen			}
4740196376Stuexen			if (tp1->data) {
4741196376Stuexen				sctp_m_freem(tp1->data);
4742196376Stuexen				tp1->data = NULL;
4743196376Stuexen			}
4744189790Srrs			do_wakeup_routine = 1;
4745189790Srrs			if (PR_SCTP_BUF_ENABLED(tp1->flags)) {
4746189790Srrs				stcb->asoc.sent_queue_cnt_removeable--;
4747172090Srrs			}
4748163953Srrs		}
4749190689Srrs		tp1->sent = SCTP_FORWARD_TSN_SKIP;
4750163953Srrs		if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) ==
4751163953Srrs		    SCTP_DATA_NOT_FRAG) {
4752163953Srrs			/* not frag'ed we ae done   */
4753163953Srrs			notdone = 0;
4754163953Srrs			foundeom = 1;
4755163953Srrs		} else if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
4756163953Srrs			/* end of frag, we are done */
4757163953Srrs			notdone = 0;
4758163953Srrs			foundeom = 1;
4759163953Srrs		} else {
4760163953Srrs			/*
4761163953Srrs			 * Its a begin or middle piece, we must mark all of
4762163953Srrs			 * it
4763163953Srrs			 */
4764163953Srrs			notdone = 1;
4765163953Srrs			tp1 = TAILQ_NEXT(tp1, sctp_next);
4766163953Srrs		}
4767163953Srrs	} while (tp1 && notdone);
4768189790Srrs	if (foundeom == 0) {
4769163953Srrs		/*
4770163953Srrs		 * The multi-part message was scattered across the send and
4771163953Srrs		 * sent queue.
4772163953Srrs		 */
4773216822Stuexen		TAILQ_FOREACH_SAFE(tp1, &stcb->asoc.send_queue, sctp_next, tp2) {
4774216822Stuexen			if ((tp1->rec.data.stream_number != stream) ||
4775216822Stuexen			    (tp1->rec.data.stream_seq != seq)) {
4776216822Stuexen				break;
4777216822Stuexen			}
4778189790Srrs			/*
4779189790Srrs			 * save to chk in case we have some on stream out
4780189790Srrs			 * queue. If so and we have an un-transmitted one we
4781189790Srrs			 * don't have to fudge the TSN.
4782189790Srrs			 */
4783189790Srrs			chk = tp1;
4784189790Srrs			ret_sz += tp1->book_size;
4785196376Stuexen			sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
4786237889Stuexen			if (sent) {
4787237889Stuexen				sctp_ulp_notify(SCTP_NOTIFY_SENT_DG_FAIL, stcb, 0, tp1, so_locked);
4788237889Stuexen			} else {
4789237889Stuexen				sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb, 0, tp1, so_locked);
4790237889Stuexen			}
4791196376Stuexen			if (tp1->data) {
4792196376Stuexen				sctp_m_freem(tp1->data);
4793196376Stuexen				tp1->data = NULL;
4794196376Stuexen			}
4795190689Srrs			/* No flight involved here book the size to 0 */
4796190689Srrs			tp1->book_size = 0;
4797189790Srrs			if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
4798189790Srrs				foundeom = 1;
4799189790Srrs			}
4800189790Srrs			do_wakeup_routine = 1;
4801189790Srrs			tp1->sent = SCTP_FORWARD_TSN_SKIP;
4802189790Srrs			TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next);
4803189790Srrs			/*
4804189790Srrs			 * on to the sent queue so we can wait for it to be
4805189790Srrs			 * passed by.
4806189790Srrs			 */
4807189790Srrs			TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1,
4808189790Srrs			    sctp_next);
4809189790Srrs			stcb->asoc.send_queue_cnt--;
4810189790Srrs			stcb->asoc.sent_queue_cnt++;
4811163953Srrs		}
4812163953Srrs	}
4813189790Srrs	if (foundeom == 0) {
4814189790Srrs		/*
4815189790Srrs		 * Still no eom found. That means there is stuff left on the
4816189790Srrs		 * stream out queue.. yuck.
4817189790Srrs		 */
4818252940Stuexen		SCTP_TCB_SEND_LOCK(stcb);
4819189790Srrs		strq = &stcb->asoc.strmout[stream];
4820252940Stuexen		sp = TAILQ_FIRST(&strq->outqueue);
4821252940Stuexen		if (sp != NULL) {
4822252940Stuexen			sp->discard_rest = 1;
4823252940Stuexen			/*
4824252940Stuexen			 * We may need to put a chunk on the queue that
4825252940Stuexen			 * holds the TSN that would have been sent with the
4826252940Stuexen			 * LAST bit.
4827252940Stuexen			 */
4828252940Stuexen			if (chk == NULL) {
4829252940Stuexen				/* Yep, we have to */
4830252940Stuexen				sctp_alloc_a_chunk(stcb, chk);
4831189790Srrs				if (chk == NULL) {
4832189790Srrs					/*
4833252940Stuexen					 * we are hosed. All we can do is
4834252940Stuexen					 * nothing.. which will cause an
4835252940Stuexen					 * abort if the peer is paying
4836252940Stuexen					 * attention.
4837189790Srrs					 */
4838252940Stuexen					goto oh_well;
4839189790Srrs				}
4840252940Stuexen				memset(chk, 0, sizeof(*chk));
4841252940Stuexen				chk->rec.data.rcv_flags = SCTP_DATA_LAST_FRAG;
4842252940Stuexen				chk->sent = SCTP_FORWARD_TSN_SKIP;
4843252940Stuexen				chk->asoc = &stcb->asoc;
4844252940Stuexen				chk->rec.data.stream_seq = strq->next_sequence_send;
4845252940Stuexen				chk->rec.data.stream_number = sp->stream;
4846252940Stuexen				chk->rec.data.payloadtype = sp->ppid;
4847252940Stuexen				chk->rec.data.context = sp->context;
4848252940Stuexen				chk->flags = sp->act_flags;
4849252940Stuexen				if (sp->net)
4850252940Stuexen					chk->whoTo = sp->net;
4851252940Stuexen				else
4852252940Stuexen					chk->whoTo = stcb->asoc.primary_destination;
4853252940Stuexen				atomic_add_int(&chk->whoTo->ref_count, 1);
4854252940Stuexen				chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1);
4855252940Stuexen				stcb->asoc.pr_sctp_cnt++;
4856252940Stuexen				TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next);
4857252940Stuexen				stcb->asoc.sent_queue_cnt++;
4858252940Stuexen				stcb->asoc.pr_sctp_cnt++;
4859252940Stuexen			} else {
4860252940Stuexen				chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
4861189790Srrs			}
4862252940Stuexen			strq->next_sequence_send++;
4863252940Stuexen	oh_well:
4864252940Stuexen			if (sp->data) {
4865252940Stuexen				/*
4866252940Stuexen				 * Pull any data to free up the SB and allow
4867252940Stuexen				 * sender to "add more" while we will throw
4868252940Stuexen				 * away :-)
4869252940Stuexen				 */
4870252940Stuexen				sctp_free_spbufspace(stcb, &stcb->asoc, sp);
4871252940Stuexen				ret_sz += sp->length;
4872252940Stuexen				do_wakeup_routine = 1;
4873252940Stuexen				sp->some_taken = 1;
4874252940Stuexen				sctp_m_freem(sp->data);
4875252940Stuexen				sp->data = NULL;
4876252940Stuexen				sp->tail_mbuf = NULL;
4877252940Stuexen				sp->length = 0;
4878252940Stuexen			}
4879252940Stuexen		}
4880189790Srrs		SCTP_TCB_SEND_UNLOCK(stcb);
4881189790Srrs	}
4882189790Srrs	if (do_wakeup_routine) {
4883252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4884190689Srrs		struct socket *so;
4885190689Srrs
4886189790Srrs		so = SCTP_INP_SO(stcb->sctp_ep);
4887189790Srrs		if (!so_locked) {
4888189790Srrs			atomic_add_int(&stcb->asoc.refcnt, 1);
4889189790Srrs			SCTP_TCB_UNLOCK(stcb);
4890189790Srrs			SCTP_SOCKET_LOCK(so, 1);
4891189790Srrs			SCTP_TCB_LOCK(stcb);
4892189790Srrs			atomic_subtract_int(&stcb->asoc.refcnt, 1);
4893189790Srrs			if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
4894189790Srrs				/* assoc was freed while we were unlocked */
4895189790Srrs				SCTP_SOCKET_UNLOCK(so, 1);
4896189790Srrs				return (ret_sz);
4897189790Srrs			}
4898189790Srrs		}
4899189790Srrs#endif
4900189790Srrs		sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
4901252882Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4902189790Srrs		if (!so_locked) {
4903189790Srrs			SCTP_SOCKET_UNLOCK(so, 1);
4904189790Srrs		}
4905189790Srrs#endif
4906189790Srrs	}
4907163953Srrs	return (ret_sz);
4908163953Srrs}
4909163953Srrs
4910163953Srrs/*
4911163953Srrs * checks to see if the given address, sa, is one that is currently known by
4912163953Srrs * the kernel note: can't distinguish the same address on multiple interfaces
4913163953Srrs * and doesn't handle multiple addresses with different zone/scope id's note:
4914163953Srrs * ifa_ifwithaddr() compares the entire sockaddr struct
4915163953Srrs */
4916167598Srrsstruct sctp_ifa *
4917170744Srrssctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr,
4918170744Srrs    int holds_lock)
4919163953Srrs{
4920167598Srrs	struct sctp_laddr *laddr;
4921163953Srrs
4922169420Srrs	if (holds_lock == 0) {
4923167598Srrs		SCTP_INP_RLOCK(inp);
4924169420Srrs	}
4925167598Srrs	LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
4926167598Srrs		if (laddr->ifa == NULL)
4927167598Srrs			continue;
4928167598Srrs		if (addr->sa_family != laddr->ifa->address.sa.sa_family)
4929167598Srrs			continue;
4930221249Stuexen#ifdef INET
4931167598Srrs		if (addr->sa_family == AF_INET) {
4932167598Srrs			if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
4933167598Srrs			    laddr->ifa->address.sin.sin_addr.s_addr) {
4934167598Srrs				/* found him. */
4935169420Srrs				if (holds_lock == 0) {
4936167598Srrs					SCTP_INP_RUNLOCK(inp);
4937169420Srrs				}
4938167598Srrs				return (laddr->ifa);
4939167598Srrs				break;
4940167598Srrs			}
4941178251Srrs		}
4942221249Stuexen#endif
4943178251Srrs#ifdef INET6
4944178251Srrs		if (addr->sa_family == AF_INET6) {
4945179157Srrs			if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr,
4946179157Srrs			    &laddr->ifa->address.sin6)) {
4947167598Srrs				/* found him. */
4948169420Srrs				if (holds_lock == 0) {
4949167598Srrs					SCTP_INP_RUNLOCK(inp);
4950169420Srrs				}
4951167598Srrs				return (laddr->ifa);
4952167598Srrs				break;
4953167598Srrs			}
4954167598Srrs		}
4955178251Srrs#endif
4956167598Srrs	}
4957169420Srrs	if (holds_lock == 0) {
4958167598Srrs		SCTP_INP_RUNLOCK(inp);
4959169420Srrs	}
4960167598Srrs	return (NULL);
4961167598Srrs}
4962163953Srrs
4963167698Srrsuint32_t
4964167698Srrssctp_get_ifa_hash_val(struct sockaddr *addr)
4965167698Srrs{
4966221328Stuexen	switch (addr->sa_family) {
4967221328Stuexen#ifdef INET
4968221328Stuexen	case AF_INET:
4969221328Stuexen		{
4970221328Stuexen			struct sockaddr_in *sin;
4971167698Srrs
4972221328Stuexen			sin = (struct sockaddr_in *)addr;
4973221328Stuexen			return (sin->sin_addr.s_addr ^ (sin->sin_addr.s_addr >> 16));
4974221328Stuexen		}
4975221328Stuexen#endif
4976221328Stuexen#ifdef INET6
4977252957Stuexen	case AF_INET6:
4978221328Stuexen		{
4979221328Stuexen			struct sockaddr_in6 *sin6;
4980221328Stuexen			uint32_t hash_of_addr;
4981167698Srrs
4982221328Stuexen			sin6 = (struct sockaddr_in6 *)addr;
4983221328Stuexen			hash_of_addr = (sin6->sin6_addr.s6_addr32[0] +
4984221328Stuexen			    sin6->sin6_addr.s6_addr32[1] +
4985221328Stuexen			    sin6->sin6_addr.s6_addr32[2] +
4986221328Stuexen			    sin6->sin6_addr.s6_addr32[3]);
4987221328Stuexen			hash_of_addr = (hash_of_addr ^ (hash_of_addr >> 16));
4988221328Stuexen			return (hash_of_addr);
4989221328Stuexen		}
4990221328Stuexen#endif
4991221328Stuexen	default:
4992221328Stuexen		break;
4993167698Srrs	}
4994167698Srrs	return (0);
4995167698Srrs}
4996167698Srrs
4997167598Srrsstruct sctp_ifa *
4998167598Srrssctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
4999167598Srrs{
5000167598Srrs	struct sctp_ifa *sctp_ifap;
5001167598Srrs	struct sctp_vrf *vrf;
5002167698Srrs	struct sctp_ifalist *hash_head;
5003167698Srrs	uint32_t hash_of_addr;
5004167598Srrs
5005168299Srrs	if (holds_lock == 0)
5006172218Srrs		SCTP_IPI_ADDR_RLOCK();
5007168299Srrs
5008167598Srrs	vrf = sctp_find_vrf(vrf_id);
5009168299Srrs	if (vrf == NULL) {
5010182367Srrsstage_right:
5011168299Srrs		if (holds_lock == 0)
5012172218Srrs			SCTP_IPI_ADDR_RUNLOCK();
5013167598Srrs		return (NULL);
5014168299Srrs	}
5015167698Srrs	hash_of_addr = sctp_get_ifa_hash_val(addr);
5016167598Srrs
5017169352Srrs	hash_head = &vrf->vrf_addr_hash[(hash_of_addr & vrf->vrf_addr_hashmark)];
5018168299Srrs	if (hash_head == NULL) {
5019169420Srrs		SCTP_PRINTF("hash_of_addr:%x mask:%x table:%x - ",
5020172218Srrs		    hash_of_addr, (uint32_t) vrf->vrf_addr_hashmark,
5021172218Srrs		    (uint32_t) (hash_of_addr & vrf->vrf_addr_hashmark));
5022168299Srrs		sctp_print_address(addr);
5023169420Srrs		SCTP_PRINTF("No such bucket for address\n");
5024168299Srrs		if (holds_lock == 0)
5025172218Srrs			SCTP_IPI_ADDR_RUNLOCK();
5026168299Srrs
5027168299Srrs		return (NULL);
5028168299Srrs	}
5029167698Srrs	LIST_FOREACH(sctp_ifap, hash_head, next_bucket) {
5030168299Srrs		if (sctp_ifap == NULL) {
5031182367Srrs#ifdef INVARIANTS
5032168299Srrs			panic("Huh LIST_FOREACH corrupt");
5033182367Srrs			goto stage_right;
5034182367Srrs#else
5035182367Srrs			SCTP_PRINTF("LIST corrupt of sctp_ifap's?\n");
5036182367Srrs			goto stage_right;
5037182367Srrs#endif
5038168299Srrs		}
5039167698Srrs		if (addr->sa_family != sctp_ifap->address.sa.sa_family)
5040167698Srrs			continue;
5041221249Stuexen#ifdef INET
5042167698Srrs		if (addr->sa_family == AF_INET) {
5043167698Srrs			if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
5044167698Srrs			    sctp_ifap->address.sin.sin_addr.s_addr) {
5045167698Srrs				/* found him. */
5046167698Srrs				if (holds_lock == 0)
5047172218Srrs					SCTP_IPI_ADDR_RUNLOCK();
5048167698Srrs				return (sctp_ifap);
5049167698Srrs				break;
5050167698Srrs			}
5051178251Srrs		}
5052221249Stuexen#endif
5053178251Srrs#ifdef INET6
5054178251Srrs		if (addr->sa_family == AF_INET6) {
5055179157Srrs			if (SCTP6_ARE_ADDR_EQUAL((struct sockaddr_in6 *)addr,
5056179157Srrs			    &sctp_ifap->address.sin6)) {
5057167698Srrs				/* found him. */
5058167698Srrs				if (holds_lock == 0)
5059172218Srrs					SCTP_IPI_ADDR_RUNLOCK();
5060167698Srrs				return (sctp_ifap);
5061167698Srrs				break;
5062167698Srrs			}
5063167598Srrs		}
5064178251Srrs#endif
5065167598Srrs	}
5066167598Srrs	if (holds_lock == 0)
5067172218Srrs		SCTP_IPI_ADDR_RUNLOCK();
5068167598Srrs	return (NULL);
5069167598Srrs}
5070167598Srrs
5071163953Srrsstatic void
5072170140Srrssctp_user_rcvd(struct sctp_tcb *stcb, uint32_t * freed_so_far, int hold_rlock,
5073163953Srrs    uint32_t rwnd_req)
5074163953Srrs{
5075163953Srrs	/* User pulled some data, do we need a rwnd update? */
5076163953Srrs	int r_unlocked = 0;
5077163953Srrs	uint32_t dif, rwnd;
5078163953Srrs	struct socket *so = NULL;
5079163953Srrs
5080163953Srrs	if (stcb == NULL)
5081163953Srrs		return;
5082163953Srrs
5083163996Srrs	atomic_add_int(&stcb->asoc.refcnt, 1);
5084163953Srrs
5085167736Srrs	if (stcb->asoc.state & (SCTP_STATE_ABOUT_TO_BE_FREED |
5086167736Srrs	    SCTP_STATE_SHUTDOWN_RECEIVED |
5087170140Srrs	    SCTP_STATE_SHUTDOWN_ACK_SENT)) {
5088163953Srrs		/* Pre-check If we are freeing no update */
5089163953Srrs		goto no_lock;
5090163953Srrs	}
5091163953Srrs	SCTP_INP_INCR_REF(stcb->sctp_ep);
5092163953Srrs	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
5093163953Srrs	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
5094163953Srrs		goto out;
5095163953Srrs	}
5096163953Srrs	so = stcb->sctp_socket;
5097163953Srrs	if (so == NULL) {
5098163953Srrs		goto out;
5099163953Srrs	}
5100163953Srrs	atomic_add_int(&stcb->freed_by_sorcv_sincelast, *freed_so_far);
5101163953Srrs	/* Have you have freed enough to look */
5102163953Srrs	*freed_so_far = 0;
5103163953Srrs	/* Yep, its worth a look and the lock overhead */
5104163953Srrs
5105163953Srrs	/* Figure out what the rwnd would be */
5106163953Srrs	rwnd = sctp_calc_rwnd(stcb, &stcb->asoc);
5107163953Srrs	if (rwnd >= stcb->asoc.my_last_reported_rwnd) {
5108163953Srrs		dif = rwnd - stcb->asoc.my_last_reported_rwnd;
5109163953Srrs	} else {
5110163953Srrs		dif = 0;
5111163953Srrs	}
5112163953Srrs	if (dif >= rwnd_req) {
5113163953Srrs		if (hold_rlock) {
5114163953Srrs			SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
5115163953Srrs			r_unlocked = 1;
5116163953Srrs		}
5117163953Srrs		if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
5118163953Srrs			/*
5119163953Srrs			 * One last check before we allow the guy possibly
5120163953Srrs			 * to get in. There is a race, where the guy has not
5121163953Srrs			 * reached the gate. In that case
5122163953Srrs			 */
5123163953Srrs			goto out;
5124163953Srrs		}
5125163953Srrs		SCTP_TCB_LOCK(stcb);
5126163953Srrs		if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
5127163953Srrs			/* No reports here */
5128163953Srrs			SCTP_TCB_UNLOCK(stcb);
5129163953Srrs			goto out;
5130163953Srrs		}
5131163953Srrs		SCTP_STAT_INCR(sctps_wu_sacks_sent);
5132221627Stuexen		sctp_send_sack(stcb, SCTP_SO_LOCKED);
5133185694Srrs
5134163953Srrs		sctp_chunk_output(stcb->sctp_ep, stcb,
5135172090Srrs		    SCTP_OUTPUT_FROM_USR_RCVD, SCTP_SO_LOCKED);
5136163953Srrs		/* make sure no timer is running */
5137165220Srrs		sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTPUTIL + SCTP_LOC_6);
5138163953Srrs		SCTP_TCB_UNLOCK(stcb);
5139163953Srrs	} else {
5140163953Srrs		/* Update how much we have pending */
5141163953Srrs		stcb->freed_by_sorcv_sincelast = dif;
5142163953Srrs	}
5143163953Srrsout:
5144163953Srrs	if (so && r_unlocked && hold_rlock) {
5145163953Srrs		SCTP_INP_READ_LOCK(stcb->sctp_ep);
5146163953Srrs	}
5147163953Srrs	SCTP_INP_DECR_REF(stcb->sctp_ep);
5148163953Srrsno_lock:
5149163996Srrs	atomic_add_int(&stcb->asoc.refcnt, -1);
5150163953Srrs	return;
5151163953Srrs}
5152163953Srrs
5153163953Srrsint
5154163953Srrssctp_sorecvmsg(struct socket *so,
5155163953Srrs    struct uio *uio,
5156163953Srrs    struct mbuf **mp,
5157163953Srrs    struct sockaddr *from,
5158163953Srrs    int fromlen,
5159163953Srrs    int *msg_flags,
5160163953Srrs    struct sctp_sndrcvinfo *sinfo,
5161163953Srrs    int filling_sinfo)
5162163953Srrs{
5163163953Srrs	/*
5164163953Srrs	 * MSG flags we will look at MSG_DONTWAIT - non-blocking IO.
5165163953Srrs	 * MSG_PEEK - Look don't touch :-D (only valid with OUT mbuf copy
5166163953Srrs	 * mp=NULL thus uio is the copy method to userland) MSG_WAITALL - ??
5167163953Srrs	 * On the way out we may send out any combination of:
5168163953Srrs	 * MSG_NOTIFICATION MSG_EOR
5169163953Srrs	 *
5170163953Srrs	 */
5171163953Srrs	struct sctp_inpcb *inp = NULL;
5172163953Srrs	int my_len = 0;
5173163953Srrs	int cp_len = 0, error = 0;
5174163953Srrs	struct sctp_queued_to_read *control = NULL, *ctl = NULL, *nxt = NULL;
5175212713Stuexen	struct mbuf *m = NULL;
5176163953Srrs	struct sctp_tcb *stcb = NULL;
5177163953Srrs	int wakeup_read_socket = 0;
5178163953Srrs	int freecnt_applied = 0;
5179163953Srrs	int out_flags = 0, in_flags = 0;
5180163953Srrs	int block_allowed = 1;
5181170140Srrs	uint32_t freed_so_far = 0;
5182173509Srrs	uint32_t copied_so_far = 0;
5183166086Srrs	int in_eeor_mode = 0;
5184163953Srrs	int no_rcv_needed = 0;
5185163953Srrs	uint32_t rwnd_req = 0;
5186163953Srrs	int hold_sblock = 0;
5187163953Srrs	int hold_rlock = 0;
5188167598Srrs	int slen = 0;
5189170140Srrs	uint32_t held_length = 0;
5190169236Srwatson	int sockbuf_lock = 0;
5191163953Srrs
5192169352Srrs	if (uio == NULL) {
5193171943Srrs		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
5194169352Srrs		return (EINVAL);
5195169352Srrs	}
5196163953Srrs	if (msg_flags) {
5197163953Srrs		in_flags = *msg_flags;
5198168709Srrs		if (in_flags & MSG_PEEK)
5199168709Srrs			SCTP_STAT_INCR(sctps_read_peeks);
5200163953Srrs	} else {
5201163953Srrs		in_flags = 0;
5202163953Srrs	}
5203169352Srrs	slen = uio->uio_resid;
5204169352Srrs
5205163953Srrs	/* Pull in and set up our int flags */
5206163953Srrs	if (in_flags & MSG_OOB) {
5207163953Srrs		/* Out of band's NOT supported */
5208163953Srrs		return (EOPNOTSUPP);
5209163953Srrs	}
5210163953Srrs	if ((in_flags & MSG_PEEK) && (mp != NULL)) {
5211171943Srrs		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
5212163953Srrs		return (EINVAL);
5213163953Srrs	}
5214163953Srrs	if ((in_flags & (MSG_DONTWAIT
5215163953Srrs	    | MSG_NBIO
5216163953Srrs	    )) ||
5217167598Srrs	    SCTP_SO_IS_NBIO(so)) {
5218163953Srrs		block_allowed = 0;
5219163953Srrs	}
5220163953Srrs	/* setup the endpoint */
5221163953Srrs	inp = (struct sctp_inpcb *)so->so_pcb;
5222163953Srrs	if (inp == NULL) {
5223171943Srrs		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EFAULT);
5224163953Srrs		return (EFAULT);
5225163953Srrs	}
5226167736Srrs	rwnd_req = (SCTP_SB_LIMIT_RCV(so) >> SCTP_RWND_HIWAT_SHIFT);
5227163953Srrs	/* Must be at least a MTU's worth */
5228163953Srrs	if (rwnd_req < SCTP_MIN_RWND)
5229163953Srrs		rwnd_req = SCTP_MIN_RWND;
5230163953Srrs	in_eeor_mode = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
5231179783Srrs	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
5232170744Srrs		sctp_misc_ints(SCTP_SORECV_ENTER,
5233170744Srrs		    rwnd_req, in_eeor_mode, so->so_rcv.sb_cc, uio->uio_resid);
5234170744Srrs	}
5235179783Srrs	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
5236170744Srrs		sctp_misc_ints(SCTP_SORECV_ENTERPL,
5237170744Srrs		    rwnd_req, block_allowed, so->so_rcv.sb_cc, uio->uio_resid);
5238170744Srrs	}
5239175845Srwatson	error = sblock(&so->so_rcv, (block_allowed ? SBL_WAIT : 0));
5240163953Srrs	if (error) {
5241163953Srrs		goto release_unlocked;
5242163953Srrs	}
5243242836Smjg	sockbuf_lock = 1;
5244163953Srrsrestart:
5245163953Srrs
5246169236Srwatson
5247163953Srrsrestart_nosblocks:
5248163953Srrs	if (hold_sblock == 0) {
5249163953Srrs		SOCKBUF_LOCK(&so->so_rcv);
5250163953Srrs		hold_sblock = 1;
5251163953Srrs	}
5252163953Srrs	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
5253163953Srrs	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
5254163953Srrs		goto out;
5255163953Srrs	}
5256237885Stuexen	if ((so->so_rcv.sb_state & SBS_CANTRCVMORE) && (so->so_rcv.sb_cc == 0)) {
5257163953Srrs		if (so->so_error) {
5258163953Srrs			error = so->so_error;
5259166023Srrs			if ((in_flags & MSG_PEEK) == 0)
5260166023Srrs				so->so_error = 0;
5261174257Srrs			goto out;
5262163953Srrs		} else {
5263174257Srrs			if (so->so_rcv.sb_cc == 0) {
5264174257Srrs				/* indicate EOF */
5265174257Srrs				error = 0;
5266174257Srrs				goto out;
5267174257Srrs			}
5268163953Srrs		}
5269163953Srrs	}
5270163953Srrs	if ((so->so_rcv.sb_cc <= held_length) && block_allowed) {
5271163953Srrs		/* we need to wait for data */
5272163953Srrs		if ((so->so_rcv.sb_cc == 0) &&
5273163953Srrs		    ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5274163953Srrs		    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
5275163953Srrs			if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
5276163953Srrs				/*
5277163953Srrs				 * For active open side clear flags for
5278163953Srrs				 * re-use passive open is blocked by
5279163953Srrs				 * connect.
5280163953Srrs				 */
5281163953Srrs				if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) {
5282163953Srrs					/*
5283163953Srrs					 * You were aborted, passive side
5284163953Srrs					 * always hits here
5285163953Srrs					 */
5286171943Srrs					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
5287163953Srrs					error = ECONNRESET;
5288163953Srrs				}
5289163953Srrs				so->so_state &= ~(SS_ISCONNECTING |
5290163953Srrs				    SS_ISDISCONNECTING |
5291163953Srrs				    SS_ISCONFIRMING |
5292163953Srrs				    SS_ISCONNECTED);
5293163953Srrs				if (error == 0) {
5294163953Srrs					if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
5295171943Srrs						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
5296163953Srrs						error = ENOTCONN;
5297163953Srrs					}
5298163953Srrs				}
5299163953Srrs				goto out;
5300163953Srrs			}
5301163953Srrs		}
5302163953Srrs		error = sbwait(&so->so_rcv);
5303163953Srrs		if (error) {
5304163953Srrs			goto out;
5305163953Srrs		}
5306163953Srrs		held_length = 0;
5307163953Srrs		goto restart_nosblocks;
5308163953Srrs	} else if (so->so_rcv.sb_cc == 0) {
5309166023Srrs		if (so->so_error) {
5310166023Srrs			error = so->so_error;
5311166023Srrs			if ((in_flags & MSG_PEEK) == 0)
5312166023Srrs				so->so_error = 0;
5313166023Srrs		} else {
5314166023Srrs			if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5315166023Srrs			    (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
5316166023Srrs				if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
5317166023Srrs					/*
5318166023Srrs					 * For active open side clear flags
5319166023Srrs					 * for re-use passive open is
5320166023Srrs					 * blocked by connect.
5321166023Srrs					 */
5322166023Srrs					if (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED) {
5323166023Srrs						/*
5324166023Srrs						 * You were aborted, passive
5325166023Srrs						 * side always hits here
5326166023Srrs						 */
5327171943Srrs						SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ECONNRESET);
5328166023Srrs						error = ECONNRESET;
5329166023Srrs					}
5330166023Srrs					so->so_state &= ~(SS_ISCONNECTING |
5331166023Srrs					    SS_ISDISCONNECTING |
5332166023Srrs					    SS_ISCONFIRMING |
5333166023Srrs					    SS_ISCONNECTED);
5334166023Srrs					if (error == 0) {
5335166023Srrs						if ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) == 0) {
5336171943Srrs							SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOTCONN);
5337166023Srrs							error = ENOTCONN;
5338166023Srrs						}
5339166023Srrs					}
5340166023Srrs					goto out;
5341166023Srrs				}
5342166023Srrs			}
5343171943Srrs			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EWOULDBLOCK);
5344166023Srrs			error = EWOULDBLOCK;
5345166023Srrs		}
5346163953Srrs		goto out;
5347163953Srrs	}
5348169208Srrs	if (hold_sblock == 1) {
5349169208Srrs		SOCKBUF_UNLOCK(&so->so_rcv);
5350169208Srrs		hold_sblock = 0;
5351169208Srrs	}
5352163953Srrs	/* we possibly have data we can read */
5353169655Srrs	/* sa_ignore FREED_MEMORY */
5354163953Srrs	control = TAILQ_FIRST(&inp->read_queue);
5355163953Srrs	if (control == NULL) {
5356163953Srrs		/*
5357163953Srrs		 * This could be happening since the appender did the
5358163953Srrs		 * increment but as not yet did the tailq insert onto the
5359163953Srrs		 * read_queue
5360163953Srrs		 */
5361163953Srrs		if (hold_rlock == 0) {
5362163953Srrs			SCTP_INP_READ_LOCK(inp);
5363163953Srrs		}
5364163953Srrs		control = TAILQ_FIRST(&inp->read_queue);
5365163953Srrs		if ((control == NULL) && (so->so_rcv.sb_cc != 0)) {
5366165220Srrs#ifdef INVARIANTS
5367163953Srrs			panic("Huh, its non zero and nothing on control?");
5368163953Srrs#endif
5369163953Srrs			so->so_rcv.sb_cc = 0;
5370163953Srrs		}
5371163953Srrs		SCTP_INP_READ_UNLOCK(inp);
5372163953Srrs		hold_rlock = 0;
5373163953Srrs		goto restart;
5374163953Srrs	}
5375163953Srrs	if ((control->length == 0) &&
5376163953Srrs	    (control->do_not_ref_stcb)) {
5377163953Srrs		/*
5378163953Srrs		 * Clean up code for freeing assoc that left behind a
5379163953Srrs		 * pdapi.. maybe a peer in EEOR that just closed after
5380163953Srrs		 * sending and never indicated a EOR.
5381163953Srrs		 */
5382163953Srrs		if (hold_rlock == 0) {
5383163953Srrs			hold_rlock = 1;
5384163953Srrs			SCTP_INP_READ_LOCK(inp);
5385163953Srrs		}
5386163953Srrs		control->held_length = 0;
5387163953Srrs		if (control->data) {
5388163953Srrs			/* Hmm there is data here .. fix */
5389170140Srrs			struct mbuf *m_tmp;
5390163953Srrs			int cnt = 0;
5391163953Srrs
5392170140Srrs			m_tmp = control->data;
5393170140Srrs			while (m_tmp) {
5394170140Srrs				cnt += SCTP_BUF_LEN(m_tmp);
5395170140Srrs				if (SCTP_BUF_NEXT(m_tmp) == NULL) {
5396170140Srrs					control->tail_mbuf = m_tmp;
5397163953Srrs					control->end_added = 1;
5398163953Srrs				}
5399170140Srrs				m_tmp = SCTP_BUF_NEXT(m_tmp);
5400163953Srrs			}
5401163953Srrs			control->length = cnt;
5402163953Srrs		} else {
5403163953Srrs			/* remove it */
5404163953Srrs			TAILQ_REMOVE(&inp->read_queue, control, next);
5405163953Srrs			/* Add back any hiddend data */
5406163953Srrs			sctp_free_remote_addr(control->whoFrom);
5407163953Srrs			sctp_free_a_readq(stcb, control);
5408163953Srrs		}
5409163953Srrs		if (hold_rlock) {
5410163953Srrs			hold_rlock = 0;
5411163953Srrs			SCTP_INP_READ_UNLOCK(inp);
5412163953Srrs		}
5413163953Srrs		goto restart;
5414163953Srrs	}
5415196260Stuexen	if ((control->length == 0) &&
5416196260Stuexen	    (control->end_added == 1)) {
5417196260Stuexen		/*
5418196260Stuexen		 * Do we also need to check for (control->pdapi_aborted ==
5419196260Stuexen		 * 1)?
5420196260Stuexen		 */
5421196260Stuexen		if (hold_rlock == 0) {
5422196260Stuexen			hold_rlock = 1;
5423196260Stuexen			SCTP_INP_READ_LOCK(inp);
5424196260Stuexen		}
5425196260Stuexen		TAILQ_REMOVE(&inp->read_queue, control, next);
5426196260Stuexen		if (control->data) {
5427196260Stuexen#ifdef INVARIANTS
5428196260Stuexen			panic("control->data not null but control->length == 0");
5429196260Stuexen#else
5430196260Stuexen			SCTP_PRINTF("Strange, data left in the control buffer. Cleaning up.\n");
5431196260Stuexen			sctp_m_freem(control->data);
5432196260Stuexen			control->data = NULL;
5433196260Stuexen#endif
5434196260Stuexen		}
5435196260Stuexen		if (control->aux_data) {
5436196260Stuexen			sctp_m_free(control->aux_data);
5437196260Stuexen			control->aux_data = NULL;
5438196260Stuexen		}
5439196260Stuexen		sctp_free_remote_addr(control->whoFrom);
5440196260Stuexen		sctp_free_a_readq(stcb, control);
5441196260Stuexen		if (hold_rlock) {
5442196260Stuexen			hold_rlock = 0;
5443196260Stuexen			SCTP_INP_READ_UNLOCK(inp);
5444196260Stuexen		}
5445196260Stuexen		goto restart;
5446196260Stuexen	}
5447163953Srrs	if (control->length == 0) {
5448163953Srrs		if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) &&
5449163953Srrs		    (filling_sinfo)) {
5450163953Srrs			/* find a more suitable one then this */
5451163953Srrs			ctl = TAILQ_NEXT(control, next);
5452163953Srrs			while (ctl) {
5453168943Srrs				if ((ctl->stcb != control->stcb) && (ctl->length) &&
5454168943Srrs				    (ctl->some_taken ||
5455169352Srrs				    (ctl->spec_flags & M_NOTIFICATION) ||
5456168943Srrs				    ((ctl->do_not_ref_stcb == 0) &&
5457168943Srrs				    (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0)))
5458168943Srrs				    ) {
5459168943Srrs					/*-
5460168943Srrs					 * If we have a different TCB next, and there is data
5461168943Srrs					 * present. If we have already taken some (pdapi), OR we can
5462168943Srrs					 * ref the tcb and no delivery as started on this stream, we
5463169352Srrs					 * take it. Note we allow a notification on a different
5464169352Srrs					 * assoc to be delivered..
5465168943Srrs					 */
5466163953Srrs					control = ctl;
5467163953Srrs					goto found_one;
5468168943Srrs				} else if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) &&
5469168943Srrs					    (ctl->length) &&
5470168943Srrs					    ((ctl->some_taken) ||
5471168943Srrs					    ((ctl->do_not_ref_stcb == 0) &&
5472169352Srrs					    ((ctl->spec_flags & M_NOTIFICATION) == 0) &&
5473206137Stuexen				    (ctl->stcb->asoc.strmin[ctl->sinfo_stream].delivery_started == 0)))) {
5474168943Srrs					/*-
5475168943Srrs					 * If we have the same tcb, and there is data present, and we
5476168943Srrs					 * have the strm interleave feature present. Then if we have
5477168943Srrs					 * taken some (pdapi) or we can refer to tht tcb AND we have
5478168943Srrs					 * not started a delivery for this stream, we can take it.
5479169352Srrs					 * Note we do NOT allow a notificaiton on the same assoc to
5480169352Srrs					 * be delivered.
5481168943Srrs					 */
5482168943Srrs					control = ctl;
5483168943Srrs					goto found_one;
5484163953Srrs				}
5485163953Srrs				ctl = TAILQ_NEXT(ctl, next);
5486163953Srrs			}
5487163953Srrs		}
5488163953Srrs		/*
5489163953Srrs		 * if we reach here, not suitable replacement is available
5490163953Srrs		 * <or> fragment interleave is NOT on. So stuff the sb_cc
5491163953Srrs		 * into the our held count, and its time to sleep again.
5492163953Srrs		 */
5493163953Srrs		held_length = so->so_rcv.sb_cc;
5494163953Srrs		control->held_length = so->so_rcv.sb_cc;
5495163953Srrs		goto restart;
5496163953Srrs	}
5497163953Srrs	/* Clear the held length since there is something to read */
5498163953Srrs	control->held_length = 0;
5499163953Srrs	if (hold_rlock) {
5500163953Srrs		SCTP_INP_READ_UNLOCK(inp);
5501163953Srrs		hold_rlock = 0;
5502163953Srrs	}
5503163953Srrsfound_one:
5504163953Srrs	/*
5505163953Srrs	 * If we reach here, control has a some data for us to read off.
5506163953Srrs	 * Note that stcb COULD be NULL.
5507163953Srrs	 */
5508174323Srrs	control->some_taken++;
5509163953Srrs	if (hold_sblock) {
5510163953Srrs		SOCKBUF_UNLOCK(&so->so_rcv);
5511163953Srrs		hold_sblock = 0;
5512163953Srrs	}
5513163953Srrs	stcb = control->stcb;
5514163953Srrs	if (stcb) {
5515170138Srrs		if ((control->do_not_ref_stcb == 0) &&
5516170138Srrs		    (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) {
5517163996Srrs			if (freecnt_applied == 0)
5518163996Srrs				stcb = NULL;
5519163953Srrs		} else if (control->do_not_ref_stcb == 0) {
5520163953Srrs			/* you can't free it on me please */
5521163953Srrs			/*
5522163953Srrs			 * The lock on the socket buffer protects us so the
5523163953Srrs			 * free code will stop. But since we used the
5524163953Srrs			 * socketbuf lock and the sender uses the tcb_lock
5525163953Srrs			 * to increment, we need to use the atomic add to
5526163953Srrs			 * the refcnt
5527163953Srrs			 */
5528172396Srrs			if (freecnt_applied) {
5529172396Srrs#ifdef INVARIANTS
5530170091Srrs				panic("refcnt already incremented");
5531172396Srrs#else
5532235164Stuexen				SCTP_PRINTF("refcnt already incremented?\n");
5533172396Srrs#endif
5534172396Srrs			} else {
5535172396Srrs				atomic_add_int(&stcb->asoc.refcnt, 1);
5536172396Srrs				freecnt_applied = 1;
5537172396Srrs			}
5538163953Srrs			/*
5539163953Srrs			 * Setup to remember how much we have not yet told
5540163953Srrs			 * the peer our rwnd has opened up. Note we grab the
5541163953Srrs			 * value from the tcb from last time. Note too that
5542170138Srrs			 * sack sending clears this when a sack is sent,
5543163953Srrs			 * which is fine. Once we hit the rwnd_req, we then
5544163953Srrs			 * will go to the sctp_user_rcvd() that will not
5545163953Srrs			 * lock until it KNOWs it MUST send a WUP-SACK.
5546163953Srrs			 */
5547163953Srrs			freed_so_far = stcb->freed_by_sorcv_sincelast;
5548163953Srrs			stcb->freed_by_sorcv_sincelast = 0;
5549163953Srrs		}
5550163953Srrs	}
5551169352Srrs	if (stcb &&
5552169352Srrs	    ((control->spec_flags & M_NOTIFICATION) == 0) &&
5553169295Srrs	    control->do_not_ref_stcb == 0) {
5554169208Srrs		stcb->asoc.strmin[control->sinfo_stream].delivery_started = 1;
5555169208Srrs	}
5556163953Srrs	/* First lets get off the sinfo and sockaddr info */
5557163953Srrs	if ((sinfo) && filling_sinfo) {
5558163953Srrs		memcpy(sinfo, control, sizeof(struct sctp_nonpad_sndrcvinfo));
5559163953Srrs		nxt = TAILQ_NEXT(control, next);
5560223132Stuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) ||
5561223132Stuexen		    sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) {
5562163953Srrs			struct sctp_extrcvinfo *s_extra;
5563163953Srrs
5564163953Srrs			s_extra = (struct sctp_extrcvinfo *)sinfo;
5565168943Srrs			if ((nxt) &&
5566168943Srrs			    (nxt->length)) {
5567168943Srrs				s_extra->sreinfo_next_flags = SCTP_NEXT_MSG_AVAIL;
5568163953Srrs				if (nxt->sinfo_flags & SCTP_UNORDERED) {
5569168943Srrs					s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_UNORDERED;
5570163953Srrs				}
5571166675Srrs				if (nxt->spec_flags & M_NOTIFICATION) {
5572168943Srrs					s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_IS_NOTIFICATION;
5573166675Srrs				}
5574168943Srrs				s_extra->sreinfo_next_aid = nxt->sinfo_assoc_id;
5575168943Srrs				s_extra->sreinfo_next_length = nxt->length;
5576168943Srrs				s_extra->sreinfo_next_ppid = nxt->sinfo_ppid;
5577168943Srrs				s_extra->sreinfo_next_stream = nxt->sinfo_stream;
5578163953Srrs				if (nxt->tail_mbuf != NULL) {
5579165647Srrs					if (nxt->end_added) {
5580168943Srrs						s_extra->sreinfo_next_flags |= SCTP_NEXT_MSG_ISCOMPLETE;
5581163953Srrs					}
5582163953Srrs				}
5583163953Srrs			} else {
5584163953Srrs				/*
5585163953Srrs				 * we explicitly 0 this, since the memcpy
5586163953Srrs				 * got some other things beyond the older
5587163953Srrs				 * sinfo_ that is on the control's structure
5588163953Srrs				 * :-D
5589163953Srrs				 */
5590168943Srrs				nxt = NULL;
5591168943Srrs				s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG;
5592168943Srrs				s_extra->sreinfo_next_aid = 0;
5593168943Srrs				s_extra->sreinfo_next_length = 0;
5594168943Srrs				s_extra->sreinfo_next_ppid = 0;
5595168943Srrs				s_extra->sreinfo_next_stream = 0;
5596163953Srrs			}
5597163953Srrs		}
5598163953Srrs		/*
5599163953Srrs		 * update off the real current cum-ack, if we have an stcb.
5600163953Srrs		 */
5601170138Srrs		if ((control->do_not_ref_stcb == 0) && stcb)
5602163953Srrs			sinfo->sinfo_cumtsn = stcb->asoc.cumulative_tsn;
5603163953Srrs		/*
5604163953Srrs		 * mask off the high bits, we keep the actual chunk bits in
5605163953Srrs		 * there.
5606163953Srrs		 */
5607163953Srrs		sinfo->sinfo_flags &= 0x00ff;
5608170354Srrs		if ((control->sinfo_flags >> 8) & SCTP_DATA_UNORDERED) {
5609170354Srrs			sinfo->sinfo_flags |= SCTP_UNORDERED;
5610170354Srrs		}
5611163953Srrs	}
5612171477Srrs#ifdef SCTP_ASOCLOG_OF_TSNS
5613171477Srrs	{
5614171477Srrs		int index, newindex;
5615171477Srrs		struct sctp_pcbtsn_rlog *entry;
5616171477Srrs
5617171477Srrs		do {
5618171477Srrs			index = inp->readlog_index;
5619171477Srrs			newindex = index + 1;
5620171477Srrs			if (newindex >= SCTP_READ_LOG_SIZE) {
5621171477Srrs				newindex = 0;
5622171477Srrs			}
5623171477Srrs		} while (atomic_cmpset_int(&inp->readlog_index, index, newindex) == 0);
5624171477Srrs		entry = &inp->readlog[index];
5625171477Srrs		entry->vtag = control->sinfo_assoc_id;
5626171477Srrs		entry->strm = control->sinfo_stream;
5627171477Srrs		entry->seq = control->sinfo_ssn;
5628171477Srrs		entry->sz = control->length;
5629171477Srrs		entry->flgs = control->sinfo_flags;
5630171477Srrs	}
5631171477Srrs#endif
5632163953Srrs	if (fromlen && from) {
5633234787Stuexen		cp_len = min((size_t)fromlen, (size_t)control->whoFrom->ro._l_addr.sa.sa_len);
5634234787Stuexen		switch (control->whoFrom->ro._l_addr.sa.sa_family) {
5635234787Stuexen#ifdef INET6
5636234787Stuexen		case AF_INET6:
5637234787Stuexen			((struct sockaddr_in6 *)from)->sin6_port = control->port_from;
5638234787Stuexen			break;
5639234787Stuexen#endif
5640167598Srrs#ifdef INET
5641234787Stuexen		case AF_INET:
5642234787Stuexen			((struct sockaddr_in *)from)->sin_port = control->port_from;
5643234787Stuexen			break;
5644234787Stuexen#endif
5645234787Stuexen		default:
5646234787Stuexen			break;
5647234787Stuexen		}
5648163953Srrs		memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
5649163953Srrs
5650167598Srrs#if defined(INET) && defined(INET6)
5651178251Srrs		if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
5652234787Stuexen		    (from->sa_family == AF_INET) &&
5653163953Srrs		    ((size_t)fromlen >= sizeof(struct sockaddr_in6))) {
5654163953Srrs			struct sockaddr_in *sin;
5655163953Srrs			struct sockaddr_in6 sin6;
5656163953Srrs
5657234787Stuexen			sin = (struct sockaddr_in *)from;
5658163953Srrs			bzero(&sin6, sizeof(sin6));
5659163953Srrs			sin6.sin6_family = AF_INET6;
5660163953Srrs			sin6.sin6_len = sizeof(struct sockaddr_in6);
5661180955Srrs			sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
5662163953Srrs			bcopy(&sin->sin_addr,
5663180955Srrs			    &sin6.sin6_addr.s6_addr32[3],
5664180955Srrs			    sizeof(sin6.sin6_addr.s6_addr32[3]));
5665163953Srrs			sin6.sin6_port = sin->sin_port;
5666234787Stuexen			memcpy(from, &sin6, sizeof(struct sockaddr_in6));
5667163953Srrs		}
5668163953Srrs#endif
5669238578Stuexen#ifdef INET6
5670163953Srrs		{
5671234787Stuexen			struct sockaddr_in6 lsa6, *from6;
5672163953Srrs
5673234787Stuexen			from6 = (struct sockaddr_in6 *)from;
5674234787Stuexen			sctp_recover_scope_mac(from6, (&lsa6));
5675163953Srrs		}
5676163953Srrs#endif
5677163953Srrs	}
5678163953Srrs	/* now copy out what data we can */
5679163953Srrs	if (mp == NULL) {
5680163953Srrs		/* copy out each mbuf in the chain up to length */
5681163953Srrsget_more_data:
5682163953Srrs		m = control->data;
5683163953Srrs		while (m) {
5684163953Srrs			/* Move out all we can */
5685163953Srrs			cp_len = (int)uio->uio_resid;
5686165647Srrs			my_len = (int)SCTP_BUF_LEN(m);
5687163953Srrs			if (cp_len > my_len) {
5688163953Srrs				/* not enough in this buf */
5689163953Srrs				cp_len = my_len;
5690163953Srrs			}
5691163953Srrs			if (hold_rlock) {
5692163953Srrs				SCTP_INP_READ_UNLOCK(inp);
5693163953Srrs				hold_rlock = 0;
5694163953Srrs			}
5695163953Srrs			if (cp_len > 0)
5696163953Srrs				error = uiomove(mtod(m, char *), cp_len, uio);
5697163953Srrs			/* re-read */
5698163953Srrs			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
5699163953Srrs				goto release;
5700163953Srrs			}
5701170138Srrs			if ((control->do_not_ref_stcb == 0) && stcb &&
5702163953Srrs			    stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
5703163953Srrs				no_rcv_needed = 1;
5704163953Srrs			}
5705163953Srrs			if (error) {
5706163953Srrs				/* error we are out of here */
5707163953Srrs				goto release;
5708163953Srrs			}
5709165647Srrs			if ((SCTP_BUF_NEXT(m) == NULL) &&
5710165647Srrs			    (cp_len >= SCTP_BUF_LEN(m)) &&
5711163953Srrs			    ((control->end_added == 0) ||
5712170138Srrs			    (control->end_added &&
5713170138Srrs			    (TAILQ_NEXT(control, next) == NULL)))
5714163953Srrs			    ) {
5715163953Srrs				SCTP_INP_READ_LOCK(inp);
5716163953Srrs				hold_rlock = 1;
5717163953Srrs			}
5718165647Srrs			if (cp_len == SCTP_BUF_LEN(m)) {
5719165647Srrs				if ((SCTP_BUF_NEXT(m) == NULL) &&
5720165647Srrs				    (control->end_added)) {
5721163953Srrs					out_flags |= MSG_EOR;
5722212225Srrs					if ((control->do_not_ref_stcb == 0) &&
5723212225Srrs					    (control->stcb != NULL) &&
5724212225Srrs					    ((control->spec_flags & M_NOTIFICATION) == 0))
5725168961Srrs						control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
5726163953Srrs				}
5727165647Srrs				if (control->spec_flags & M_NOTIFICATION) {
5728163953Srrs					out_flags |= MSG_NOTIFICATION;
5729163953Srrs				}
5730163953Srrs				/* we ate up the mbuf */
5731163953Srrs				if (in_flags & MSG_PEEK) {
5732163953Srrs					/* just looking */
5733165647Srrs					m = SCTP_BUF_NEXT(m);
5734163953Srrs					copied_so_far += cp_len;
5735163953Srrs				} else {
5736163953Srrs					/* dispose of the mbuf */
5737179783Srrs					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
5738170744Srrs						sctp_sblog(&so->so_rcv,
5739170744Srrs						    control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m));
5740170744Srrs					}
5741163953Srrs					sctp_sbfree(control, stcb, &so->so_rcv, m);
5742179783Srrs					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
5743170744Srrs						sctp_sblog(&so->so_rcv,
5744170744Srrs						    control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0);
5745170744Srrs					}
5746163953Srrs					copied_so_far += cp_len;
5747163953Srrs					freed_so_far += cp_len;
5748171943Srrs					freed_so_far += MSIZE;
5749171477Srrs					atomic_subtract_int(&control->length, cp_len);
5750163953Srrs					control->data = sctp_m_free(m);
5751163953Srrs					m = control->data;
5752163953Srrs					/*
5753163953Srrs					 * been through it all, must hold sb
5754163953Srrs					 * lock ok to null tail
5755163953Srrs					 */
5756163953Srrs					if (control->data == NULL) {
5757165220Srrs#ifdef INVARIANTS
5758163953Srrs						if ((control->end_added == 0) ||
5759163953Srrs						    (TAILQ_NEXT(control, next) == NULL)) {
5760163953Srrs							/*
5761163953Srrs							 * If the end is not
5762163953Srrs							 * added, OR the
5763163953Srrs							 * next is NOT null
5764163953Srrs							 * we MUST have the
5765163953Srrs							 * lock.
5766163953Srrs							 */
5767163953Srrs							if (mtx_owned(&inp->inp_rdata_mtx) == 0) {
5768163953Srrs								panic("Hmm we don't own the lock?");
5769163953Srrs							}
5770163953Srrs						}
5771163953Srrs#endif
5772163953Srrs						control->tail_mbuf = NULL;
5773165220Srrs#ifdef INVARIANTS
5774163953Srrs						if ((control->end_added) && ((out_flags & MSG_EOR) == 0)) {
5775163953Srrs							panic("end_added, nothing left and no MSG_EOR");
5776163953Srrs						}
5777163953Srrs#endif
5778163953Srrs					}
5779163953Srrs				}
5780163953Srrs			} else {
5781163953Srrs				/* Do we need to trim the mbuf? */
5782165647Srrs				if (control->spec_flags & M_NOTIFICATION) {
5783163953Srrs					out_flags |= MSG_NOTIFICATION;
5784163953Srrs				}
5785163953Srrs				if ((in_flags & MSG_PEEK) == 0) {
5786165647Srrs					SCTP_BUF_RESV_UF(m, cp_len);
5787165647Srrs					SCTP_BUF_LEN(m) -= cp_len;
5788179783Srrs					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
5789170744Srrs						sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, cp_len);
5790170744Srrs					}
5791163953Srrs					atomic_subtract_int(&so->so_rcv.sb_cc, cp_len);
5792170138Srrs					if ((control->do_not_ref_stcb == 0) &&
5793170138Srrs					    stcb) {
5794163953Srrs						atomic_subtract_int(&stcb->asoc.sb_cc, cp_len);
5795163953Srrs					}
5796163953Srrs					copied_so_far += cp_len;
5797163953Srrs					freed_so_far += cp_len;
5798171943Srrs					freed_so_far += MSIZE;
5799179783Srrs					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
5800170744Srrs						sctp_sblog(&so->so_rcv, control->do_not_ref_stcb ? NULL : stcb,
5801170744Srrs						    SCTP_LOG_SBRESULT, 0);
5802170744Srrs					}
5803171477Srrs					atomic_subtract_int(&control->length, cp_len);
5804163953Srrs				} else {
5805163953Srrs					copied_so_far += cp_len;
5806163953Srrs				}
5807163953Srrs			}
5808170056Srrs			if ((out_flags & MSG_EOR) || (uio->uio_resid == 0)) {
5809163953Srrs				break;
5810163953Srrs			}
5811163953Srrs			if (((stcb) && (in_flags & MSG_PEEK) == 0) &&
5812163953Srrs			    (control->do_not_ref_stcb == 0) &&
5813163953Srrs			    (freed_so_far >= rwnd_req)) {
5814163953Srrs				sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
5815163953Srrs			}
5816163953Srrs		}		/* end while(m) */
5817163953Srrs		/*
5818163953Srrs		 * At this point we have looked at it all and we either have
5819163953Srrs		 * a MSG_EOR/or read all the user wants... <OR>
5820163953Srrs		 * control->length == 0.
5821163953Srrs		 */
5822170056Srrs		if ((out_flags & MSG_EOR) && ((in_flags & MSG_PEEK) == 0)) {
5823163953Srrs			/* we are done with this control */
5824163953Srrs			if (control->length == 0) {
5825163953Srrs				if (control->data) {
5826165220Srrs#ifdef INVARIANTS
5827163953Srrs					panic("control->data not null at read eor?");
5828163953Srrs#else
5829169420Srrs					SCTP_PRINTF("Strange, data left in the control buffer .. invarients would panic?\n");
5830163953Srrs					sctp_m_freem(control->data);
5831163953Srrs					control->data = NULL;
5832163953Srrs#endif
5833163953Srrs				}
5834163953Srrs		done_with_control:
5835163953Srrs				if (TAILQ_NEXT(control, next) == NULL) {
5836163953Srrs					/*
5837163953Srrs					 * If we don't have a next we need a
5838172703Srrs					 * lock, if there is a next
5839172703Srrs					 * interrupt is filling ahead of us
5840172703Srrs					 * and we don't need a lock to
5841172703Srrs					 * remove this guy (which is the
5842172703Srrs					 * head of the queue).
5843163953Srrs					 */
5844163953Srrs					if (hold_rlock == 0) {
5845163953Srrs						SCTP_INP_READ_LOCK(inp);
5846163953Srrs						hold_rlock = 1;
5847163953Srrs					}
5848163953Srrs				}
5849163953Srrs				TAILQ_REMOVE(&inp->read_queue, control, next);
5850163953Srrs				/* Add back any hiddend data */
5851163953Srrs				if (control->held_length) {
5852163953Srrs					held_length = 0;
5853163953Srrs					control->held_length = 0;
5854163953Srrs					wakeup_read_socket = 1;
5855163953Srrs				}
5856169352Srrs				if (control->aux_data) {
5857169352Srrs					sctp_m_free(control->aux_data);
5858169352Srrs					control->aux_data = NULL;
5859169352Srrs				}
5860163953Srrs				no_rcv_needed = control->do_not_ref_stcb;
5861163953Srrs				sctp_free_remote_addr(control->whoFrom);
5862163953Srrs				control->data = NULL;
5863163953Srrs				sctp_free_a_readq(stcb, control);
5864163953Srrs				control = NULL;
5865170138Srrs				if ((freed_so_far >= rwnd_req) &&
5866170138Srrs				    (no_rcv_needed == 0))
5867163953Srrs					sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
5868163953Srrs
5869163953Srrs			} else {
5870163953Srrs				/*
5871163953Srrs				 * The user did not read all of this
5872163953Srrs				 * message, turn off the returned MSG_EOR
5873163953Srrs				 * since we are leaving more behind on the
5874163953Srrs				 * control to read.
5875163953Srrs				 */
5876165220Srrs#ifdef INVARIANTS
5877170138Srrs				if (control->end_added &&
5878170138Srrs				    (control->data == NULL) &&
5879163953Srrs				    (control->tail_mbuf == NULL)) {
5880163953Srrs					panic("Gak, control->length is corrupt?");
5881163953Srrs				}
5882163953Srrs#endif
5883163953Srrs				no_rcv_needed = control->do_not_ref_stcb;
5884163953Srrs				out_flags &= ~MSG_EOR;
5885163953Srrs			}
5886163953Srrs		}
5887163953Srrs		if (out_flags & MSG_EOR) {
5888163953Srrs			goto release;
5889163953Srrs		}
5890163953Srrs		if ((uio->uio_resid == 0) ||
5891266068Stuexen		    ((in_eeor_mode) &&
5892266068Stuexen		    (copied_so_far >= (uint32_t) max(so->so_rcv.sb_lowat, 1)))) {
5893163953Srrs			goto release;
5894163953Srrs		}
5895163953Srrs		/*
5896163953Srrs		 * If I hit here the receiver wants more and this message is
5897163953Srrs		 * NOT done (pd-api). So two questions. Can we block? if not
5898163953Srrs		 * we are done. Did the user NOT set MSG_WAITALL?
5899163953Srrs		 */
5900163953Srrs		if (block_allowed == 0) {
5901163953Srrs			goto release;
5902163953Srrs		}
5903163953Srrs		/*
5904163953Srrs		 * We need to wait for more data a few things: - We don't
5905163953Srrs		 * sbunlock() so we don't get someone else reading. - We
5906163953Srrs		 * must be sure to account for the case where what is added
5907163953Srrs		 * is NOT to our control when we wakeup.
5908163953Srrs		 */
5909163953Srrs
5910163953Srrs		/*
5911163953Srrs		 * Do we need to tell the transport a rwnd update might be
5912163953Srrs		 * needed before we go to sleep?
5913163953Srrs		 */
5914163953Srrs		if (((stcb) && (in_flags & MSG_PEEK) == 0) &&
5915163953Srrs		    ((freed_so_far >= rwnd_req) &&
5916163953Srrs		    (control->do_not_ref_stcb == 0) &&
5917163953Srrs		    (no_rcv_needed == 0))) {
5918163953Srrs			sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
5919163953Srrs		}
5920163953Srrswait_some_more:
5921166023Srrs		if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
5922163953Srrs			goto release;
5923163953Srrs		}
5924163953Srrs		if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)
5925163953Srrs			goto release;
5926163953Srrs
5927163953Srrs		if (hold_rlock == 1) {
5928163953Srrs			SCTP_INP_READ_UNLOCK(inp);
5929163953Srrs			hold_rlock = 0;
5930163953Srrs		}
5931163953Srrs		if (hold_sblock == 0) {
5932163953Srrs			SOCKBUF_LOCK(&so->so_rcv);
5933163953Srrs			hold_sblock = 1;
5934163953Srrs		}
5935172091Srrs		if ((copied_so_far) && (control->length == 0) &&
5936206137Stuexen		    (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE))) {
5937172091Srrs			goto release;
5938172091Srrs		}
5939163953Srrs		if (so->so_rcv.sb_cc <= control->held_length) {
5940163953Srrs			error = sbwait(&so->so_rcv);
5941163953Srrs			if (error) {
5942163953Srrs				goto release;
5943163953Srrs			}
5944163953Srrs			control->held_length = 0;
5945163953Srrs		}
5946163953Srrs		if (hold_sblock) {
5947163953Srrs			SOCKBUF_UNLOCK(&so->so_rcv);
5948163953Srrs			hold_sblock = 0;
5949163953Srrs		}
5950163953Srrs		if (control->length == 0) {
5951163953Srrs			/* still nothing here */
5952163953Srrs			if (control->end_added == 1) {
5953163953Srrs				/* he aborted, or is done i.e.did a shutdown */
5954163953Srrs				out_flags |= MSG_EOR;
5955168943Srrs				if (control->pdapi_aborted) {
5956169295Srrs					if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0))
5957168961Srrs						control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
5958168943Srrs
5959164085Srrs					out_flags |= MSG_TRUNC;
5960168943Srrs				} else {
5961169295Srrs					if ((control->do_not_ref_stcb == 0) && ((control->spec_flags & M_NOTIFICATION) == 0))
5962168961Srrs						control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
5963168943Srrs				}
5964163953Srrs				goto done_with_control;
5965163953Srrs			}
5966163953Srrs			if (so->so_rcv.sb_cc > held_length) {
5967163953Srrs				control->held_length = so->so_rcv.sb_cc;
5968163953Srrs				held_length = 0;
5969163953Srrs			}
5970163953Srrs			goto wait_some_more;
5971163953Srrs		} else if (control->data == NULL) {
5972163996Srrs			/*
5973163996Srrs			 * we must re-sync since data is probably being
5974163996Srrs			 * added
5975163996Srrs			 */
5976163996Srrs			SCTP_INP_READ_LOCK(inp);
5977163996Srrs			if ((control->length > 0) && (control->data == NULL)) {
5978163996Srrs				/*
5979163996Srrs				 * big trouble.. we have the lock and its
5980163996Srrs				 * corrupt?
5981163996Srrs				 */
5982174323Srrs#ifdef INVARIANTS
5983163996Srrs				panic("Impossible data==NULL length !=0");
5984174323Srrs#endif
5985174323Srrs				out_flags |= MSG_EOR;
5986174323Srrs				out_flags |= MSG_TRUNC;
5987174323Srrs				control->length = 0;
5988174323Srrs				SCTP_INP_READ_UNLOCK(inp);
5989174323Srrs				goto done_with_control;
5990163996Srrs			}
5991163996Srrs			SCTP_INP_READ_UNLOCK(inp);
5992163996Srrs			/* We will fall around to get more data */
5993163953Srrs		}
5994163953Srrs		goto get_more_data;
5995163953Srrs	} else {
5996169352Srrs		/*-
5997169352Srrs		 * Give caller back the mbuf chain,
5998169352Srrs		 * store in uio_resid the length
5999163953Srrs		 */
6000169352Srrs		wakeup_read_socket = 0;
6001169352Srrs		if ((control->end_added == 0) ||
6002169352Srrs		    (TAILQ_NEXT(control, next) == NULL)) {
6003169352Srrs			/* Need to get rlock */
6004169352Srrs			if (hold_rlock == 0) {
6005169352Srrs				SCTP_INP_READ_LOCK(inp);
6006169352Srrs				hold_rlock = 1;
6007163953Srrs			}
6008169352Srrs		}
6009169352Srrs		if (control->end_added) {
6010169352Srrs			out_flags |= MSG_EOR;
6011231039Stuexen			if ((control->do_not_ref_stcb == 0) &&
6012231039Stuexen			    (control->stcb != NULL) &&
6013231039Stuexen			    ((control->spec_flags & M_NOTIFICATION) == 0))
6014169352Srrs				control->stcb->asoc.strmin[control->sinfo_stream].delivery_started = 0;
6015169352Srrs		}
6016169352Srrs		if (control->spec_flags & M_NOTIFICATION) {
6017169352Srrs			out_flags |= MSG_NOTIFICATION;
6018169352Srrs		}
6019169352Srrs		uio->uio_resid = control->length;
6020169352Srrs		*mp = control->data;
6021169352Srrs		m = control->data;
6022169352Srrs		while (m) {
6023179783Srrs			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
6024170744Srrs				sctp_sblog(&so->so_rcv,
6025170744Srrs				    control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBFREE, SCTP_BUF_LEN(m));
6026170744Srrs			}
6027169352Srrs			sctp_sbfree(control, stcb, &so->so_rcv, m);
6028169352Srrs			freed_so_far += SCTP_BUF_LEN(m);
6029171943Srrs			freed_so_far += MSIZE;
6030179783Srrs			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_SB_LOGGING_ENABLE) {
6031170744Srrs				sctp_sblog(&so->so_rcv,
6032170744Srrs				    control->do_not_ref_stcb ? NULL : stcb, SCTP_LOG_SBRESULT, 0);
6033170744Srrs			}
6034169352Srrs			m = SCTP_BUF_NEXT(m);
6035163953Srrs		}
6036169352Srrs		control->data = control->tail_mbuf = NULL;
6037169352Srrs		control->length = 0;
6038169352Srrs		if (out_flags & MSG_EOR) {
6039169352Srrs			/* Done with this control */
6040169352Srrs			goto done_with_control;
6041169352Srrs		}
6042163953Srrs	}
6043163953Srrsrelease:
6044163953Srrs	if (hold_rlock == 1) {
6045163953Srrs		SCTP_INP_READ_UNLOCK(inp);
6046163953Srrs		hold_rlock = 0;
6047163953Srrs	}
6048169236Srwatson	if (hold_sblock == 1) {
6049169236Srwatson		SOCKBUF_UNLOCK(&so->so_rcv);
6050169236Srwatson		hold_sblock = 0;
6051163953Srrs	}
6052163953Srrs	sbunlock(&so->so_rcv);
6053169236Srwatson	sockbuf_lock = 0;
6054163953Srrs
6055163953Srrsrelease_unlocked:
6056163953Srrs	if (hold_sblock) {
6057163953Srrs		SOCKBUF_UNLOCK(&so->so_rcv);
6058163953Srrs		hold_sblock = 0;
6059163953Srrs	}
6060163953Srrs	if ((stcb) && (in_flags & MSG_PEEK) == 0) {
6061163953Srrs		if ((freed_so_far >= rwnd_req) &&
6062163953Srrs		    (control && (control->do_not_ref_stcb == 0)) &&
6063163953Srrs		    (no_rcv_needed == 0))
6064163953Srrs			sctp_user_rcvd(stcb, &freed_so_far, hold_rlock, rwnd_req);
6065163953Srrs	}
6066184031Srrsout:
6067184031Srrs	if (msg_flags) {
6068174323Srrs		*msg_flags = out_flags;
6069184031Srrs	}
6070168943Srrs	if (((out_flags & MSG_EOR) == 0) &&
6071168943Srrs	    ((in_flags & MSG_PEEK) == 0) &&
6072168943Srrs	    (sinfo) &&
6073223132Stuexen	    (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) ||
6074223132Stuexen	    sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO))) {
6075168943Srrs		struct sctp_extrcvinfo *s_extra;
6076168943Srrs
6077168943Srrs		s_extra = (struct sctp_extrcvinfo *)sinfo;
6078168943Srrs		s_extra->sreinfo_next_flags = SCTP_NO_NEXT_MSG;
6079168943Srrs	}
6080163953Srrs	if (hold_rlock == 1) {
6081163953Srrs		SCTP_INP_READ_UNLOCK(inp);
6082163953Srrs	}
6083163953Srrs	if (hold_sblock) {
6084163953Srrs		SOCKBUF_UNLOCK(&so->so_rcv);
6085163953Srrs	}
6086169236Srwatson	if (sockbuf_lock) {
6087169236Srwatson		sbunlock(&so->so_rcv);
6088169236Srwatson	}
6089163996Srrs	if (freecnt_applied) {
6090163953Srrs		/*
6091163953Srrs		 * The lock on the socket buffer protects us so the free
6092163953Srrs		 * code will stop. But since we used the socketbuf lock and
6093163953Srrs		 * the sender uses the tcb_lock to increment, we need to use
6094163953Srrs		 * the atomic add to the refcnt.
6095163953Srrs		 */
6096163996Srrs		if (stcb == NULL) {
6097182367Srrs#ifdef INVARIANTS
6098163996Srrs			panic("stcb for refcnt has gone NULL?");
6099182367Srrs			goto stage_left;
6100182367Srrs#else
6101182367Srrs			goto stage_left;
6102182367Srrs#endif
6103163996Srrs		}
6104163996Srrs		atomic_add_int(&stcb->asoc.refcnt, -1);
6105163953Srrs		/* Save the value back for next time */
6106163953Srrs		stcb->freed_by_sorcv_sincelast = freed_so_far;
6107163953Srrs	}
6108179783Srrs	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_RECV_RWND_LOGGING_ENABLE) {
6109170744Srrs		if (stcb) {
6110170744Srrs			sctp_misc_ints(SCTP_SORECV_DONE,
6111170744Srrs			    freed_so_far,
6112170744Srrs			    ((uio) ? (slen - uio->uio_resid) : slen),
6113170744Srrs			    stcb->asoc.my_rwnd,
6114170744Srrs			    so->so_rcv.sb_cc);
6115170744Srrs		} else {
6116170744Srrs			sctp_misc_ints(SCTP_SORECV_DONE,
6117170744Srrs			    freed_so_far,
6118170744Srrs			    ((uio) ? (slen - uio->uio_resid) : slen),
6119170744Srrs			    0,
6120170744Srrs			    so->so_rcv.sb_cc);
6121170744Srrs		}
6122163953Srrs	}
6123182367Srrsstage_left:
6124163953Srrs	if (wakeup_read_socket) {
6125163953Srrs		sctp_sorwakeup(inp, so);
6126163953Srrs	}
6127163953Srrs	return (error);
6128163953Srrs}
6129163953Srrs
6130163953Srrs
6131163953Srrs#ifdef SCTP_MBUF_LOGGING
6132163953Srrsstruct mbuf *
6133163953Srrssctp_m_free(struct mbuf *m)
6134163953Srrs{
6135179783Srrs	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
6136170744Srrs		if (SCTP_BUF_IS_EXTENDED(m)) {
6137170744Srrs			sctp_log_mb(m, SCTP_MBUF_IFREE);
6138170744Srrs		}
6139163953Srrs	}
6140163953Srrs	return (m_free(m));
6141163953Srrs}
6142163953Srrs
6143163953Srrsvoid
6144163953Srrssctp_m_freem(struct mbuf *mb)
6145163953Srrs{
6146163953Srrs	while (mb != NULL)
6147163953Srrs		mb = sctp_m_free(mb);
6148163953Srrs}
6149163953Srrs
6150163953Srrs#endif
6151163953Srrs
6152167598Srrsint
6153167598Srrssctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
6154167598Srrs{
6155167598Srrs	/*
6156167598Srrs	 * Given a local address. For all associations that holds the
6157167598Srrs	 * address, request a peer-set-primary.
6158167598Srrs	 */
6159167598Srrs	struct sctp_ifa *ifa;
6160167598Srrs	struct sctp_laddr *wi;
6161163953Srrs
6162167598Srrs	ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
6163167598Srrs	if (ifa == NULL) {
6164171943Srrs		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, EADDRNOTAVAIL);
6165167598Srrs		return (EADDRNOTAVAIL);
6166167598Srrs	}
6167167598Srrs	/*
6168167598Srrs	 * Now that we have the ifa we must awaken the iterator with this
6169167598Srrs	 * message.
6170167598Srrs	 */
6171179783Srrs	wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr);
6172167598Srrs	if (wi == NULL) {
6173171943Srrs		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
6174167598Srrs		return (ENOMEM);
6175167598Srrs	}
6176167598Srrs	/* Now incr the count and int wi structure */
6177167598Srrs	SCTP_INCR_LADDR_COUNT();
6178167598Srrs	bzero(wi, sizeof(*wi));
6179170056Srrs	(void)SCTP_GETTIME_TIMEVAL(&wi->start_time);
6180167598Srrs	wi->ifa = ifa;
6181167598Srrs	wi->action = SCTP_SET_PRIM_ADDR;
6182167598Srrs	atomic_add_int(&ifa->refcount, 1);
6183167598Srrs
6184167598Srrs	/* Now add it to the work queue */
6185208160Srrs	SCTP_WQ_ADDR_LOCK();
6186167598Srrs	/*
6187167598Srrs	 * Should this really be a tailq? As it is we will process the
6188167598Srrs	 * newest first :-0
6189167598Srrs	 */
6190179783Srrs	LIST_INSERT_HEAD(&SCTP_BASE_INFO(addr_wq), wi, sctp_nxt_addr);
6191208160Srrs	SCTP_WQ_ADDR_UNLOCK();
6192167598Srrs	sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
6193167598Srrs	    (struct sctp_inpcb *)NULL,
6194167598Srrs	    (struct sctp_tcb *)NULL,
6195167598Srrs	    (struct sctp_nets *)NULL);
6196167598Srrs	return (0);
6197167598Srrs}
6198167598Srrs
6199167598Srrs
6200163953Srrsint
6201169352Srrssctp_soreceive(struct socket *so,
6202169352Srrs    struct sockaddr **psa,
6203169352Srrs    struct uio *uio,
6204169352Srrs    struct mbuf **mp0,
6205169352Srrs    struct mbuf **controlp,
6206169352Srrs    int *flagsp)
6207163953Srrs{
6208163953Srrs	int error, fromlen;
6209163953Srrs	uint8_t sockbuf[256];
6210163953Srrs	struct sockaddr *from;
6211163953Srrs	struct sctp_extrcvinfo sinfo;
6212163953Srrs	int filling_sinfo = 1;
6213163953Srrs	struct sctp_inpcb *inp;
6214163953Srrs
6215163953Srrs	inp = (struct sctp_inpcb *)so->so_pcb;
6216163953Srrs	/* pickup the assoc we are reading from */
6217163953Srrs	if (inp == NULL) {
6218171943Srrs		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6219163953Srrs		return (EINVAL);
6220163953Srrs	}
6221223132Stuexen	if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) &&
6222223132Stuexen	    sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
6223223132Stuexen	    sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) ||
6224163953Srrs	    (controlp == NULL)) {
6225163953Srrs		/* user does not want the sndrcv ctl */
6226163953Srrs		filling_sinfo = 0;
6227163953Srrs	}
6228163953Srrs	if (psa) {
6229163953Srrs		from = (struct sockaddr *)sockbuf;
6230163953Srrs		fromlen = sizeof(sockbuf);
6231163953Srrs		from->sa_len = 0;
6232163953Srrs	} else {
6233163953Srrs		from = NULL;
6234163953Srrs		fromlen = 0;
6235163953Srrs	}
6236163953Srrs
6237268433Sdelphij	if (filling_sinfo) {
6238268433Sdelphij		memset(&sinfo, 0, sizeof(struct sctp_extrcvinfo));
6239268433Sdelphij	}
6240163953Srrs	error = sctp_sorecvmsg(so, uio, mp0, from, fromlen, flagsp,
6241163953Srrs	    (struct sctp_sndrcvinfo *)&sinfo, filling_sinfo);
6242268433Sdelphij	if (controlp != NULL) {
6243163953Srrs		/* copy back the sinfo in a CMSG format */
6244163953Srrs		if (filling_sinfo)
6245163953Srrs			*controlp = sctp_build_ctl_nchunk(inp,
6246163953Srrs			    (struct sctp_sndrcvinfo *)&sinfo);
6247163953Srrs		else
6248163953Srrs			*controlp = NULL;
6249163953Srrs	}
6250163953Srrs	if (psa) {
6251163953Srrs		/* copy back the address info */
6252163953Srrs		if (from && from->sa_len) {
6253163953Srrs			*psa = sodupsockaddr(from, M_NOWAIT);
6254163953Srrs		} else {
6255163953Srrs			*psa = NULL;
6256163953Srrs		}
6257163953Srrs	}
6258163953Srrs	return (error);
6259163953Srrs}
6260169352Srrs
6261169352Srrs
6262169352Srrs
6263169352Srrs
6264169352Srrs
6265169352Srrsint
6266170056Srrssctp_connectx_helper_add(struct sctp_tcb *stcb, struct sockaddr *addr,
6267170056Srrs    int totaddr, int *error)
6268169352Srrs{
6269169352Srrs	int added = 0;
6270169352Srrs	int i;
6271169352Srrs	struct sctp_inpcb *inp;
6272169352Srrs	struct sockaddr *sa;
6273169352Srrs	size_t incr = 0;
6274169352Srrs
6275225571Stuexen#ifdef INET
6276225571Stuexen	struct sockaddr_in *sin;
6277225571Stuexen
6278225571Stuexen#endif
6279225571Stuexen#ifdef INET6
6280225571Stuexen	struct sockaddr_in6 *sin6;
6281225571Stuexen
6282225571Stuexen#endif
6283225571Stuexen
6284169352Srrs	sa = addr;
6285169352Srrs	inp = stcb->sctp_ep;
6286169352Srrs	*error = 0;
6287169352Srrs	for (i = 0; i < totaddr; i++) {
6288221328Stuexen		switch (sa->sa_family) {
6289221328Stuexen#ifdef INET
6290221328Stuexen		case AF_INET:
6291169352Srrs			incr = sizeof(struct sockaddr_in);
6292225571Stuexen			sin = (struct sockaddr_in *)sa;
6293225571Stuexen			if ((sin->sin_addr.s_addr == INADDR_ANY) ||
6294225571Stuexen			    (sin->sin_addr.s_addr == INADDR_BROADCAST) ||
6295225571Stuexen			    IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
6296225571Stuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6297225571Stuexen				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
6298225571Stuexen				*error = EINVAL;
6299225571Stuexen				goto out_now;
6300225571Stuexen			}
6301224641Stuexen			if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
6302169352Srrs				/* assoc gone no un-lock */
6303171943Srrs				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
6304171943Srrs				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
6305169352Srrs				*error = ENOBUFS;
6306169352Srrs				goto out_now;
6307169352Srrs			}
6308169352Srrs			added++;
6309221328Stuexen			break;
6310221328Stuexen#endif
6311221328Stuexen#ifdef INET6
6312221328Stuexen		case AF_INET6:
6313169352Srrs			incr = sizeof(struct sockaddr_in6);
6314225571Stuexen			sin6 = (struct sockaddr_in6 *)sa;
6315225571Stuexen			if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
6316225571Stuexen			    IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
6317225571Stuexen				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6318225571Stuexen				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
6319225571Stuexen				*error = EINVAL;
6320225571Stuexen				goto out_now;
6321225571Stuexen			}
6322224641Stuexen			if (sctp_add_remote_addr(stcb, sa, NULL, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
6323169352Srrs				/* assoc gone no un-lock */
6324171943Srrs				SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOBUFS);
6325171943Srrs				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
6326169352Srrs				*error = ENOBUFS;
6327169352Srrs				goto out_now;
6328169352Srrs			}
6329169352Srrs			added++;
6330221328Stuexen			break;
6331221328Stuexen#endif
6332221328Stuexen		default:
6333221328Stuexen			break;
6334169352Srrs		}
6335169352Srrs		sa = (struct sockaddr *)((caddr_t)sa + incr);
6336169352Srrs	}
6337169352Srrsout_now:
6338169352Srrs	return (added);
6339169352Srrs}
6340169352Srrs
6341169352Srrsstruct sctp_tcb *
6342170056Srrssctp_connectx_helper_find(struct sctp_inpcb *inp, struct sockaddr *addr,
6343170056Srrs    int *totaddr, int *num_v4, int *num_v6, int *error,
6344170056Srrs    int limit, int *bad_addr)
6345169352Srrs{
6346169352Srrs	struct sockaddr *sa;
6347169352Srrs	struct sctp_tcb *stcb = NULL;
6348169352Srrs	size_t incr, at, i;
6349169352Srrs
6350169352Srrs	at = incr = 0;
6351169352Srrs	sa = addr;
6352221328Stuexen
6353169352Srrs	*error = *num_v6 = *num_v4 = 0;
6354169352Srrs	/* account and validate addresses */
6355170140Srrs	for (i = 0; i < (size_t)*totaddr; i++) {
6356221328Stuexen		switch (sa->sa_family) {
6357221328Stuexen#ifdef INET
6358221328Stuexen		case AF_INET:
6359169352Srrs			(*num_v4) += 1;
6360169352Srrs			incr = sizeof(struct sockaddr_in);
6361170056Srrs			if (sa->sa_len != incr) {
6362171943Srrs				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6363170056Srrs				*error = EINVAL;
6364170056Srrs				*bad_addr = 1;
6365170056Srrs				return (NULL);
6366170056Srrs			}
6367221328Stuexen			break;
6368221328Stuexen#endif
6369221328Stuexen#ifdef INET6
6370221328Stuexen		case AF_INET6:
6371221328Stuexen			{
6372221328Stuexen				struct sockaddr_in6 *sin6;
6373169352Srrs
6374221328Stuexen				sin6 = (struct sockaddr_in6 *)sa;
6375221328Stuexen				if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6376221328Stuexen					/* Must be non-mapped for connectx */
6377221328Stuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6378221328Stuexen					*error = EINVAL;
6379221328Stuexen					*bad_addr = 1;
6380221328Stuexen					return (NULL);
6381221328Stuexen				}
6382221328Stuexen				(*num_v6) += 1;
6383221328Stuexen				incr = sizeof(struct sockaddr_in6);
6384221328Stuexen				if (sa->sa_len != incr) {
6385221328Stuexen					SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6386221328Stuexen					*error = EINVAL;
6387221328Stuexen					*bad_addr = 1;
6388221328Stuexen					return (NULL);
6389221328Stuexen				}
6390221328Stuexen				break;
6391169352Srrs			}
6392221328Stuexen#endif
6393221328Stuexen		default:
6394169352Srrs			*totaddr = i;
6395169352Srrs			/* we are done */
6396169352Srrs			break;
6397169352Srrs		}
6398221328Stuexen		if (i == (size_t)*totaddr) {
6399221328Stuexen			break;
6400221328Stuexen		}
6401170056Srrs		SCTP_INP_INCR_REF(inp);
6402169352Srrs		stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL);
6403169352Srrs		if (stcb != NULL) {
6404169352Srrs			/* Already have or am bring up an association */
6405169352Srrs			return (stcb);
6406170056Srrs		} else {
6407170056Srrs			SCTP_INP_DECR_REF(inp);
6408169352Srrs		}
6409170140Srrs		if ((at + incr) > (size_t)limit) {
6410169352Srrs			*totaddr = i;
6411169352Srrs			break;
6412169352Srrs		}
6413169352Srrs		sa = (struct sockaddr *)((caddr_t)sa + incr);
6414169352Srrs	}
6415169352Srrs	return ((struct sctp_tcb *)NULL);
6416169352Srrs}
6417170606Srrs
6418170606Srrs/*
6419170606Srrs * sctp_bindx(ADD) for one address.
6420170606Srrs * assumes all arguments are valid/checked by caller.
6421170606Srrs */
6422170606Srrsvoid
6423170606Srrssctp_bindx_add_address(struct socket *so, struct sctp_inpcb *inp,
6424170606Srrs    struct sockaddr *sa, sctp_assoc_t assoc_id,
6425170606Srrs    uint32_t vrf_id, int *error, void *p)
6426170606Srrs{
6427170606Srrs	struct sockaddr *addr_touse;
6428178251Srrs
6429178251Srrs#ifdef INET6
6430170606Srrs	struct sockaddr_in sin;
6431170606Srrs
6432178251Srrs#endif
6433178251Srrs
6434170606Srrs	/* see if we're bound all already! */
6435170606Srrs	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
6436171943Srrs		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6437170606Srrs		*error = EINVAL;
6438170606Srrs		return;
6439170606Srrs	}
6440170606Srrs	addr_touse = sa;
6441221328Stuexen#ifdef INET6
6442170606Srrs	if (sa->sa_family == AF_INET6) {
6443170606Srrs		struct sockaddr_in6 *sin6;
6444170606Srrs
6445170606Srrs		if (sa->sa_len != sizeof(struct sockaddr_in6)) {
6446171943Srrs			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6447170606Srrs			*error = EINVAL;
6448170606Srrs			return;
6449170606Srrs		}
6450170665Srrs		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
6451170665Srrs			/* can only bind v6 on PF_INET6 sockets */
6452171943Srrs			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6453170665Srrs			*error = EINVAL;
6454170665Srrs			return;
6455170665Srrs		}
6456170606Srrs		sin6 = (struct sockaddr_in6 *)addr_touse;
6457170606Srrs		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6458170665Srrs			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
6459170665Srrs			    SCTP_IPV6_V6ONLY(inp)) {
6460170665Srrs				/* can't bind v4-mapped on PF_INET sockets */
6461171943Srrs				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6462170665Srrs				*error = EINVAL;
6463170665Srrs				return;
6464170665Srrs			}
6465170606Srrs			in6_sin6_2_sin(&sin, sin6);
6466170606Srrs			addr_touse = (struct sockaddr *)&sin;
6467170606Srrs		}
6468170606Srrs	}
6469170606Srrs#endif
6470221328Stuexen#ifdef INET
6471170606Srrs	if (sa->sa_family == AF_INET) {
6472170606Srrs		if (sa->sa_len != sizeof(struct sockaddr_in)) {
6473171943Srrs			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6474170606Srrs			*error = EINVAL;
6475170606Srrs			return;
6476170606Srrs		}
6477170665Srrs		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
6478170665Srrs		    SCTP_IPV6_V6ONLY(inp)) {
6479170665Srrs			/* can't bind v4 on PF_INET sockets */
6480171943Srrs			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6481170665Srrs			*error = EINVAL;
6482170665Srrs			return;
6483170665Srrs		}
6484170606Srrs	}
6485221328Stuexen#endif
6486170606Srrs	if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
6487170606Srrs		if (p == NULL) {
6488170606Srrs			/* Can't get proc for Net/Open BSD */
6489171943Srrs			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6490170606Srrs			*error = EINVAL;
6491170606Srrs			return;
6492170606Srrs		}
6493171572Srrs		*error = sctp_inpcb_bind(so, addr_touse, NULL, p);
6494170606Srrs		return;
6495170606Srrs	}
6496170606Srrs	/*
6497170606Srrs	 * No locks required here since bind and mgmt_ep_sa all do their own
6498170606Srrs	 * locking. If we do something for the FIX: below we may need to
6499170606Srrs	 * lock in that case.
6500170606Srrs	 */
6501170606Srrs	if (assoc_id == 0) {
6502170606Srrs		/* add the address */
6503170606Srrs		struct sctp_inpcb *lep;
6504171032Srrs		struct sockaddr_in *lsin = (struct sockaddr_in *)addr_touse;
6505170606Srrs
6506171032Srrs		/* validate the incoming port */
6507171032Srrs		if ((lsin->sin_port != 0) &&
6508171032Srrs		    (lsin->sin_port != inp->sctp_lport)) {
6509171943Srrs			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6510171032Srrs			*error = EINVAL;
6511171032Srrs			return;
6512171032Srrs		} else {
6513171032Srrs			/* user specified 0 port, set it to existing port */
6514171032Srrs			lsin->sin_port = inp->sctp_lport;
6515171032Srrs		}
6516171032Srrs
6517170606Srrs		lep = sctp_pcb_findep(addr_touse, 1, 0, vrf_id);
6518170606Srrs		if (lep != NULL) {
6519170606Srrs			/*
6520170606Srrs			 * We must decrement the refcount since we have the
6521170606Srrs			 * ep already and are binding. No remove going on
6522170606Srrs			 * here.
6523170606Srrs			 */
6524181054Srrs			SCTP_INP_DECR_REF(lep);
6525170606Srrs		}
6526170606Srrs		if (lep == inp) {
6527170606Srrs			/* already bound to it.. ok */
6528170606Srrs			return;
6529170606Srrs		} else if (lep == NULL) {
6530170606Srrs			((struct sockaddr_in *)addr_touse)->sin_port = 0;
6531170606Srrs			*error = sctp_addr_mgmt_ep_sa(inp, addr_touse,
6532170606Srrs			    SCTP_ADD_IP_ADDRESS,
6533170744Srrs			    vrf_id, NULL);
6534170606Srrs		} else {
6535170606Srrs			*error = EADDRINUSE;
6536170606Srrs		}
6537170606Srrs		if (*error)
6538170606Srrs			return;
6539170606Srrs	} else {
6540170606Srrs		/*
6541170606Srrs		 * FIX: decide whether we allow assoc based bindx
6542170606Srrs		 */
6543170606Srrs	}
6544170606Srrs}
6545170606Srrs
6546170606Srrs/*
6547170606Srrs * sctp_bindx(DELETE) for one address.
6548170606Srrs * assumes all arguments are valid/checked by caller.
6549170606Srrs */
6550170606Srrsvoid
6551231038Stuexensctp_bindx_delete_address(struct sctp_inpcb *inp,
6552170606Srrs    struct sockaddr *sa, sctp_assoc_t assoc_id,
6553170606Srrs    uint32_t vrf_id, int *error)
6554170606Srrs{
6555170606Srrs	struct sockaddr *addr_touse;
6556178251Srrs
6557178251Srrs#ifdef INET6
6558170606Srrs	struct sockaddr_in sin;
6559170606Srrs
6560178251Srrs#endif
6561178251Srrs
6562170606Srrs	/* see if we're bound all already! */
6563170606Srrs	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
6564171943Srrs		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6565170606Srrs		*error = EINVAL;
6566170606Srrs		return;
6567170606Srrs	}
6568170606Srrs	addr_touse = sa;
6569238578Stuexen#ifdef INET6
6570170606Srrs	if (sa->sa_family == AF_INET6) {
6571170606Srrs		struct sockaddr_in6 *sin6;
6572170606Srrs
6573170606Srrs		if (sa->sa_len != sizeof(struct sockaddr_in6)) {
6574171943Srrs			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6575170606Srrs			*error = EINVAL;
6576170606Srrs			return;
6577170606Srrs		}
6578170665Srrs		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
6579170665Srrs			/* can only bind v6 on PF_INET6 sockets */
6580171943Srrs			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6581170665Srrs			*error = EINVAL;
6582170665Srrs			return;
6583170665Srrs		}
6584170606Srrs		sin6 = (struct sockaddr_in6 *)addr_touse;
6585170606Srrs		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6586170665Srrs			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
6587170665Srrs			    SCTP_IPV6_V6ONLY(inp)) {
6588170665Srrs				/* can't bind mapped-v4 on PF_INET sockets */
6589171943Srrs				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6590170665Srrs				*error = EINVAL;
6591170665Srrs				return;
6592170665Srrs			}
6593170606Srrs			in6_sin6_2_sin(&sin, sin6);
6594170606Srrs			addr_touse = (struct sockaddr *)&sin;
6595170606Srrs		}
6596170606Srrs	}
6597170606Srrs#endif
6598221328Stuexen#ifdef INET
6599170606Srrs	if (sa->sa_family == AF_INET) {
6600170606Srrs		if (sa->sa_len != sizeof(struct sockaddr_in)) {
6601171943Srrs			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6602170606Srrs			*error = EINVAL;
6603170606Srrs			return;
6604170606Srrs		}
6605170665Srrs		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
6606170665Srrs		    SCTP_IPV6_V6ONLY(inp)) {
6607170665Srrs			/* can't bind v4 on PF_INET sockets */
6608171943Srrs			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
6609170665Srrs			*error = EINVAL;
6610170665Srrs			return;
6611170665Srrs		}
6612170606Srrs	}
6613221328Stuexen#endif
6614170606Srrs	/*
6615170606Srrs	 * No lock required mgmt_ep_sa does its own locking. If the FIX:
6616170606Srrs	 * below is ever changed we may need to lock before calling
6617170606Srrs	 * association level binding.
6618170606Srrs	 */
6619170606Srrs	if (assoc_id == 0) {
6620170606Srrs		/* delete the address */
6621170606Srrs		*error = sctp_addr_mgmt_ep_sa(inp, addr_touse,
6622170606Srrs		    SCTP_DEL_IP_ADDRESS,
6623170744Srrs		    vrf_id, NULL);
6624170606Srrs	} else {
6625170606Srrs		/*
6626170606Srrs		 * FIX: decide whether we allow assoc based bindx
6627170606Srrs		 */
6628170606Srrs	}
6629170606Srrs}
6630171572Srrs
6631171572Srrs/*
6632171572Srrs * returns the valid local address count for an assoc, taking into account
6633171572Srrs * all scoping rules
6634171572Srrs */
6635171572Srrsint
6636171572Srrssctp_local_addr_count(struct sctp_tcb *stcb)
6637171572Srrs{
6638266054Stuexen	int loopback_scope;
6639266054Stuexen
6640266054Stuexen#if defined(INET)
6641266054Stuexen	int ipv4_local_scope, ipv4_addr_legal;
6642266054Stuexen
6643266054Stuexen#endif
6644266054Stuexen#if defined (INET6)
6645266054Stuexen	int local_scope, site_scope, ipv6_addr_legal;
6646266054Stuexen
6647266054Stuexen#endif
6648171572Srrs	struct sctp_vrf *vrf;
6649171572Srrs	struct sctp_ifn *sctp_ifn;
6650171572Srrs	struct sctp_ifa *sctp_ifa;
6651171572Srrs	int count = 0;
6652171572Srrs
6653171572Srrs	/* Turn on all the appropriate scopes */
6654252961Stuexen	loopback_scope = stcb->asoc.scope.loopback_scope;
6655266054Stuexen#if defined(INET)
6656252961Stuexen	ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
6657266054Stuexen	ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
6658266054Stuexen#endif
6659266054Stuexen#if defined(INET6)
6660252961Stuexen	local_scope = stcb->asoc.scope.local_scope;
6661252961Stuexen	site_scope = stcb->asoc.scope.site_scope;
6662252961Stuexen	ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
6663266054Stuexen#endif
6664172218Srrs	SCTP_IPI_ADDR_RLOCK();
6665171572Srrs	vrf = sctp_find_vrf(stcb->asoc.vrf_id);
6666171572Srrs	if (vrf == NULL) {
6667171572Srrs		/* no vrf, no addresses */
6668172218Srrs		SCTP_IPI_ADDR_RUNLOCK();
6669171572Srrs		return (0);
6670171572Srrs	}
6671171572Srrs	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
6672171572Srrs		/*
6673171572Srrs		 * bound all case: go through all ifns on the vrf
6674171572Srrs		 */
6675171572Srrs		LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
6676171572Srrs			if ((loopback_scope == 0) &&
6677171572Srrs			    SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
6678171572Srrs				continue;
6679171572Srrs			}
6680171572Srrs			LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
6681171572Srrs				if (sctp_is_addr_restricted(stcb, sctp_ifa))
6682171572Srrs					continue;
6683178251Srrs				switch (sctp_ifa->address.sa.sa_family) {
6684221328Stuexen#ifdef INET
6685178251Srrs				case AF_INET:
6686178251Srrs					if (ipv4_addr_legal) {
6687178251Srrs						struct sockaddr_in *sin;
6688171572Srrs
6689178251Srrs						sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
6690178251Srrs						if (sin->sin_addr.s_addr == 0) {
6691178251Srrs							/*
6692178251Srrs							 * skip unspecified
6693178251Srrs							 * addrs
6694178251Srrs							 */
6695178251Srrs							continue;
6696178251Srrs						}
6697267799Stuexen						if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
6698267799Stuexen						    &sin->sin_addr) != 0) {
6699267799Stuexen							continue;
6700267799Stuexen						}
6701178251Srrs						if ((ipv4_local_scope == 0) &&
6702178251Srrs						    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
6703178251Srrs							continue;
6704178251Srrs						}
6705178251Srrs						/* count this one */
6706178251Srrs						count++;
6707178251Srrs					} else {
6708171572Srrs						continue;
6709171572Srrs					}
6710178251Srrs					break;
6711221328Stuexen#endif
6712178251Srrs#ifdef INET6
6713178251Srrs				case AF_INET6:
6714178251Srrs					if (ipv6_addr_legal) {
6715178251Srrs						struct sockaddr_in6 *sin6;
6716171572Srrs
6717178251Srrs						sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
6718178251Srrs						if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6719171572Srrs							continue;
6720178251Srrs						}
6721267799Stuexen						if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
6722267799Stuexen						    &sin6->sin6_addr) != 0) {
6723267799Stuexen							continue;
6724267799Stuexen						}
6725178251Srrs						if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
6726178251Srrs							if (local_scope == 0)
6727171572Srrs								continue;
6728178251Srrs							if (sin6->sin6_scope_id == 0) {
6729178251Srrs								if (sa6_recoverscope(sin6) != 0)
6730178251Srrs									/*
6731178251Srrs									 *
6732178251Srrs									 * bad
6733178251Srrs									 *
6734178251Srrs									 * li
6735178251Srrs									 * nk
6736178251Srrs									 *
6737178251Srrs									 * loc
6738178251Srrs									 * al
6739178251Srrs									 *
6740178251Srrs									 * add
6741178251Srrs									 * re
6742178251Srrs									 * ss
6743178251Srrs									 * */
6744178251Srrs									continue;
6745178251Srrs							}
6746171572Srrs						}
6747178251Srrs						if ((site_scope == 0) &&
6748178251Srrs						    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
6749178251Srrs							continue;
6750178251Srrs						}
6751178251Srrs						/* count this one */
6752178251Srrs						count++;
6753171572Srrs					}
6754178251Srrs					break;
6755178251Srrs#endif
6756178251Srrs				default:
6757178251Srrs					/* TSNH */
6758178251Srrs					break;
6759171572Srrs				}
6760171572Srrs			}
6761171572Srrs		}
6762171572Srrs	} else {
6763171572Srrs		/*
6764171572Srrs		 * subset bound case
6765171572Srrs		 */
6766171572Srrs		struct sctp_laddr *laddr;
6767171572Srrs
6768171572Srrs		LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list,
6769171572Srrs		    sctp_nxt_addr) {
6770171572Srrs			if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
6771171572Srrs				continue;
6772171572Srrs			}
6773171572Srrs			/* count this one */
6774171572Srrs			count++;
6775171572Srrs		}
6776171572Srrs	}
6777172218Srrs	SCTP_IPI_ADDR_RUNLOCK();
6778171572Srrs	return (count);
6779171572Srrs}
6780171943Srrs
6781171943Srrs#if defined(SCTP_LOCAL_TRACE_BUF)
6782171943Srrs
6783171943Srrsvoid
6784172157Srrssctp_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)
6785171943Srrs{
6786172157Srrs	uint32_t saveindex, newindex;
6787171943Srrs
6788171943Srrs	do {
6789179783Srrs		saveindex = SCTP_BASE_SYSCTL(sctp_log).index;
6790171943Srrs		if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
6791171943Srrs			newindex = 1;
6792171943Srrs		} else {
6793171943Srrs			newindex = saveindex + 1;
6794171943Srrs		}
6795179783Srrs	} while (atomic_cmpset_int(&SCTP_BASE_SYSCTL(sctp_log).index, saveindex, newindex) == 0);
6796171943Srrs	if (saveindex >= SCTP_MAX_LOGGING_SIZE) {
6797171943Srrs		saveindex = 0;
6798171943Srrs	}
6799179783Srrs	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].timestamp = SCTP_GET_CYCLECOUNT;
6800179783Srrs	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].subsys = subsys;
6801179783Srrs	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[0] = a;
6802179783Srrs	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[1] = b;
6803179783Srrs	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[2] = c;
6804179783Srrs	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[3] = d;
6805179783Srrs	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[4] = e;
6806179783Srrs	SCTP_BASE_SYSCTL(sctp_log).entry[saveindex].params[5] = f;
6807171943Srrs}
6808171943Srrs
6809171943Srrs#endif
6810188067Srrsstatic void
6811188067Srrssctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
6812188067Srrs{
6813188067Srrs	struct ip *iph;
6814252944Stuexen
6815252944Stuexen#ifdef INET6
6816252944Stuexen	struct ip6_hdr *ip6;
6817252944Stuexen
6818252944Stuexen#endif
6819188067Srrs	struct mbuf *sp, *last;
6820188067Srrs	struct udphdr *uhdr;
6821237912Stuexen	uint16_t port;
6822188067Srrs
6823188067Srrs	if ((m->m_flags & M_PKTHDR) == 0) {
6824188067Srrs		/* Can't handle one that is not a pkt hdr */
6825188067Srrs		goto out;
6826188067Srrs	}
6827237912Stuexen	/* Pull the src port */
6828188067Srrs	iph = mtod(m, struct ip *);
6829188067Srrs	uhdr = (struct udphdr *)((caddr_t)iph + off);
6830188067Srrs	port = uhdr->uh_sport;
6831237912Stuexen	/*
6832237912Stuexen	 * Split out the mbuf chain. Leave the IP header in m, place the
6833237912Stuexen	 * rest in the sp.
6834237912Stuexen	 */
6835188067Srrs	sp = m_split(m, off, M_DONTWAIT);
6836188067Srrs	if (sp == NULL) {
6837188067Srrs		/* Gak, drop packet, we can't do a split */
6838188067Srrs		goto out;
6839188067Srrs	}
6840237912Stuexen	if (sp->m_pkthdr.len < sizeof(struct udphdr) + sizeof(struct sctphdr)) {
6841237912Stuexen		/* Gak, packet can't have an SCTP header in it - too small */
6842188067Srrs		m_freem(sp);
6843188067Srrs		goto out;
6844188067Srrs	}
6845237912Stuexen	/* Now pull up the UDP header and SCTP header together */
6846237912Stuexen	sp = m_pullup(sp, sizeof(struct udphdr) + sizeof(struct sctphdr));
6847188067Srrs	if (sp == NULL) {
6848188067Srrs		/* Gak pullup failed */
6849188067Srrs		goto out;
6850188067Srrs	}
6851237912Stuexen	/* Trim out the UDP header */
6852188067Srrs	m_adj(sp, sizeof(struct udphdr));
6853188067Srrs
6854188067Srrs	/* Now reconstruct the mbuf chain */
6855237912Stuexen	for (last = m; last->m_next; last = last->m_next);
6856188067Srrs	last->m_next = sp;
6857188067Srrs	m->m_pkthdr.len += sp->m_pkthdr.len;
6858188067Srrs	iph = mtod(m, struct ip *);
6859188067Srrs	switch (iph->ip_v) {
6860221249Stuexen#ifdef INET
6861188067Srrs	case IPVERSION:
6862237912Stuexen		iph->ip_len -= sizeof(struct udphdr);
6863237912Stuexen		sctp_input_with_port(m, off, port);
6864237912Stuexen		break;
6865221249Stuexen#endif
6866188067Srrs#ifdef INET6
6867188067Srrs	case IPV6_VERSION >> 4:
6868252944Stuexen		ip6 = mtod(m, struct ip6_hdr *);
6869252944Stuexen		ip6->ip6_plen = htons(ntohs(ip6->ip6_plen) - sizeof(struct udphdr));
6870252944Stuexen		sctp6_input_with_port(&m, &off, port);
6871237912Stuexen		break;
6872188067Srrs#endif
6873188067Srrs	default:
6874237912Stuexen		goto out;
6875237912Stuexen		break;
6876188067Srrs	}
6877188067Srrs	return;
6878188067Srrsout:
6879188067Srrs	m_freem(m);
6880188067Srrs}
6881188067Srrs
6882221328Stuexenvoid
6883179157Srrssctp_over_udp_stop(void)
6884179157Srrs{
6885188067Srrs	/*
6886188067Srrs	 * This function assumes sysctl caller holds sctp_sysctl_info_lock()
6887188067Srrs	 * for writting!
6888188067Srrs	 */
6889252944Stuexen#ifdef INET
6890252944Stuexen	if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) {
6891252944Stuexen		soclose(SCTP_BASE_INFO(udp4_tun_socket));
6892252944Stuexen		SCTP_BASE_INFO(udp4_tun_socket) = NULL;
6893188067Srrs	}
6894252944Stuexen#endif
6895252944Stuexen#ifdef INET6
6896252944Stuexen	if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) {
6897252944Stuexen		soclose(SCTP_BASE_INFO(udp6_tun_socket));
6898252944Stuexen		SCTP_BASE_INFO(udp6_tun_socket) = NULL;
6899252944Stuexen	}
6900252944Stuexen#endif
6901179157Srrs}
6902221328Stuexen
6903221328Stuexenint
6904179157Srrssctp_over_udp_start(void)
6905179157Srrs{
6906188067Srrs	uint16_t port;
6907188067Srrs	int ret;
6908252944Stuexen
6909252944Stuexen#ifdef INET
6910188067Srrs	struct sockaddr_in sin;
6911188067Srrs
6912252944Stuexen#endif
6913252944Stuexen#ifdef INET6
6914252944Stuexen	struct sockaddr_in6 sin6;
6915252944Stuexen
6916252944Stuexen#endif
6917188067Srrs	/*
6918188067Srrs	 * This function assumes sysctl caller holds sctp_sysctl_info_lock()
6919188067Srrs	 * for writting!
6920188067Srrs	 */
6921188067Srrs	port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port);
6922252944Stuexen	if (ntohs(port) == 0) {
6923188067Srrs		/* Must have a port set */
6924188067Srrs		return (EINVAL);
6925188067Srrs	}
6926252944Stuexen#ifdef INET
6927252944Stuexen	if (SCTP_BASE_INFO(udp4_tun_socket) != NULL) {
6928188067Srrs		/* Already running -- must stop first */
6929188067Srrs		return (EALREADY);
6930188067Srrs	}
6931252944Stuexen#endif
6932252944Stuexen#ifdef INET6
6933252944Stuexen	if (SCTP_BASE_INFO(udp6_tun_socket) != NULL) {
6934252944Stuexen		/* Already running -- must stop first */
6935252944Stuexen		return (EALREADY);
6936252944Stuexen	}
6937252944Stuexen#endif
6938252944Stuexen#ifdef INET
6939252944Stuexen	if ((ret = socreate(PF_INET, &SCTP_BASE_INFO(udp4_tun_socket),
6940252944Stuexen	    SOCK_DGRAM, IPPROTO_UDP,
6941252944Stuexen	    curthread->td_ucred, curthread))) {
6942252944Stuexen		sctp_over_udp_stop();
6943188067Srrs		return (ret);
6944188067Srrs	}
6945252944Stuexen	/* Call the special UDP hook. */
6946252944Stuexen	if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp4_tun_socket),
6947252944Stuexen	    sctp_recv_udp_tunneled_packet))) {
6948252944Stuexen		sctp_over_udp_stop();
6949252944Stuexen		return (ret);
6950188067Srrs	}
6951252944Stuexen	/* Ok, we have a socket, bind it to the port. */
6952252944Stuexen	memset(&sin, 0, sizeof(struct sockaddr_in));
6953252944Stuexen	sin.sin_len = sizeof(struct sockaddr_in);
6954188067Srrs	sin.sin_family = AF_INET;
6955188067Srrs	sin.sin_port = htons(port);
6956252944Stuexen	if ((ret = sobind(SCTP_BASE_INFO(udp4_tun_socket),
6957252944Stuexen	    (struct sockaddr *)&sin, curthread))) {
6958188067Srrs		sctp_over_udp_stop();
6959188067Srrs		return (ret);
6960188067Srrs	}
6961252944Stuexen#endif
6962252944Stuexen#ifdef INET6
6963252944Stuexen	if ((ret = socreate(PF_INET6, &SCTP_BASE_INFO(udp6_tun_socket),
6964252944Stuexen	    SOCK_DGRAM, IPPROTO_UDP,
6965252944Stuexen	    curthread->td_ucred, curthread))) {
6966252944Stuexen		sctp_over_udp_stop();
6967252944Stuexen		return (ret);
6968252944Stuexen	}
6969252944Stuexen	/* Call the special UDP hook. */
6970252944Stuexen	if ((ret = udp_set_kernel_tunneling(SCTP_BASE_INFO(udp6_tun_socket),
6971252944Stuexen	    sctp_recv_udp_tunneled_packet))) {
6972252944Stuexen		sctp_over_udp_stop();
6973252944Stuexen		return (ret);
6974252944Stuexen	}
6975252944Stuexen	/* Ok, we have a socket, bind it to the port. */
6976252944Stuexen	memset(&sin6, 0, sizeof(struct sockaddr_in6));
6977252944Stuexen	sin6.sin6_len = sizeof(struct sockaddr_in6);
6978252944Stuexen	sin6.sin6_family = AF_INET6;
6979252944Stuexen	sin6.sin6_port = htons(port);
6980252944Stuexen	if ((ret = sobind(SCTP_BASE_INFO(udp6_tun_socket),
6981252944Stuexen	    (struct sockaddr *)&sin6, curthread))) {
6982252944Stuexen		sctp_over_udp_stop();
6983252944Stuexen		return (ret);
6984252944Stuexen	}
6985252944Stuexen#endif
6986188067Srrs	return (0);
6987179157Srrs}
6988