1163953Srrs/*-
2185694Srrs * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
3235828Stuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4235828Stuexen * 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,
10228653Stuexen *    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
14228653Stuexen *    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: releng/10.3/sys/netinet/sctp_input.c 296052 2016-02-25 18:46:06Z tuexen $");
35163953Srrs
36163953Srrs#include <netinet/sctp_os.h>
37163953Srrs#include <netinet/sctp_var.h>
38167598Srrs#include <netinet/sctp_sysctl.h>
39163953Srrs#include <netinet/sctp_pcb.h>
40163953Srrs#include <netinet/sctp_header.h>
41163953Srrs#include <netinet/sctputil.h>
42163953Srrs#include <netinet/sctp_output.h>
43163953Srrs#include <netinet/sctp_input.h>
44163953Srrs#include <netinet/sctp_auth.h>
45163953Srrs#include <netinet/sctp_indata.h>
46163953Srrs#include <netinet/sctp_asconf.h>
47170091Srrs#include <netinet/sctp_bsd_addr.h>
48172091Srrs#include <netinet/sctp_timer.h>
49188067Srrs#include <netinet/sctp_crc32.h>
50270350Stuexen#if defined(INET) || defined(INET6)
51179157Srrs#include <netinet/udp.h>
52270350Stuexen#endif
53218211Srrs#include <sys/smp.h>
54163953Srrs
55163953Srrs
56163953Srrs
57163953Srrsstatic void
58163953Srrssctp_stop_all_cookie_timers(struct sctp_tcb *stcb)
59163953Srrs{
60163953Srrs	struct sctp_nets *net;
61163953Srrs
62165220Srrs	/*
63165220Srrs	 * This now not only stops all cookie timers it also stops any INIT
64165220Srrs	 * timers as well. This will make sure that the timers are stopped
65165220Srrs	 * in all collision cases.
66165220Srrs	 */
67163953Srrs	SCTP_TCB_LOCK_ASSERT(stcb);
68163953Srrs	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
69165220Srrs		if (net->rxt_timer.type == SCTP_TIMER_TYPE_COOKIE) {
70163953Srrs			sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE,
71163953Srrs			    stcb->sctp_ep,
72163953Srrs			    stcb,
73165220Srrs			    net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_1);
74165220Srrs		} else if (net->rxt_timer.type == SCTP_TIMER_TYPE_INIT) {
75165220Srrs			sctp_timer_stop(SCTP_TIMER_TYPE_INIT,
76165220Srrs			    stcb->sctp_ep,
77165220Srrs			    stcb,
78165220Srrs			    net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_2);
79163953Srrs		}
80163953Srrs	}
81163953Srrs}
82163953Srrs
83163953Srrs/* INIT handler */
84163953Srrsstatic void
85237715Stuexensctp_handle_init(struct mbuf *m, int iphlen, int offset,
86237715Stuexen    struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh,
87237049Stuexen    struct sctp_init_chunk *cp, struct sctp_inpcb *inp,
88295208Stuexen    struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_no_unlock,
89281955Shiren    uint8_t mflowtype, uint32_t mflowid,
90237049Stuexen    uint32_t vrf_id, uint16_t port)
91163953Srrs{
92163953Srrs	struct sctp_init *init;
93163953Srrs	struct mbuf *op_err;
94163953Srrs
95169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_init: handling INIT tcb:%p\n",
96240148Stuexen	    (void *)stcb);
97172396Srrs	if (stcb == NULL) {
98172396Srrs		SCTP_INP_RLOCK(inp);
99172396Srrs	}
100229774Stuexen	/* validate length */
101163953Srrs	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) {
102267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
103237715Stuexen		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
104281955Shiren		    mflowtype, mflowid,
105179157Srrs		    vrf_id, port);
106168299Srrs		if (stcb)
107168299Srrs			*abort_no_unlock = 1;
108172396Srrs		goto outnow;
109163953Srrs	}
110163953Srrs	/* validate parameters */
111229774Stuexen	init = &cp->init;
112163953Srrs	if (init->initiate_tag == 0) {
113163953Srrs		/* protocol error... send abort */
114267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
115237715Stuexen		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
116281955Shiren		    mflowtype, mflowid,
117179157Srrs		    vrf_id, port);
118168299Srrs		if (stcb)
119168299Srrs			*abort_no_unlock = 1;
120172396Srrs		goto outnow;
121163953Srrs	}
122163953Srrs	if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) {
123163953Srrs		/* invalid parameter... send abort */
124267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
125237715Stuexen		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
126281955Shiren		    mflowtype, mflowid,
127179157Srrs		    vrf_id, port);
128171440Srrs		if (stcb)
129171440Srrs			*abort_no_unlock = 1;
130172396Srrs		goto outnow;
131163953Srrs	}
132163953Srrs	if (init->num_inbound_streams == 0) {
133163953Srrs		/* protocol error... send abort */
134267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
135237715Stuexen		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
136281955Shiren		    mflowtype, mflowid,
137179157Srrs		    vrf_id, port);
138168299Srrs		if (stcb)
139168299Srrs			*abort_no_unlock = 1;
140172396Srrs		goto outnow;
141163953Srrs	}
142163953Srrs	if (init->num_outbound_streams == 0) {
143163953Srrs		/* protocol error... send abort */
144267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
145237715Stuexen		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
146281955Shiren		    mflowtype, mflowid,
147179157Srrs		    vrf_id, port);
148168299Srrs		if (stcb)
149168299Srrs			*abort_no_unlock = 1;
150172396Srrs		goto outnow;
151163953Srrs	}
152163953Srrs	if (sctp_validate_init_auth_params(m, offset + sizeof(*cp),
153229774Stuexen	    offset + ntohs(cp->ch.chunk_length))) {
154163953Srrs		/* auth parameter(s) error... send abort */
155267723Stuexen		op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
156267723Stuexen		    "Problem with AUTH parameters");
157267723Stuexen		sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err,
158281955Shiren		    mflowtype, mflowid,
159237049Stuexen		    vrf_id, port);
160168299Srrs		if (stcb)
161168299Srrs			*abort_no_unlock = 1;
162172396Srrs		goto outnow;
163163953Srrs	}
164229774Stuexen	/*
165229774Stuexen	 * We are only accepting if we have a socket with positive
166229774Stuexen	 * so_qlimit.
167229774Stuexen	 */
168229774Stuexen	if ((stcb == NULL) &&
169229774Stuexen	    ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
170229774Stuexen	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
171229774Stuexen	    (inp->sctp_socket == NULL) ||
172229774Stuexen	    (inp->sctp_socket->so_qlimit == 0))) {
173229774Stuexen		/*
174229774Stuexen		 * FIX ME ?? What about TCP model and we have a
175229774Stuexen		 * match/restart case? Actually no fix is needed. the lookup
176229774Stuexen		 * will always find the existing assoc so stcb would not be
177229774Stuexen		 * NULL. It may be questionable to do this since we COULD
178229774Stuexen		 * just send back the INIT-ACK and hope that the app did
179229774Stuexen		 * accept()'s by the time the COOKIE was sent. But there is
180229774Stuexen		 * a price to pay for COOKIE generation and I don't want to
181229774Stuexen		 * pay it on the chance that the app will actually do some
182229774Stuexen		 * accepts(). The App just looses and should NOT be in this
183229774Stuexen		 * state :-)
184229774Stuexen		 */
185229805Stuexen		if (SCTP_BASE_SYSCTL(sctp_blackhole) == 0) {
186267723Stuexen			op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
187267723Stuexen			    "No listener");
188267723Stuexen			sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err,
189284633Stuexen			    mflowtype, mflowid, inp->fibnum,
190237049Stuexen			    vrf_id, port);
191229805Stuexen		}
192229774Stuexen		goto outnow;
193229774Stuexen	}
194229774Stuexen	if ((stcb != NULL) &&
195229774Stuexen	    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT)) {
196229774Stuexen		SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending SHUTDOWN-ACK\n");
197229774Stuexen		sctp_send_shutdown_ack(stcb, NULL);
198229774Stuexen		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
199229774Stuexen	} else {
200229774Stuexen		SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n");
201295208Stuexen		sctp_send_initiate_ack(inp, stcb, net, m, iphlen, offset,
202295208Stuexen		    src, dst, sh, cp,
203281955Shiren		    mflowtype, mflowid,
204237049Stuexen		    vrf_id, port,
205229774Stuexen		    ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED));
206229774Stuexen	}
207172396Srrsoutnow:
208172396Srrs	if (stcb == NULL) {
209172396Srrs		SCTP_INP_RUNLOCK(inp);
210172396Srrs	}
211163953Srrs}
212163953Srrs
213163953Srrs/*
214163953Srrs * process peer "INIT/INIT-ACK" chunk returns value < 0 on error
215163953Srrs */
216171158Srrs
217171158Srrsint
218221627Stuexensctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked
219221627Stuexen#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
220221627Stuexen    SCTP_UNUSED
221221627Stuexen#endif
222221627Stuexen)
223171158Srrs{
224171158Srrs	int unsent_data = 0;
225217760Stuexen	unsigned int i;
226217760Stuexen	struct sctp_stream_queue_pending *sp;
227171158Srrs	struct sctp_association *asoc;
228171158Srrs
229171158Srrs	/*
230171158Srrs	 * This function returns the number of streams that have true unsent
231171158Srrs	 * data on them. Note that as it looks through it will clean up any
232171158Srrs	 * places that have old data that has been sent but left at top of
233171158Srrs	 * stream queue.
234171158Srrs	 */
235171158Srrs	asoc = &stcb->asoc;
236171158Srrs	SCTP_TCB_SEND_LOCK(stcb);
237217760Stuexen	if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
238217760Stuexen		/* Check to see if some data queued */
239217760Stuexen		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
240217760Stuexen			/* sa_ignore FREED_MEMORY */
241217760Stuexen			sp = TAILQ_FIRST(&stcb->asoc.strmout[i].outqueue);
242217760Stuexen			if (sp == NULL) {
243217760Stuexen				continue;
244217760Stuexen			}
245171158Srrs			if ((sp->msg_is_complete) &&
246171158Srrs			    (sp->length == 0) &&
247171158Srrs			    (sp->sender_all_done)) {
248171158Srrs				/*
249171158Srrs				 * We are doing differed cleanup. Last time
250171158Srrs				 * through when we took all the data the
251171158Srrs				 * sender_all_done was not set.
252171158Srrs				 */
253171158Srrs				if (sp->put_last_out == 0) {
254171158Srrs					SCTP_PRINTF("Gak, put out entire msg with NO end!-1\n");
255171158Srrs					SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d\n",
256171158Srrs					    sp->sender_all_done,
257171158Srrs					    sp->length,
258171158Srrs					    sp->msg_is_complete,
259171158Srrs					    sp->put_last_out);
260171158Srrs				}
261217760Stuexen				atomic_subtract_int(&stcb->asoc.stream_queue_cnt, 1);
262217760Stuexen				TAILQ_REMOVE(&stcb->asoc.strmout[i].outqueue, sp, next);
263212712Stuexen				if (sp->net) {
264212712Stuexen					sctp_free_remote_addr(sp->net);
265212712Stuexen					sp->net = NULL;
266212712Stuexen				}
267171158Srrs				if (sp->data) {
268171158Srrs					sctp_m_freem(sp->data);
269171158Srrs					sp->data = NULL;
270171158Srrs				}
271221627Stuexen				sctp_free_a_strmoq(stcb, sp, so_locked);
272171158Srrs			} else {
273171158Srrs				unsent_data++;
274216822Stuexen				break;
275171158Srrs			}
276171158Srrs		}
277171158Srrs	}
278171158Srrs	SCTP_TCB_SEND_UNLOCK(stcb);
279171158Srrs	return (unsent_data);
280171158Srrs}
281171158Srrs
282163953Srrsstatic int
283228653Stuexensctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
284163953Srrs{
285163953Srrs	struct sctp_init *init;
286163953Srrs	struct sctp_association *asoc;
287163953Srrs	struct sctp_nets *lnet;
288163953Srrs	unsigned int i;
289163953Srrs
290163953Srrs	init = &cp->init;
291163953Srrs	asoc = &stcb->asoc;
292163953Srrs	/* save off parameters */
293163953Srrs	asoc->peer_vtag = ntohl(init->initiate_tag);
294163953Srrs	asoc->peers_rwnd = ntohl(init->a_rwnd);
295218129Srrs	/* init tsn's */
296218129Srrs	asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1;
297218129Srrs
298212712Stuexen	if (!TAILQ_EMPTY(&asoc->nets)) {
299163953Srrs		/* update any ssthresh's that may have a default */
300163953Srrs		TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) {
301163953Srrs			lnet->ssthresh = asoc->peers_rwnd;
302179783Srrs			if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) {
303170744Srrs				sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_INITIALIZATION);
304170744Srrs			}
305163953Srrs		}
306163953Srrs	}
307164181Srrs	SCTP_TCB_SEND_LOCK(stcb);
308163953Srrs	if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) {
309163953Srrs		unsigned int newcnt;
310163953Srrs		struct sctp_stream_out *outs;
311216822Stuexen		struct sctp_stream_queue_pending *sp, *nsp;
312216822Stuexen		struct sctp_tmit_chunk *chk, *nchk;
313163953Srrs
314196260Stuexen		/* abandon the upper streams */
315163953Srrs		newcnt = ntohs(init->num_inbound_streams);
316216822Stuexen		TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
317216822Stuexen			if (chk->rec.data.stream_number >= newcnt) {
318216822Stuexen				TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
319216822Stuexen				asoc->send_queue_cnt--;
320242714Stuexen				if (asoc->strmout[chk->rec.data.stream_number].chunks_on_queues > 0) {
321242714Stuexen					asoc->strmout[chk->rec.data.stream_number].chunks_on_queues--;
322242714Stuexen#ifdef INVARIANTS
323242714Stuexen				} else {
324242714Stuexen					panic("No chunks on the queues for sid %u.", chk->rec.data.stream_number);
325242714Stuexen#endif
326242714Stuexen				}
327216822Stuexen				if (chk->data != NULL) {
328216822Stuexen					sctp_free_bufspace(stcb, asoc, chk, 1);
329235416Stuexen					sctp_ulp_notify(SCTP_NOTIFY_UNSENT_DG_FAIL, stcb,
330235416Stuexen					    0, chk, SCTP_SO_NOT_LOCKED);
331216822Stuexen					if (chk->data) {
332216822Stuexen						sctp_m_freem(chk->data);
333216822Stuexen						chk->data = NULL;
334196260Stuexen					}
335196260Stuexen				}
336221627Stuexen				sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
337216822Stuexen				/* sa_ignore FREED_MEMORY */
338196260Stuexen			}
339196260Stuexen		}
340163953Srrs		if (asoc->strmout) {
341163953Srrs			for (i = newcnt; i < asoc->pre_open_streams; i++) {
342163953Srrs				outs = &asoc->strmout[i];
343216822Stuexen				TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
344196260Stuexen					TAILQ_REMOVE(&outs->outqueue, sp, next);
345163953Srrs					asoc->stream_queue_cnt--;
346163953Srrs					sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL,
347235416Stuexen					    stcb, 0, sp, SCTP_SO_NOT_LOCKED);
348163953Srrs					if (sp->data) {
349163953Srrs						sctp_m_freem(sp->data);
350163953Srrs						sp->data = NULL;
351163953Srrs					}
352212712Stuexen					if (sp->net) {
353212712Stuexen						sctp_free_remote_addr(sp->net);
354212712Stuexen						sp->net = NULL;
355212712Stuexen					}
356163953Srrs					/* Free the chunk */
357221627Stuexen					sctp_free_a_strmoq(stcb, sp, SCTP_SO_NOT_LOCKED);
358169655Srrs					/* sa_ignore FREED_MEMORY */
359163953Srrs				}
360294140Stuexen				outs->state = SCTP_STREAM_CLOSED;
361163953Srrs			}
362163953Srrs		}
363196260Stuexen		/* cut back the count */
364163953Srrs		asoc->pre_open_streams = newcnt;
365163953Srrs	}
366164181Srrs	SCTP_TCB_SEND_UNLOCK(stcb);
367294140Stuexen	asoc->streamoutcnt = asoc->pre_open_streams;
368296052Stuexen	if (asoc->strmout) {
369296052Stuexen		for (i = 0; i < asoc->streamoutcnt; i++) {
370296052Stuexen			asoc->strmout[i].state = SCTP_STREAM_OPEN;
371296052Stuexen		}
372294140Stuexen	}
373185694Srrs	/* EY - nr_sack: initialize highest tsn in nr_mapping_array */
374185694Srrs	asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map;
375179783Srrs	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
376170744Srrs		sctp_log_map(0, 5, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
377170744Srrs	}
378163953Srrs	/* This is the next one we expect */
379163953Srrs	asoc->str_reset_seq_in = asoc->asconf_seq_in + 1;
380163953Srrs
381163953Srrs	asoc->mapping_array_base_tsn = ntohl(init->initial_tsn);
382180955Srrs	asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->asconf_seq_in;
383218129Srrs
384163953Srrs	asoc->advanced_peer_ack_point = asoc->last_acked_seq;
385163953Srrs	/* open the requested streams */
386170091Srrs
387163953Srrs	if (asoc->strmin != NULL) {
388163953Srrs		/* Free the old ones */
389216822Stuexen		struct sctp_queued_to_read *ctl, *nctl;
390164181Srrs
391164181Srrs		for (i = 0; i < asoc->streamincnt; i++) {
392216822Stuexen			TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) {
393164181Srrs				TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next);
394164181Srrs				sctp_free_remote_addr(ctl->whoFrom);
395171158Srrs				ctl->whoFrom = NULL;
396164181Srrs				sctp_m_freem(ctl->data);
397164181Srrs				ctl->data = NULL;
398164181Srrs				sctp_free_a_readq(stcb, ctl);
399164181Srrs			}
400164181Srrs		}
401170091Srrs		SCTP_FREE(asoc->strmin, SCTP_M_STRMI);
402163953Srrs	}
403252779Stuexen	if (asoc->max_inbound_streams > ntohs(init->num_outbound_streams)) {
404252779Stuexen		asoc->streamincnt = ntohs(init->num_outbound_streams);
405252779Stuexen	} else {
406252779Stuexen		asoc->streamincnt = asoc->max_inbound_streams;
407164181Srrs	}
408163953Srrs	SCTP_MALLOC(asoc->strmin, struct sctp_stream_in *, asoc->streamincnt *
409170091Srrs	    sizeof(struct sctp_stream_in), SCTP_M_STRMI);
410163953Srrs	if (asoc->strmin == NULL) {
411163953Srrs		/* we didn't get memory for the streams! */
412169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT2, "process_init: couldn't get memory for the streams!\n");
413163953Srrs		return (-1);
414163953Srrs	}
415163953Srrs	for (i = 0; i < asoc->streamincnt; i++) {
416163953Srrs		asoc->strmin[i].stream_no = i;
417163953Srrs		asoc->strmin[i].last_sequence_delivered = 0xffff;
418163953Srrs		TAILQ_INIT(&asoc->strmin[i].inqueue);
419168943Srrs		asoc->strmin[i].delivery_started = 0;
420163953Srrs	}
421163953Srrs	/*
422163953Srrs	 * load_address_from_init will put the addresses into the
423163953Srrs	 * association when the COOKIE is processed or the INIT-ACK is
424163953Srrs	 * processed. Both types of COOKIE's existing and new call this
425163953Srrs	 * routine. It will remove addresses that are no longer in the
426163953Srrs	 * association (for the restarting case where addresses are
427163953Srrs	 * removed). Up front when the INIT arrives we will discard it if it
428163953Srrs	 * is a restart and new addresses have been added.
429163953Srrs	 */
430169655Srrs	/* sa_ignore MEMLEAK */
431163953Srrs	return (0);
432163953Srrs}
433163953Srrs
434163953Srrs/*
435163953Srrs * INIT-ACK message processing/consumption returns value < 0 on error
436163953Srrs */
437163953Srrsstatic int
438237715Stuexensctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
439237715Stuexen    struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh,
440237049Stuexen    struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
441237049Stuexen    struct sctp_nets *net, int *abort_no_unlock,
442281955Shiren    uint8_t mflowtype, uint32_t mflowid,
443237049Stuexen    uint32_t vrf_id)
444163953Srrs{
445163953Srrs	struct sctp_association *asoc;
446163953Srrs	struct mbuf *op_err;
447163953Srrs	int retval, abort_flag;
448163953Srrs	uint32_t initack_limit;
449185694Srrs	int nat_friendly = 0;
450163953Srrs
451163953Srrs	/* First verify that we have no illegal param's */
452163953Srrs	abort_flag = 0;
453163953Srrs
454163953Srrs	op_err = sctp_arethere_unrecognized_parameters(m,
455163953Srrs	    (offset + sizeof(struct sctp_init_chunk)),
456185694Srrs	    &abort_flag, (struct sctp_chunkhdr *)cp, &nat_friendly);
457163953Srrs	if (abort_flag) {
458163953Srrs		/* Send an abort and notify peer */
459235360Stuexen		sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
460170056Srrs		*abort_no_unlock = 1;
461163953Srrs		return (-1);
462163953Srrs	}
463163953Srrs	asoc = &stcb->asoc;
464185694Srrs	asoc->peer_supports_nat = (uint8_t) nat_friendly;
465163953Srrs	/* process the peer's parameters in the INIT-ACK */
466228653Stuexen	retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb);
467163953Srrs	if (retval < 0) {
468163953Srrs		return (retval);
469163953Srrs	}
470163953Srrs	initack_limit = offset + ntohs(cp->ch.chunk_length);
471163953Srrs	/* load all addresses */
472228653Stuexen	if ((retval = sctp_load_addresses_from_init(stcb, m,
473237715Stuexen	    (offset + sizeof(struct sctp_init_chunk)), initack_limit,
474237715Stuexen	    src, dst, NULL))) {
475267723Stuexen		op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
476267723Stuexen		    "Problem with address parameters");
477169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT1,
478169420Srrs		    "Load addresses from INIT causes an abort %d\n",
479169420Srrs		    retval);
480237715Stuexen		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
481267723Stuexen		    src, dst, sh, op_err,
482281955Shiren		    mflowtype, mflowid,
483237049Stuexen		    vrf_id, net->port);
484168299Srrs		*abort_no_unlock = 1;
485163953Srrs		return (-1);
486163953Srrs	}
487171477Srrs	/* if the peer doesn't support asconf, flush the asconf queue */
488270362Stuexen	if (asoc->asconf_supported == 0) {
489216822Stuexen		struct sctp_asconf_addr *param, *nparam;
490171477Srrs
491216822Stuexen		TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) {
492216822Stuexen			TAILQ_REMOVE(&asoc->asconf_queue, param, next);
493216822Stuexen			SCTP_FREE(param, SCTP_M_ASC_ADDR);
494171477Srrs		}
495171477Srrs	}
496163953Srrs	stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs,
497163953Srrs	    stcb->asoc.local_hmacs);
498163953Srrs	if (op_err) {
499163953Srrs		sctp_queue_op_err(stcb, op_err);
500163953Srrs		/* queuing will steal away the mbuf chain to the out queue */
501163953Srrs		op_err = NULL;
502163953Srrs	}
503163953Srrs	/* extract the cookie and queue it to "echo" it back... */
504179783Srrs	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
505171943Srrs		sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
506171943Srrs		    stcb->asoc.overall_error_count,
507171943Srrs		    0,
508171943Srrs		    SCTP_FROM_SCTP_INPUT,
509171943Srrs		    __LINE__);
510171943Srrs	}
511163953Srrs	stcb->asoc.overall_error_count = 0;
512163953Srrs	net->error_count = 0;
513163953Srrs
514163953Srrs	/*
515163953Srrs	 * Cancel the INIT timer, We do this first before queueing the
516163953Srrs	 * cookie. We always cancel at the primary to assue that we are
517163953Srrs	 * canceling the timer started by the INIT which always goes to the
518163953Srrs	 * primary.
519163953Srrs	 */
520163953Srrs	sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb,
521283822Stuexen	    asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
522163953Srrs
523165220Srrs	/* calculate the RTO */
524218186Srrs	net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy,
525219397Srrs	    SCTP_RTT_FROM_NON_DATA);
526163953Srrs	retval = sctp_send_cookie_echo(m, offset, stcb, net);
527163953Srrs	if (retval < 0) {
528163953Srrs		/*
529163953Srrs		 * No cookie, we probably should send a op error. But in any
530163953Srrs		 * case if there is no cookie in the INIT-ACK, we can
531163953Srrs		 * abandon the peer, its broke.
532163953Srrs		 */
533163953Srrs		if (retval == -3) {
534294159Stuexen			uint16_t len;
535294158Stuexen
536294159Stuexen			len = (uint16_t) (sizeof(struct sctp_error_missing_param) + sizeof(uint16_t));
537163953Srrs			/* We abort with an error of missing mandatory param */
538294158Stuexen			op_err = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA);
539294158Stuexen			if (op_err != NULL) {
540294158Stuexen				struct sctp_error_missing_param *cause;
541163953Srrs
542294158Stuexen				SCTP_BUF_LEN(op_err) = len;
543294158Stuexen				cause = mtod(op_err, struct sctp_error_missing_param *);
544163953Srrs				/* Subtract the reserved param */
545294158Stuexen				cause->cause.code = htons(SCTP_CAUSE_MISSING_PARAM);
546294158Stuexen				cause->cause.length = htons(len);
547294158Stuexen				cause->num_missing_params = htonl(1);
548294158Stuexen				cause->type[0] = htons(SCTP_STATE_COOKIE);
549163953Srrs			}
550163953Srrs			sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
551237715Stuexen			    src, dst, sh, op_err,
552281955Shiren			    mflowtype, mflowid,
553237049Stuexen			    vrf_id, net->port);
554168299Srrs			*abort_no_unlock = 1;
555163953Srrs		}
556163953Srrs		return (retval);
557163953Srrs	}
558163953Srrs	return (0);
559163953Srrs}
560163953Srrs
561163953Srrsstatic void
562163953Srrssctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
563163953Srrs    struct sctp_tcb *stcb, struct sctp_nets *net)
564163953Srrs{
565271746Stuexen	union sctp_sockstore store;
566212225Srrs	struct sctp_nets *r_net, *f_net;
567163953Srrs	struct timeval tv;
568172396Srrs	int req_prim = 0;
569224641Stuexen	uint16_t old_error_counter;
570163953Srrs
571163953Srrs	if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) {
572163953Srrs		/* Invalid length */
573163953Srrs		return;
574163953Srrs	}
575163953Srrs	memset(&store, 0, sizeof(store));
576221249Stuexen	switch (cp->heartbeat.hb_info.addr_family) {
577221249Stuexen#ifdef INET
578221249Stuexen	case AF_INET:
579221249Stuexen		if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) {
580271746Stuexen			store.sin.sin_family = cp->heartbeat.hb_info.addr_family;
581271746Stuexen			store.sin.sin_len = cp->heartbeat.hb_info.addr_len;
582271746Stuexen			store.sin.sin_port = stcb->rport;
583271746Stuexen			memcpy(&store.sin.sin_addr, cp->heartbeat.hb_info.address,
584271746Stuexen			    sizeof(store.sin.sin_addr));
585221249Stuexen		} else {
586221249Stuexen			return;
587221249Stuexen		}
588221249Stuexen		break;
589221249Stuexen#endif
590221249Stuexen#ifdef INET6
591221249Stuexen	case AF_INET6:
592221249Stuexen		if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) {
593271746Stuexen			store.sin6.sin6_family = cp->heartbeat.hb_info.addr_family;
594271746Stuexen			store.sin6.sin6_len = cp->heartbeat.hb_info.addr_len;
595271746Stuexen			store.sin6.sin6_port = stcb->rport;
596271746Stuexen			memcpy(&store.sin6.sin6_addr, cp->heartbeat.hb_info.address, sizeof(struct in6_addr));
597221249Stuexen		} else {
598221249Stuexen			return;
599221249Stuexen		}
600221249Stuexen		break;
601221249Stuexen#endif
602221249Stuexen	default:
603163953Srrs		return;
604163953Srrs	}
605271746Stuexen	r_net = sctp_findnet(stcb, &store.sa);
606163953Srrs	if (r_net == NULL) {
607169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n");
608163953Srrs		return;
609163953Srrs	}
610163953Srrs	if ((r_net && (r_net->dest_state & SCTP_ADDR_UNCONFIRMED)) &&
611163953Srrs	    (r_net->heartbeat_random1 == cp->heartbeat.hb_info.random_value1) &&
612163953Srrs	    (r_net->heartbeat_random2 == cp->heartbeat.hb_info.random_value2)) {
613163953Srrs		/*
614163953Srrs		 * If the its a HB and it's random value is correct when can
615163953Srrs		 * confirm the destination.
616163953Srrs		 */
617163953Srrs		r_net->dest_state &= ~SCTP_ADDR_UNCONFIRMED;
618167598Srrs		if (r_net->dest_state & SCTP_ADDR_REQ_PRIMARY) {
619167598Srrs			stcb->asoc.primary_destination = r_net;
620167598Srrs			r_net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY;
621212225Srrs			f_net = TAILQ_FIRST(&stcb->asoc.nets);
622212225Srrs			if (f_net != r_net) {
623167598Srrs				/*
624167598Srrs				 * first one on the list is NOT the primary
625167598Srrs				 * sctp_cmpaddr() is much more efficent if
626167598Srrs				 * the primary is the first on the list,
627167598Srrs				 * make it so.
628167598Srrs				 */
629212225Srrs				TAILQ_REMOVE(&stcb->asoc.nets, r_net, sctp_next);
630212225Srrs				TAILQ_INSERT_HEAD(&stcb->asoc.nets, r_net, sctp_next);
631167598Srrs			}
632172396Srrs			req_prim = 1;
633167598Srrs		}
634163953Srrs		sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
635172090Srrs		    stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED);
636283822Stuexen		sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb,
637283822Stuexen		    r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4);
638224641Stuexen		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net);
639163953Srrs	}
640224641Stuexen	old_error_counter = r_net->error_count;
641163953Srrs	r_net->error_count = 0;
642163953Srrs	r_net->hb_responded = 1;
643163953Srrs	tv.tv_sec = cp->heartbeat.hb_info.time_value_1;
644163953Srrs	tv.tv_usec = cp->heartbeat.hb_info.time_value_2;
645224641Stuexen	/* Now lets do a RTO with this */
646224641Stuexen	r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy,
647224641Stuexen	    SCTP_RTT_FROM_NON_DATA);
648224641Stuexen	if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) {
649163953Srrs		r_net->dest_state |= SCTP_ADDR_REACHABLE;
650163953Srrs		sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
651235414Stuexen		    0, (void *)r_net, SCTP_SO_NOT_LOCKED);
652163953Srrs	}
653224641Stuexen	if (r_net->dest_state & SCTP_ADDR_PF) {
654224641Stuexen		r_net->dest_state &= ~SCTP_ADDR_PF;
655224641Stuexen		stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
656224641Stuexen	}
657224641Stuexen	if (old_error_counter > 0) {
658283822Stuexen		sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
659283822Stuexen		    stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_5);
660224641Stuexen		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net);
661224641Stuexen	}
662224641Stuexen	if (r_net == stcb->asoc.primary_destination) {
663224641Stuexen		if (stcb->asoc.alternate) {
664224641Stuexen			/* release the alternate, primary is good */
665224641Stuexen			sctp_free_remote_addr(stcb->asoc.alternate);
666224641Stuexen			stcb->asoc.alternate = NULL;
667171440Srrs		}
668171440Srrs	}
669172396Srrs	/* Mobility adaptation */
670172396Srrs	if (req_prim) {
671172396Srrs		if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
672172396Srrs		    SCTP_MOBILITY_BASE) ||
673172396Srrs		    sctp_is_mobility_feature_on(stcb->sctp_ep,
674172396Srrs		    SCTP_MOBILITY_FASTHANDOFF)) &&
675172396Srrs		    sctp_is_mobility_feature_on(stcb->sctp_ep,
676172396Srrs		    SCTP_MOBILITY_PRIM_DELETED)) {
677172396Srrs
678283822Stuexen			sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED,
679283822Stuexen			    stcb->sctp_ep, stcb, NULL,
680283822Stuexen			    SCTP_FROM_SCTP_INPUT + SCTP_LOC_6);
681172396Srrs			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
682172396Srrs			    SCTP_MOBILITY_FASTHANDOFF)) {
683172396Srrs				sctp_assoc_immediate_retrans(stcb,
684172396Srrs				    stcb->asoc.primary_destination);
685172396Srrs			}
686172396Srrs			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
687172396Srrs			    SCTP_MOBILITY_BASE)) {
688212712Stuexen				sctp_move_chunks_from_net(stcb,
689212712Stuexen				    stcb->asoc.deleted_primary);
690172396Srrs			}
691172396Srrs			sctp_delete_prim_timer(stcb->sctp_ep, stcb,
692172396Srrs			    stcb->asoc.deleted_primary);
693172396Srrs		}
694172396Srrs	}
695163953Srrs}
696163953Srrs
697185694Srrsstatic int
698185694Srrssctp_handle_nat_colliding_state(struct sctp_tcb *stcb)
699185694Srrs{
700185694Srrs	/*
701185694Srrs	 * return 0 means we want you to proceed with the abort non-zero
702185694Srrs	 * means no abort processing
703185694Srrs	 */
704185694Srrs	struct sctpasochead *head;
705185694Srrs
706185694Srrs	if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
707185694Srrs		/* generate a new vtag and send init */
708185694Srrs		LIST_REMOVE(stcb, sctp_asocs);
709185694Srrs		stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1);
710185694Srrs		head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))];
711185694Srrs		/*
712185694Srrs		 * put it in the bucket in the vtag hash of assoc's for the
713185694Srrs		 * system
714185694Srrs		 */
715185694Srrs		LIST_INSERT_HEAD(head, stcb, sctp_asocs);
716185694Srrs		sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
717185694Srrs		return (1);
718185694Srrs	}
719185694Srrs	if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
720185694Srrs		/*
721185694Srrs		 * treat like a case where the cookie expired i.e.: - dump
722185694Srrs		 * current cookie. - generate a new vtag. - resend init.
723185694Srrs		 */
724185694Srrs		/* generate a new vtag and send init */
725185694Srrs		LIST_REMOVE(stcb, sctp_asocs);
726185694Srrs		stcb->asoc.state &= ~SCTP_STATE_COOKIE_ECHOED;
727185694Srrs		stcb->asoc.state |= SCTP_STATE_COOKIE_WAIT;
728185694Srrs		sctp_stop_all_cookie_timers(stcb);
729185694Srrs		sctp_toss_old_cookies(stcb, &stcb->asoc);
730185694Srrs		stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1);
731185694Srrs		head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))];
732185694Srrs		/*
733185694Srrs		 * put it in the bucket in the vtag hash of assoc's for the
734185694Srrs		 * system
735185694Srrs		 */
736185694Srrs		LIST_INSERT_HEAD(head, stcb, sctp_asocs);
737185694Srrs		sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
738185694Srrs		return (1);
739185694Srrs	}
740185694Srrs	return (0);
741185694Srrs}
742185694Srrs
743185694Srrsstatic int
744185694Srrssctp_handle_nat_missing_state(struct sctp_tcb *stcb,
745185694Srrs    struct sctp_nets *net)
746185694Srrs{
747185694Srrs	/*
748185694Srrs	 * return 0 means we want you to proceed with the abort non-zero
749185694Srrs	 * means no abort processing
750185694Srrs	 */
751270362Stuexen	if (stcb->asoc.auth_supported == 0) {
752185694Srrs		SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n");
753185694Srrs		return (0);
754185694Srrs	}
755185694Srrs	sctp_asconf_send_nat_state_update(stcb, net);
756185694Srrs	return (1);
757185694Srrs}
758185694Srrs
759185694Srrs
760163953Srrsstatic void
761235360Stuexensctp_handle_abort(struct sctp_abort_chunk *abort,
762163953Srrs    struct sctp_tcb *stcb, struct sctp_nets *net)
763163953Srrs{
764237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
765172090Srrs	struct socket *so;
766172090Srrs
767172090Srrs#endif
768185694Srrs	uint16_t len;
769235360Stuexen	uint16_t error;
770172090Srrs
771169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n");
772163953Srrs	if (stcb == NULL)
773163953Srrs		return;
774163953Srrs
775235360Stuexen	len = ntohs(abort->ch.chunk_length);
776185694Srrs	if (len > sizeof(struct sctp_chunkhdr)) {
777185694Srrs		/*
778185694Srrs		 * Need to check the cause codes for our two magic nat
779185694Srrs		 * aborts which don't kill the assoc necessarily.
780185694Srrs		 */
781294158Stuexen		struct sctp_gen_error_cause *cause;
782185694Srrs
783294158Stuexen		cause = (struct sctp_gen_error_cause *)(abort + 1);
784294158Stuexen		error = ntohs(cause->code);
785235360Stuexen		if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) {
786185694Srrs			SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n",
787235360Stuexen			    abort->ch.chunk_flags);
788185694Srrs			if (sctp_handle_nat_colliding_state(stcb)) {
789185694Srrs				return;
790185694Srrs			}
791235360Stuexen		} else if (error == SCTP_CAUSE_NAT_MISSING_STATE) {
792185694Srrs			SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n",
793235360Stuexen			    abort->ch.chunk_flags);
794185694Srrs			if (sctp_handle_nat_missing_state(stcb, net)) {
795185694Srrs				return;
796185694Srrs			}
797185694Srrs		}
798235360Stuexen	} else {
799235360Stuexen		error = 0;
800185694Srrs	}
801163953Srrs	/* stop any receive timers */
802283822Stuexen	sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net,
803283822Stuexen	    SCTP_FROM_SCTP_INPUT + SCTP_LOC_7);
804163953Srrs	/* notify user of the abort and clean up... */
805235403Stuexen	sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED);
806163953Srrs	/* free the tcb */
807163953Srrs	SCTP_STAT_INCR_COUNTER32(sctps_aborted);
808163953Srrs	if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
809163953Srrs	    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
810163953Srrs		SCTP_STAT_DECR_GAUGE32(sctps_currestab);
811163953Srrs	}
812168859Srrs#ifdef SCTP_ASOCLOG_OF_TSNS
813168859Srrs	sctp_print_out_track_log(stcb);
814168859Srrs#endif
815237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
816172090Srrs	so = SCTP_INP_SO(stcb->sctp_ep);
817172090Srrs	atomic_add_int(&stcb->asoc.refcnt, 1);
818172090Srrs	SCTP_TCB_UNLOCK(stcb);
819172090Srrs	SCTP_SOCKET_LOCK(so, 1);
820172090Srrs	SCTP_TCB_LOCK(stcb);
821172090Srrs	atomic_subtract_int(&stcb->asoc.refcnt, 1);
822172090Srrs#endif
823171990Srrs	stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
824171943Srrs	(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
825283822Stuexen	    SCTP_FROM_SCTP_INPUT + SCTP_LOC_8);
826237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
827172090Srrs	SCTP_SOCKET_UNLOCK(so, 1);
828172090Srrs#endif
829169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n");
830163953Srrs}
831163953Srrs
832163953Srrsstatic void
833224641Stuexensctp_start_net_timers(struct sctp_tcb *stcb)
834224641Stuexen{
835224641Stuexen	uint32_t cnt_hb_sent;
836224641Stuexen	struct sctp_nets *net;
837224641Stuexen
838224641Stuexen	cnt_hb_sent = 0;
839224641Stuexen	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
840224641Stuexen		/*
841224641Stuexen		 * For each network start: 1) A pmtu timer. 2) A HB timer 3)
842224641Stuexen		 * If the dest in unconfirmed send a hb as well if under
843224641Stuexen		 * max_hb_burst have been sent.
844224641Stuexen		 */
845224641Stuexen		sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net);
846224641Stuexen		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
847224641Stuexen		if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
848224641Stuexen		    (cnt_hb_sent < SCTP_BASE_SYSCTL(sctp_hb_maxburst))) {
849224641Stuexen			sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
850224641Stuexen			cnt_hb_sent++;
851224641Stuexen		}
852224641Stuexen	}
853224641Stuexen	if (cnt_hb_sent) {
854224641Stuexen		sctp_chunk_output(stcb->sctp_ep, stcb,
855224641Stuexen		    SCTP_OUTPUT_FROM_COOKIE_ACK,
856224641Stuexen		    SCTP_SO_NOT_LOCKED);
857224641Stuexen	}
858224641Stuexen}
859224641Stuexen
860224641Stuexen
861224641Stuexenstatic void
862163953Srrssctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
863163953Srrs    struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag)
864163953Srrs{
865163953Srrs	struct sctp_association *asoc;
866163953Srrs	int some_on_streamwheel;
867294152Stuexen	int old_state;
868163953Srrs
869237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
870172090Srrs	struct socket *so;
871172090Srrs
872172090Srrs#endif
873172090Srrs
874169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT2,
875169420Srrs	    "sctp_handle_shutdown: handling SHUTDOWN\n");
876163953Srrs	if (stcb == NULL)
877163953Srrs		return;
878165220Srrs	asoc = &stcb->asoc;
879165220Srrs	if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
880165220Srrs	    (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
881163953Srrs		return;
882163953Srrs	}
883163953Srrs	if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) {
884163953Srrs		/* Shutdown NOT the expected size */
885163953Srrs		return;
886163953Srrs	}
887294152Stuexen	old_state = SCTP_GET_STATE(asoc);
888294152Stuexen	sctp_update_acked(stcb, cp, abort_flag);
889294152Stuexen	if (*abort_flag) {
890294152Stuexen		return;
891294152Stuexen	}
892165220Srrs	if (asoc->control_pdapi) {
893163953Srrs		/*
894163953Srrs		 * With a normal shutdown we assume the end of last record.
895163953Srrs		 */
896163953Srrs		SCTP_INP_READ_LOCK(stcb->sctp_ep);
897165220Srrs		asoc->control_pdapi->end_added = 1;
898165220Srrs		asoc->control_pdapi->pdapi_aborted = 1;
899165220Srrs		asoc->control_pdapi = NULL;
900163953Srrs		SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
901237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
902172090Srrs		so = SCTP_INP_SO(stcb->sctp_ep);
903172090Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
904172090Srrs		SCTP_TCB_UNLOCK(stcb);
905172090Srrs		SCTP_SOCKET_LOCK(so, 1);
906172090Srrs		SCTP_TCB_LOCK(stcb);
907172090Srrs		atomic_subtract_int(&stcb->asoc.refcnt, 1);
908172090Srrs		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
909172090Srrs			/* assoc was freed while we were unlocked */
910172090Srrs			SCTP_SOCKET_UNLOCK(so, 1);
911172090Srrs			return;
912172090Srrs		}
913172090Srrs#endif
914296052Stuexen		if (stcb->sctp_socket) {
915296052Stuexen			sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
916296052Stuexen		}
917237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
918172090Srrs		SCTP_SOCKET_UNLOCK(so, 1);
919172090Srrs#endif
920163953Srrs	}
921163953Srrs	/* goto SHUTDOWN_RECEIVED state to block new requests */
922163953Srrs	if (stcb->sctp_socket) {
923163953Srrs		if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
924170056Srrs		    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) &&
925163953Srrs		    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) {
926171943Srrs			SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_RECEIVED);
927172703Srrs			SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
928163953Srrs			/*
929163953Srrs			 * notify upper layer that peer has initiated a
930163953Srrs			 * shutdown
931163953Srrs			 */
932172090Srrs			sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
933163953Srrs
934163953Srrs			/* reset time */
935169378Srrs			(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
936163953Srrs		}
937163953Srrs	}
938163953Srrs	if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) {
939163953Srrs		/*
940163953Srrs		 * stop the shutdown timer, since we WILL move to
941163953Srrs		 * SHUTDOWN-ACK-SENT.
942163953Srrs		 */
943283822Stuexen		sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb,
944283822Stuexen		    net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9);
945163953Srrs	}
946171158Srrs	/* Now is there unsent data on a stream somewhere? */
947221627Stuexen	some_on_streamwheel = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED);
948163953Srrs
949163953Srrs	if (!TAILQ_EMPTY(&asoc->send_queue) ||
950163953Srrs	    !TAILQ_EMPTY(&asoc->sent_queue) ||
951163953Srrs	    some_on_streamwheel) {
952163953Srrs		/* By returning we will push more data out */
953163953Srrs		return;
954163953Srrs	} else {
955163953Srrs		/* no outstanding data to send, so move on... */
956163953Srrs		/* send SHUTDOWN-ACK */
957163953Srrs		/* move to SHUTDOWN-ACK-SENT state */
958166675Srrs		if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
959166675Srrs		    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
960163953Srrs			SCTP_STAT_DECR_GAUGE32(sctps_currestab);
961163953Srrs		}
962172703Srrs		SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
963294152Stuexen		if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) {
964294152Stuexen			SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
965294152Stuexen			sctp_stop_timers_for_shutdown(stcb);
966294152Stuexen			sctp_send_shutdown_ack(stcb, net);
967294152Stuexen			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK,
968294152Stuexen			    stcb->sctp_ep, stcb, net);
969294152Stuexen		} else if (old_state == SCTP_STATE_SHUTDOWN_ACK_SENT) {
970294152Stuexen			sctp_send_shutdown_ack(stcb, net);
971294152Stuexen		}
972163953Srrs	}
973163953Srrs}
974163953Srrs
975163953Srrsstatic void
976228653Stuexensctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED,
977204141Stuexen    struct sctp_tcb *stcb,
978204141Stuexen    struct sctp_nets *net)
979163953Srrs{
980163953Srrs	struct sctp_association *asoc;
981163953Srrs
982237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
983172090Srrs	struct socket *so;
984172090Srrs
985172090Srrs	so = SCTP_INP_SO(stcb->sctp_ep);
986172090Srrs#endif
987169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT2,
988169420Srrs	    "sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n");
989163953Srrs	if (stcb == NULL)
990163953Srrs		return;
991163953Srrs
992163953Srrs	asoc = &stcb->asoc;
993163953Srrs	/* process according to association state */
994204141Stuexen	if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
995204141Stuexen	    (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
996204141Stuexen		/* unexpected SHUTDOWN-ACK... do OOTB handling... */
997204141Stuexen		sctp_send_shutdown_complete(stcb, net, 1);
998204141Stuexen		SCTP_TCB_UNLOCK(stcb);
999204141Stuexen		return;
1000204141Stuexen	}
1001163953Srrs	if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
1002163953Srrs	    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
1003163953Srrs		/* unexpected SHUTDOWN-ACK... so ignore... */
1004163953Srrs		SCTP_TCB_UNLOCK(stcb);
1005163953Srrs		return;
1006163953Srrs	}
1007165220Srrs	if (asoc->control_pdapi) {
1008163953Srrs		/*
1009163953Srrs		 * With a normal shutdown we assume the end of last record.
1010163953Srrs		 */
1011163953Srrs		SCTP_INP_READ_LOCK(stcb->sctp_ep);
1012165220Srrs		asoc->control_pdapi->end_added = 1;
1013165220Srrs		asoc->control_pdapi->pdapi_aborted = 1;
1014165220Srrs		asoc->control_pdapi = NULL;
1015163953Srrs		SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
1016237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1017172090Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
1018172090Srrs		SCTP_TCB_UNLOCK(stcb);
1019172090Srrs		SCTP_SOCKET_LOCK(so, 1);
1020172090Srrs		SCTP_TCB_LOCK(stcb);
1021172090Srrs		atomic_subtract_int(&stcb->asoc.refcnt, 1);
1022172090Srrs		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
1023172090Srrs			/* assoc was freed while we were unlocked */
1024172090Srrs			SCTP_SOCKET_UNLOCK(so, 1);
1025172090Srrs			return;
1026172090Srrs		}
1027172090Srrs#endif
1028163996Srrs		sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
1029237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1030172090Srrs		SCTP_SOCKET_UNLOCK(so, 1);
1031172090Srrs#endif
1032163953Srrs	}
1033252585Stuexen#ifdef INVARIANTS
1034163953Srrs	if (!TAILQ_EMPTY(&asoc->send_queue) ||
1035163953Srrs	    !TAILQ_EMPTY(&asoc->sent_queue) ||
1036217760Stuexen	    !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
1037252585Stuexen		panic("Queues are not empty when handling SHUTDOWN-ACK");
1038163953Srrs	}
1039252585Stuexen#endif
1040163953Srrs	/* stop the timer */
1041283822Stuexen	sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net,
1042283822Stuexen	    SCTP_FROM_SCTP_INPUT + SCTP_LOC_10);
1043163953Srrs	/* send SHUTDOWN-COMPLETE */
1044204141Stuexen	sctp_send_shutdown_complete(stcb, net, 0);
1045163953Srrs	/* notify upper layer protocol */
1046163953Srrs	if (stcb->sctp_socket) {
1047163953Srrs		if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1048163953Srrs		    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
1049229774Stuexen			stcb->sctp_socket->so_snd.sb_cc = 0;
1050163953Srrs		}
1051230379Stuexen		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
1052163953Srrs	}
1053163953Srrs	SCTP_STAT_INCR_COUNTER32(sctps_shutdown);
1054163953Srrs	/* free the TCB but first save off the ep */
1055237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1056172090Srrs	atomic_add_int(&stcb->asoc.refcnt, 1);
1057172090Srrs	SCTP_TCB_UNLOCK(stcb);
1058172090Srrs	SCTP_SOCKET_LOCK(so, 1);
1059172090Srrs	SCTP_TCB_LOCK(stcb);
1060172090Srrs	atomic_subtract_int(&stcb->asoc.refcnt, 1);
1061172090Srrs#endif
1062171943Srrs	(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
1063283822Stuexen	    SCTP_FROM_SCTP_INPUT + SCTP_LOC_11);
1064237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1065172090Srrs	SCTP_SOCKET_UNLOCK(so, 1);
1066172090Srrs#endif
1067163953Srrs}
1068163953Srrs
1069163953Srrs/*
1070163953Srrs * Skip past the param header and then we will find the chunk that caused the
1071163953Srrs * problem. There are two possiblities ASCONF or FWD-TSN other than that and
1072163953Srrs * our peer must be broken.
1073163953Srrs */
1074163953Srrsstatic void
1075163953Srrssctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr,
1076163953Srrs    struct sctp_nets *net)
1077163953Srrs{
1078163953Srrs	struct sctp_chunkhdr *chk;
1079163953Srrs
1080163953Srrs	chk = (struct sctp_chunkhdr *)((caddr_t)phdr + sizeof(*phdr));
1081163953Srrs	switch (chk->chunk_type) {
1082163953Srrs	case SCTP_ASCONF_ACK:
1083163953Srrs	case SCTP_ASCONF:
1084163953Srrs		sctp_asconf_cleanup(stcb, net);
1085163953Srrs		break;
1086163953Srrs	case SCTP_FORWARD_CUM_TSN:
1087270357Stuexen		stcb->asoc.prsctp_supported = 0;
1088163953Srrs		break;
1089163953Srrs	default:
1090169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT2,
1091169420Srrs		    "Peer does not support chunk type %d(%x)??\n",
1092169420Srrs		    chk->chunk_type, (uint32_t) chk->chunk_type);
1093163953Srrs		break;
1094163953Srrs	}
1095163953Srrs}
1096163953Srrs
1097163953Srrs/*
1098163953Srrs * Skip past the param header and then we will find the param that caused the
1099163953Srrs * problem.  There are a number of param's in a ASCONF OR the prsctp param
1100163953Srrs * these will turn of specific features.
1101270362Stuexen * XXX: Is this the right thing to do?
1102163953Srrs */
1103163953Srrsstatic void
1104163953Srrssctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr)
1105163953Srrs{
1106163953Srrs	struct sctp_paramhdr *pbad;
1107163953Srrs
1108163953Srrs	pbad = phdr + 1;
1109163953Srrs	switch (ntohs(pbad->param_type)) {
1110163953Srrs		/* pr-sctp draft */
1111163953Srrs	case SCTP_PRSCTP_SUPPORTED:
1112270357Stuexen		stcb->asoc.prsctp_supported = 0;
1113163953Srrs		break;
1114163953Srrs	case SCTP_SUPPORTED_CHUNK_EXT:
1115163953Srrs		break;
1116163953Srrs		/* draft-ietf-tsvwg-addip-sctp */
1117185694Srrs	case SCTP_HAS_NAT_SUPPORT:
1118185694Srrs		stcb->asoc.peer_supports_nat = 0;
1119185694Srrs		break;
1120163953Srrs	case SCTP_ADD_IP_ADDRESS:
1121163953Srrs	case SCTP_DEL_IP_ADDRESS:
1122163953Srrs	case SCTP_SET_PRIM_ADDR:
1123270362Stuexen		stcb->asoc.asconf_supported = 0;
1124163953Srrs		break;
1125163953Srrs	case SCTP_SUCCESS_REPORT:
1126163953Srrs	case SCTP_ERROR_CAUSE_IND:
1127169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support success? or error cause?\n");
1128169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT2,
1129169420Srrs		    "Turning off ASCONF to this strange peer\n");
1130270362Stuexen		stcb->asoc.asconf_supported = 0;
1131163953Srrs		break;
1132163953Srrs	default:
1133169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT2,
1134169420Srrs		    "Peer does not support param type %d(%x)??\n",
1135169420Srrs		    pbad->param_type, (uint32_t) pbad->param_type);
1136163953Srrs		break;
1137163953Srrs	}
1138163953Srrs}
1139163953Srrs
1140163953Srrsstatic int
1141163953Srrssctp_handle_error(struct sctp_chunkhdr *ch,
1142163953Srrs    struct sctp_tcb *stcb, struct sctp_nets *net)
1143163953Srrs{
1144163953Srrs	int chklen;
1145163953Srrs	struct sctp_paramhdr *phdr;
1146235418Stuexen	uint16_t error, error_type;
1147163953Srrs	uint16_t error_len;
1148163953Srrs	struct sctp_association *asoc;
1149163953Srrs	int adjust;
1150163953Srrs
1151237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1152172090Srrs	struct socket *so;
1153172090Srrs
1154172090Srrs#endif
1155172090Srrs
1156163953Srrs	/* parse through all of the errors and process */
1157163953Srrs	asoc = &stcb->asoc;
1158163953Srrs	phdr = (struct sctp_paramhdr *)((caddr_t)ch +
1159163953Srrs	    sizeof(struct sctp_chunkhdr));
1160163953Srrs	chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr);
1161235418Stuexen	error = 0;
1162163953Srrs	while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) {
1163163953Srrs		/* Process an Error Cause */
1164163953Srrs		error_type = ntohs(phdr->param_type);
1165163953Srrs		error_len = ntohs(phdr->param_length);
1166163953Srrs		if ((error_len > chklen) || (error_len == 0)) {
1167163953Srrs			/* invalid param length for this param */
1168169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT1, "Bogus length in error param- chunk left:%d errorlen:%d\n",
1169169420Srrs			    chklen, error_len);
1170163953Srrs			return (0);
1171163953Srrs		}
1172235418Stuexen		if (error == 0) {
1173235418Stuexen			/* report the first error cause */
1174235418Stuexen			error = error_type;
1175235418Stuexen		}
1176163953Srrs		switch (error_type) {
1177163953Srrs		case SCTP_CAUSE_INVALID_STREAM:
1178163953Srrs		case SCTP_CAUSE_MISSING_PARAM:
1179163953Srrs		case SCTP_CAUSE_INVALID_PARAM:
1180163953Srrs		case SCTP_CAUSE_NO_USER_DATA:
1181169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT1, "Software error we got a %d back? We have a bug :/ (or do they?)\n",
1182169420Srrs			    error_type);
1183163953Srrs			break;
1184185694Srrs		case SCTP_CAUSE_NAT_COLLIDING_STATE:
1185185694Srrs			SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n",
1186185694Srrs			    ch->chunk_flags);
1187185694Srrs			if (sctp_handle_nat_colliding_state(stcb)) {
1188185694Srrs				return (0);
1189185694Srrs			}
1190185694Srrs			break;
1191185694Srrs		case SCTP_CAUSE_NAT_MISSING_STATE:
1192185694Srrs			SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n",
1193185694Srrs			    ch->chunk_flags);
1194185694Srrs			if (sctp_handle_nat_missing_state(stcb, net)) {
1195185694Srrs				return (0);
1196185694Srrs			}
1197185694Srrs			break;
1198163953Srrs		case SCTP_CAUSE_STALE_COOKIE:
1199163953Srrs			/*
1200163953Srrs			 * We only act if we have echoed a cookie and are
1201163953Srrs			 * waiting.
1202163953Srrs			 */
1203163953Srrs			if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) {
1204163953Srrs				int *p;
1205163953Srrs
1206163953Srrs				p = (int *)((caddr_t)phdr + sizeof(*phdr));
1207163953Srrs				/* Save the time doubled */
1208163953Srrs				asoc->cookie_preserve_req = ntohl(*p) << 1;
1209163953Srrs				asoc->stale_cookie_count++;
1210163953Srrs				if (asoc->stale_cookie_count >
1211163953Srrs				    asoc->max_init_times) {
1212235403Stuexen					sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
1213163953Srrs					/* now free the asoc */
1214237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1215172090Srrs					so = SCTP_INP_SO(stcb->sctp_ep);
1216172090Srrs					atomic_add_int(&stcb->asoc.refcnt, 1);
1217172090Srrs					SCTP_TCB_UNLOCK(stcb);
1218172090Srrs					SCTP_SOCKET_LOCK(so, 1);
1219172090Srrs					SCTP_TCB_LOCK(stcb);
1220172090Srrs					atomic_subtract_int(&stcb->asoc.refcnt, 1);
1221172090Srrs#endif
1222171943Srrs					(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
1223283822Stuexen					    SCTP_FROM_SCTP_INPUT + SCTP_LOC_12);
1224237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1225172090Srrs					SCTP_SOCKET_UNLOCK(so, 1);
1226172090Srrs#endif
1227163953Srrs					return (-1);
1228163953Srrs				}
1229163953Srrs				/* blast back to INIT state */
1230185694Srrs				sctp_toss_old_cookies(stcb, &stcb->asoc);
1231163953Srrs				asoc->state &= ~SCTP_STATE_COOKIE_ECHOED;
1232163953Srrs				asoc->state |= SCTP_STATE_COOKIE_WAIT;
1233163953Srrs				sctp_stop_all_cookie_timers(stcb);
1234172090Srrs				sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
1235163953Srrs			}
1236163953Srrs			break;
1237163953Srrs		case SCTP_CAUSE_UNRESOLVABLE_ADDR:
1238163953Srrs			/*
1239163953Srrs			 * Nothing we can do here, we don't do hostname
1240163953Srrs			 * addresses so if the peer does not like my IPv6
1241163953Srrs			 * (or IPv4 for that matter) it does not matter. If
1242163953Srrs			 * they don't support that type of address, they can
1243163953Srrs			 * NOT possibly get that packet type... i.e. with no
1244163953Srrs			 * IPv6 you can't recieve a IPv6 packet. so we can
1245163953Srrs			 * safely ignore this one. If we ever added support
1246163953Srrs			 * for HOSTNAME Addresses, then we would need to do
1247163953Srrs			 * something here.
1248163953Srrs			 */
1249163953Srrs			break;
1250163953Srrs		case SCTP_CAUSE_UNRECOG_CHUNK:
1251163953Srrs			sctp_process_unrecog_chunk(stcb, phdr, net);
1252163953Srrs			break;
1253163953Srrs		case SCTP_CAUSE_UNRECOG_PARAM:
1254163953Srrs			sctp_process_unrecog_param(stcb, phdr);
1255163953Srrs			break;
1256163953Srrs		case SCTP_CAUSE_COOKIE_IN_SHUTDOWN:
1257163953Srrs			/*
1258163953Srrs			 * We ignore this since the timer will drive out a
1259163953Srrs			 * new cookie anyway and there timer will drive us
1260163953Srrs			 * to send a SHUTDOWN_COMPLETE. We can't send one
1261163953Srrs			 * here since we don't have their tag.
1262163953Srrs			 */
1263163953Srrs			break;
1264163953Srrs		case SCTP_CAUSE_DELETING_LAST_ADDR:
1265163953Srrs		case SCTP_CAUSE_RESOURCE_SHORTAGE:
1266163953Srrs		case SCTP_CAUSE_DELETING_SRC_ADDR:
1267163953Srrs			/*
1268163953Srrs			 * We should NOT get these here, but in a
1269166086Srrs			 * ASCONF-ACK.
1270163953Srrs			 */
1271169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT2, "Peer sends ASCONF errors in a Operational Error?<%d>?\n",
1272169420Srrs			    error_type);
1273163953Srrs			break;
1274163953Srrs		case SCTP_CAUSE_OUT_OF_RESC:
1275163953Srrs			/*
1276163953Srrs			 * And what, pray tell do we do with the fact that
1277163953Srrs			 * the peer is out of resources? Not really sure we
1278166086Srrs			 * could do anything but abort. I suspect this
1279163953Srrs			 * should have came WITH an abort instead of in a
1280163953Srrs			 * OP-ERROR.
1281163953Srrs			 */
1282163953Srrs			break;
1283163953Srrs		default:
1284169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_handle_error: unknown error type = 0x%xh\n",
1285169420Srrs			    error_type);
1286163953Srrs			break;
1287163953Srrs		}
1288163953Srrs		adjust = SCTP_SIZE32(error_len);
1289163953Srrs		chklen -= adjust;
1290163953Srrs		phdr = (struct sctp_paramhdr *)((caddr_t)phdr + adjust);
1291163953Srrs	}
1292235418Stuexen	sctp_ulp_notify(SCTP_NOTIFY_REMOTE_ERROR, stcb, error, ch, SCTP_SO_NOT_LOCKED);
1293163953Srrs	return (0);
1294163953Srrs}
1295163953Srrs
1296163953Srrsstatic int
1297237715Stuexensctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
1298237715Stuexen    struct sockaddr *src, struct sockaddr *dst, struct sctphdr *sh,
1299237049Stuexen    struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
1300237049Stuexen    struct sctp_nets *net, int *abort_no_unlock,
1301281955Shiren    uint8_t mflowtype, uint32_t mflowid,
1302237049Stuexen    uint32_t vrf_id)
1303163953Srrs{
1304163953Srrs	struct sctp_init_ack *init_ack;
1305163953Srrs	struct mbuf *op_err;
1306163953Srrs
1307169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT2,
1308169420Srrs	    "sctp_handle_init_ack: handling INIT-ACK\n");
1309169420Srrs
1310163953Srrs	if (stcb == NULL) {
1311169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT2,
1312169420Srrs		    "sctp_handle_init_ack: TCB is null\n");
1313163953Srrs		return (-1);
1314163953Srrs	}
1315163953Srrs	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) {
1316163953Srrs		/* Invalid length */
1317267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
1318237715Stuexen		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
1319237715Stuexen		    src, dst, sh, op_err,
1320281955Shiren		    mflowtype, mflowid,
1321237049Stuexen		    vrf_id, net->port);
1322168299Srrs		*abort_no_unlock = 1;
1323163953Srrs		return (-1);
1324163953Srrs	}
1325163953Srrs	init_ack = &cp->init;
1326163953Srrs	/* validate parameters */
1327163953Srrs	if (init_ack->initiate_tag == 0) {
1328163953Srrs		/* protocol error... send an abort */
1329267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
1330237715Stuexen		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
1331237715Stuexen		    src, dst, sh, op_err,
1332281955Shiren		    mflowtype, mflowid,
1333237049Stuexen		    vrf_id, net->port);
1334168299Srrs		*abort_no_unlock = 1;
1335163953Srrs		return (-1);
1336163953Srrs	}
1337163953Srrs	if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) {
1338163953Srrs		/* protocol error... send an abort */
1339267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
1340237715Stuexen		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
1341237715Stuexen		    src, dst, sh, op_err,
1342281955Shiren		    mflowtype, mflowid,
1343237049Stuexen		    vrf_id, net->port);
1344168299Srrs		*abort_no_unlock = 1;
1345163953Srrs		return (-1);
1346163953Srrs	}
1347163953Srrs	if (init_ack->num_inbound_streams == 0) {
1348163953Srrs		/* protocol error... send an abort */
1349267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
1350237715Stuexen		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
1351237715Stuexen		    src, dst, sh, op_err,
1352281955Shiren		    mflowtype, mflowid,
1353237049Stuexen		    vrf_id, net->port);
1354168299Srrs		*abort_no_unlock = 1;
1355163953Srrs		return (-1);
1356163953Srrs	}
1357163953Srrs	if (init_ack->num_outbound_streams == 0) {
1358163953Srrs		/* protocol error... send an abort */
1359267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, "");
1360237715Stuexen		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
1361237715Stuexen		    src, dst, sh, op_err,
1362281955Shiren		    mflowtype, mflowid,
1363237049Stuexen		    vrf_id, net->port);
1364168299Srrs		*abort_no_unlock = 1;
1365163953Srrs		return (-1);
1366163953Srrs	}
1367163953Srrs	/* process according to association state... */
1368171943Srrs	switch (stcb->asoc.state & SCTP_STATE_MASK) {
1369163953Srrs	case SCTP_STATE_COOKIE_WAIT:
1370163953Srrs		/* this is the expected state for this chunk */
1371163953Srrs		/* process the INIT-ACK parameters */
1372163953Srrs		if (stcb->asoc.primary_destination->dest_state &
1373163953Srrs		    SCTP_ADDR_UNCONFIRMED) {
1374163953Srrs			/*
1375163953Srrs			 * The primary is where we sent the INIT, we can
1376163953Srrs			 * always consider it confirmed when the INIT-ACK is
1377163953Srrs			 * returned. Do this before we load addresses
1378163953Srrs			 * though.
1379163953Srrs			 */
1380163953Srrs			stcb->asoc.primary_destination->dest_state &=
1381163953Srrs			    ~SCTP_ADDR_UNCONFIRMED;
1382163953Srrs			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
1383172090Srrs			    stcb, 0, (void *)stcb->asoc.primary_destination, SCTP_SO_NOT_LOCKED);
1384163953Srrs		}
1385237715Stuexen		if (sctp_process_init_ack(m, iphlen, offset, src, dst, sh, cp, stcb,
1386237049Stuexen		    net, abort_no_unlock,
1387281955Shiren		    mflowtype, mflowid,
1388237049Stuexen		    vrf_id) < 0) {
1389163953Srrs			/* error in parsing parameters */
1390163953Srrs			return (-1);
1391163953Srrs		}
1392163953Srrs		/* update our state */
1393169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT2, "moving to COOKIE-ECHOED state\n");
1394171943Srrs		SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_ECHOED);
1395163953Srrs
1396163953Srrs		/* reset the RTO calc */
1397179783Srrs		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
1398171943Srrs			sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
1399171943Srrs			    stcb->asoc.overall_error_count,
1400171943Srrs			    0,
1401171943Srrs			    SCTP_FROM_SCTP_INPUT,
1402171943Srrs			    __LINE__);
1403171943Srrs		}
1404163953Srrs		stcb->asoc.overall_error_count = 0;
1405169378Srrs		(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
1406163953Srrs		/*
1407163953Srrs		 * collapse the init timer back in case of a exponential
1408165220Srrs		 * backoff
1409163953Srrs		 */
1410163953Srrs		sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep,
1411163953Srrs		    stcb, net);
1412163953Srrs		/*
1413163953Srrs		 * the send at the end of the inbound data processing will
1414163953Srrs		 * cause the cookie to be sent
1415163953Srrs		 */
1416163953Srrs		break;
1417163953Srrs	case SCTP_STATE_SHUTDOWN_SENT:
1418163953Srrs		/* incorrect state... discard */
1419163953Srrs		break;
1420163953Srrs	case SCTP_STATE_COOKIE_ECHOED:
1421163953Srrs		/* incorrect state... discard */
1422163953Srrs		break;
1423163953Srrs	case SCTP_STATE_OPEN:
1424163953Srrs		/* incorrect state... discard */
1425163953Srrs		break;
1426163953Srrs	case SCTP_STATE_EMPTY:
1427163953Srrs	case SCTP_STATE_INUSE:
1428163953Srrs	default:
1429163953Srrs		/* incorrect state... discard */
1430163953Srrs		return (-1);
1431163953Srrs		break;
1432163953Srrs	}
1433169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT1, "Leaving handle-init-ack end\n");
1434163953Srrs	return (0);
1435163953Srrs}
1436163953Srrs
1437185694Srrsstatic struct sctp_tcb *
1438185694Srrssctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
1439237715Stuexen    struct sockaddr *src, struct sockaddr *dst,
1440185694Srrs    struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
1441185694Srrs    struct sctp_inpcb *inp, struct sctp_nets **netp,
1442185694Srrs    struct sockaddr *init_src, int *notification,
1443185694Srrs    int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
1444281955Shiren    uint8_t mflowtype, uint32_t mflowid,
1445185694Srrs    uint32_t vrf_id, uint16_t port);
1446163953Srrs
1447185694Srrs
1448163953Srrs/*
1449163953Srrs * handle a state cookie for an existing association m: input packet mbuf
1450163953Srrs * chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a
1451163953Srrs * "split" mbuf and the cookie signature does not exist offset: offset into
1452163953Srrs * mbuf to the cookie-echo chunk
1453163953Srrs */
1454163953Srrsstatic struct sctp_tcb *
1455163953Srrssctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
1456237715Stuexen    struct sockaddr *src, struct sockaddr *dst,
1457163953Srrs    struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
1458185694Srrs    struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp,
1459228653Stuexen    struct sockaddr *init_src, int *notification,
1460237049Stuexen    int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
1461281955Shiren    uint8_t mflowtype, uint32_t mflowid,
1462237049Stuexen    uint32_t vrf_id, uint16_t port)
1463163953Srrs{
1464163953Srrs	struct sctp_association *asoc;
1465163953Srrs	struct sctp_init_chunk *init_cp, init_buf;
1466163953Srrs	struct sctp_init_ack_chunk *initack_cp, initack_buf;
1467185694Srrs	struct sctp_nets *net;
1468185694Srrs	struct mbuf *op_err;
1469165220Srrs	int init_offset, initack_offset, i;
1470163953Srrs	int retval;
1471164205Srrs	int spec_flag = 0;
1472170140Srrs	uint32_t how_indx;
1473163953Srrs
1474270363Stuexen#if defined(SCTP_DETAILED_STR_STATS)
1475270363Stuexen	int j;
1476270363Stuexen
1477270363Stuexen#endif
1478270363Stuexen
1479185694Srrs	net = *netp;
1480163953Srrs	/* I know that the TCB is non-NULL from the caller */
1481163953Srrs	asoc = &stcb->asoc;
1482166675Srrs	for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); how_indx++) {
1483166023Srrs		if (asoc->cookie_how[how_indx] == 0)
1484166023Srrs			break;
1485166023Srrs	}
1486166023Srrs	if (how_indx < sizeof(asoc->cookie_how)) {
1487166023Srrs		asoc->cookie_how[how_indx] = 1;
1488166023Srrs	}
1489163953Srrs	if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
1490163953Srrs		/* SHUTDOWN came in after sending INIT-ACK */
1491163953Srrs		sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
1492267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, "");
1493237715Stuexen		sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
1494284633Stuexen		    mflowtype, mflowid, inp->fibnum,
1495179157Srrs		    vrf_id, net->port);
1496166023Srrs		if (how_indx < sizeof(asoc->cookie_how))
1497166023Srrs			asoc->cookie_how[how_indx] = 2;
1498163953Srrs		return (NULL);
1499163953Srrs	}
1500163953Srrs	/*
1501163953Srrs	 * find and validate the INIT chunk in the cookie (peer's info) the
1502163953Srrs	 * INIT should start after the cookie-echo header struct (chunk
1503163953Srrs	 * header, state cookie header struct)
1504163953Srrs	 */
1505163953Srrs	init_offset = offset += sizeof(struct sctp_cookie_echo_chunk);
1506163953Srrs
1507163953Srrs	init_cp = (struct sctp_init_chunk *)
1508163953Srrs	    sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk),
1509163953Srrs	    (uint8_t *) & init_buf);
1510163953Srrs	if (init_cp == NULL) {
1511163953Srrs		/* could not pull a INIT chunk in cookie */
1512163953Srrs		return (NULL);
1513163953Srrs	}
1514163953Srrs	if (init_cp->ch.chunk_type != SCTP_INITIATION) {
1515163953Srrs		return (NULL);
1516163953Srrs	}
1517163953Srrs	/*
1518163953Srrs	 * find and validate the INIT-ACK chunk in the cookie (my info) the
1519163953Srrs	 * INIT-ACK follows the INIT chunk
1520163953Srrs	 */
1521228907Stuexen	initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length));
1522163953Srrs	initack_cp = (struct sctp_init_ack_chunk *)
1523163953Srrs	    sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk),
1524163953Srrs	    (uint8_t *) & initack_buf);
1525163953Srrs	if (initack_cp == NULL) {
1526163953Srrs		/* could not pull INIT-ACK chunk in cookie */
1527163953Srrs		return (NULL);
1528163953Srrs	}
1529163953Srrs	if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) {
1530163953Srrs		return (NULL);
1531163953Srrs	}
1532163953Srrs	if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) &&
1533163953Srrs	    (ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag)) {
1534163953Srrs		/*
1535163953Srrs		 * case D in Section 5.2.4 Table 2: MMAA process accordingly
1536163953Srrs		 * to get into the OPEN state
1537163953Srrs		 */
1538166023Srrs		if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) {
1539172091Srrs			/*-
1540172091Srrs			 * Opps, this means that we somehow generated two vtag's
1541172091Srrs			 * the same. I.e. we did:
1542172091Srrs			 *  Us               Peer
1543172091Srrs			 *   <---INIT(tag=a)------
1544172091Srrs			 *   ----INIT-ACK(tag=t)-->
1545172091Srrs			 *   ----INIT(tag=t)------> *1
1546172091Srrs			 *   <---INIT-ACK(tag=a)---
1547172091Srrs                         *   <----CE(tag=t)------------- *2
1548172091Srrs			 *
1549172091Srrs			 * At point *1 we should be generating a different
1550172091Srrs			 * tag t'. Which means we would throw away the CE and send
1551172091Srrs			 * ours instead. Basically this is case C (throw away side).
1552172091Srrs			 */
1553172091Srrs			if (how_indx < sizeof(asoc->cookie_how))
1554172091Srrs				asoc->cookie_how[how_indx] = 17;
1555172091Srrs			return (NULL);
1556172091Srrs
1557166023Srrs		}
1558267720Stuexen		switch (SCTP_GET_STATE(asoc)) {
1559163953Srrs		case SCTP_STATE_COOKIE_WAIT:
1560166023Srrs		case SCTP_STATE_COOKIE_ECHOED:
1561163953Srrs			/*
1562169352Srrs			 * INIT was sent but got a COOKIE_ECHO with the
1563166023Srrs			 * correct tags... just accept it...but we must
1564166023Srrs			 * process the init so that we can make sure we have
1565166023Srrs			 * the right seq no's.
1566163953Srrs			 */
1567163953Srrs			/* First we must process the INIT !! */
1568228653Stuexen			retval = sctp_process_init(init_cp, stcb);
1569163953Srrs			if (retval < 0) {
1570166023Srrs				if (how_indx < sizeof(asoc->cookie_how))
1571166023Srrs					asoc->cookie_how[how_indx] = 3;
1572163953Srrs				return (NULL);
1573163953Srrs			}
1574163953Srrs			/* we have already processed the INIT so no problem */
1575283822Stuexen			sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp,
1576283822Stuexen			    stcb, net,
1577283822Stuexen			    SCTP_FROM_SCTP_INPUT + SCTP_LOC_13);
1578283822Stuexen			sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp,
1579283822Stuexen			    stcb, net,
1580283822Stuexen			    SCTP_FROM_SCTP_INPUT + SCTP_LOC_14);
1581163953Srrs			/* update current state */
1582166675Srrs			if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)
1583166675Srrs				SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
1584166675Srrs			else
1585166675Srrs				SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
1586171943Srrs
1587171943Srrs			SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
1588163953Srrs			if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
1589163953Srrs				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1590163953Srrs				    stcb->sctp_ep, stcb, asoc->primary_destination);
1591163953Srrs			}
1592166675Srrs			SCTP_STAT_INCR_GAUGE32(sctps_currestab);
1593165220Srrs			sctp_stop_all_cookie_timers(stcb);
1594163953Srrs			if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1595163953Srrs			    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
1596163953Srrs			    (inp->sctp_socket->so_qlimit == 0)
1597163953Srrs			    ) {
1598237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1599172090Srrs				struct socket *so;
1600172090Srrs
1601172090Srrs#endif
1602163953Srrs				/*
1603163953Srrs				 * Here is where collision would go if we
1604163953Srrs				 * did a connect() and instead got a
1605163953Srrs				 * init/init-ack/cookie done before the
1606163953Srrs				 * init-ack came back..
1607163953Srrs				 */
1608163953Srrs				stcb->sctp_ep->sctp_flags |=
1609163953Srrs				    SCTP_PCB_FLAGS_CONNECTED;
1610237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1611172090Srrs				so = SCTP_INP_SO(stcb->sctp_ep);
1612172090Srrs				atomic_add_int(&stcb->asoc.refcnt, 1);
1613172090Srrs				SCTP_TCB_UNLOCK(stcb);
1614172090Srrs				SCTP_SOCKET_LOCK(so, 1);
1615172090Srrs				SCTP_TCB_LOCK(stcb);
1616172090Srrs				atomic_add_int(&stcb->asoc.refcnt, -1);
1617172090Srrs				if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
1618172090Srrs					SCTP_SOCKET_UNLOCK(so, 1);
1619172090Srrs					return (NULL);
1620172090Srrs				}
1621172090Srrs#endif
1622172090Srrs				soisconnected(stcb->sctp_socket);
1623237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1624172090Srrs				SCTP_SOCKET_UNLOCK(so, 1);
1625172090Srrs#endif
1626163953Srrs			}
1627163953Srrs			/* notify upper layer */
1628163953Srrs			*notification = SCTP_NOTIFY_ASSOC_UP;
1629163953Srrs			/*
1630163953Srrs			 * since we did not send a HB make sure we don't
1631163953Srrs			 * double things
1632163953Srrs			 */
1633163953Srrs			net->hb_responded = 1;
1634170642Srrs			net->RTO = sctp_calculate_rto(stcb, asoc, net,
1635218186Srrs			    &cookie->time_entered,
1636218186Srrs			    sctp_align_unsafe_makecopy,
1637219397Srrs			    SCTP_RTT_FROM_NON_DATA);
1638163953Srrs
1639163953Srrs			if (stcb->asoc.sctp_autoclose_ticks &&
1640163953Srrs			    (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) {
1641163953Srrs				sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE,
1642163953Srrs				    inp, stcb, NULL);
1643163953Srrs			}
1644163953Srrs			break;
1645163953Srrs		default:
1646163953Srrs			/*
1647163953Srrs			 * we're in the OPEN state (or beyond), so peer must
1648163953Srrs			 * have simply lost the COOKIE-ACK
1649163953Srrs			 */
1650163953Srrs			break;
1651267720Stuexen		}		/* end switch */
1652165220Srrs		sctp_stop_all_cookie_timers(stcb);
1653163953Srrs		/*
1654163953Srrs		 * We ignore the return code here.. not sure if we should
1655163953Srrs		 * somehow abort.. but we do have an existing asoc. This
1656163953Srrs		 * really should not fail.
1657163953Srrs		 */
1658228653Stuexen		if (sctp_load_addresses_from_init(stcb, m,
1659163953Srrs		    init_offset + sizeof(struct sctp_init_chunk),
1660237715Stuexen		    initack_offset, src, dst, init_src)) {
1661166023Srrs			if (how_indx < sizeof(asoc->cookie_how))
1662166023Srrs				asoc->cookie_how[how_indx] = 4;
1663163953Srrs			return (NULL);
1664163953Srrs		}
1665163953Srrs		/* respond with a COOKIE-ACK */
1666165220Srrs		sctp_toss_old_cookies(stcb, asoc);
1667163953Srrs		sctp_send_cookie_ack(stcb);
1668166023Srrs		if (how_indx < sizeof(asoc->cookie_how))
1669166023Srrs			asoc->cookie_how[how_indx] = 5;
1670163953Srrs		return (stcb);
1671169352Srrs	}
1672163953Srrs	if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag &&
1673163953Srrs	    ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag &&
1674163953Srrs	    cookie->tie_tag_my_vtag == 0 &&
1675163953Srrs	    cookie->tie_tag_peer_vtag == 0) {
1676163953Srrs		/*
1677163953Srrs		 * case C in Section 5.2.4 Table 2: XMOO silently discard
1678163953Srrs		 */
1679166023Srrs		if (how_indx < sizeof(asoc->cookie_how))
1680166023Srrs			asoc->cookie_how[how_indx] = 6;
1681163953Srrs		return (NULL);
1682163953Srrs	}
1683185694Srrs	/*
1684185694Srrs	 * If nat support, and the below and stcb is established, send back
1685185694Srrs	 * a ABORT(colliding state) if we are established.
1686185694Srrs	 */
1687185694Srrs	if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) &&
1688185694Srrs	    (asoc->peer_supports_nat) &&
1689185694Srrs	    ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) &&
1690185694Srrs	    ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) ||
1691185694Srrs	    (asoc->peer_vtag == 0)))) {
1692163953Srrs		/*
1693185694Srrs		 * Special case - Peer's support nat. We may have two init's
1694185694Srrs		 * that we gave out the same tag on since one was not
1695185694Srrs		 * established.. i.e. we get INIT from host-1 behind the nat
1696185694Srrs		 * and we respond tag-a, we get a INIT from host-2 behind
1697185694Srrs		 * the nat and we get tag-a again. Then we bring up host-1
1698185694Srrs		 * (or 2's) assoc, Then comes the cookie from hsot-2 (or 1).
1699185694Srrs		 * Now we have colliding state. We must send an abort here
1700185694Srrs		 * with colliding state indication.
1701185694Srrs		 */
1702267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_NAT_COLLIDING_STATE, "");
1703237715Stuexen		sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err,
1704284633Stuexen		    mflowtype, mflowid, inp->fibnum,
1705237049Stuexen		    vrf_id, port);
1706185694Srrs		return (NULL);
1707185694Srrs	}
1708185694Srrs	if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) &&
1709185694Srrs	    ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) ||
1710185694Srrs	    (asoc->peer_vtag == 0))) {
1711185694Srrs		/*
1712163953Srrs		 * case B in Section 5.2.4 Table 2: MXAA or MOAA my info
1713163953Srrs		 * should be ok, re-accept peer info
1714163953Srrs		 */
1715166023Srrs		if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) {
1716166023Srrs			/*
1717166023Srrs			 * Extension of case C. If we hit this, then the
1718166023Srrs			 * random number generator returned the same vtag
1719166023Srrs			 * when we first sent our INIT-ACK and when we later
1720166023Srrs			 * sent our INIT. The side with the seq numbers that
1721166023Srrs			 * are different will be the one that normnally
1722166023Srrs			 * would have hit case C. This in effect "extends"
1723166023Srrs			 * our vtags in this collision case to be 64 bits.
1724166023Srrs			 * The same collision could occur aka you get both
1725166023Srrs			 * vtag and seq number the same twice in a row.. but
1726166023Srrs			 * is much less likely. If it did happen then we
1727166023Srrs			 * would proceed through and bring up the assoc.. we
1728166023Srrs			 * may end up with the wrong stream setup however..
1729166023Srrs			 * which would be bad.. but there is no way to
1730166023Srrs			 * tell.. until we send on a stream that does not
1731166023Srrs			 * exist :-)
1732166023Srrs			 */
1733166023Srrs			if (how_indx < sizeof(asoc->cookie_how))
1734166023Srrs				asoc->cookie_how[how_indx] = 7;
1735166023Srrs
1736166023Srrs			return (NULL);
1737166023Srrs		}
1738166023Srrs		if (how_indx < sizeof(asoc->cookie_how))
1739166023Srrs			asoc->cookie_how[how_indx] = 8;
1740283822Stuexen		sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
1741283822Stuexen		    SCTP_FROM_SCTP_INPUT + SCTP_LOC_15);
1742163953Srrs		sctp_stop_all_cookie_timers(stcb);
1743163953Srrs		/*
1744163953Srrs		 * since we did not send a HB make sure we don't double
1745163953Srrs		 * things
1746163953Srrs		 */
1747163953Srrs		net->hb_responded = 1;
1748163953Srrs		if (stcb->asoc.sctp_autoclose_ticks &&
1749163953Srrs		    sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) {
1750163953Srrs			sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb,
1751163953Srrs			    NULL);
1752163953Srrs		}
1753163953Srrs		asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
1754164205Srrs		asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams);
1755164205Srrs
1756164205Srrs		if (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) {
1757164205Srrs			/*
1758164205Srrs			 * Ok the peer probably discarded our data (if we
1759164205Srrs			 * echoed a cookie+data). So anything on the
1760164205Srrs			 * sent_queue should be marked for retransmit, we
1761164205Srrs			 * may not get something to kick us so it COULD
1762164205Srrs			 * still take a timeout to move these.. but it can't
1763164205Srrs			 * hurt to mark them.
1764164205Srrs			 */
1765164205Srrs			struct sctp_tmit_chunk *chk;
1766163953Srrs
1767164205Srrs			TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
1768164205Srrs				if (chk->sent < SCTP_DATAGRAM_RESEND) {
1769164205Srrs					chk->sent = SCTP_DATAGRAM_RESEND;
1770171440Srrs					sctp_flight_size_decrease(chk);
1771171440Srrs					sctp_total_flight_decrease(stcb, chk);
1772168124Srrs					sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
1773164205Srrs					spec_flag++;
1774164205Srrs				}
1775164205Srrs			}
1776164205Srrs
1777164205Srrs		}
1778163953Srrs		/* process the INIT info (peer's info) */
1779228653Stuexen		retval = sctp_process_init(init_cp, stcb);
1780163953Srrs		if (retval < 0) {
1781166023Srrs			if (how_indx < sizeof(asoc->cookie_how))
1782166023Srrs				asoc->cookie_how[how_indx] = 9;
1783163953Srrs			return (NULL);
1784163953Srrs		}
1785228653Stuexen		if (sctp_load_addresses_from_init(stcb, m,
1786163953Srrs		    init_offset + sizeof(struct sctp_init_chunk),
1787237715Stuexen		    initack_offset, src, dst, init_src)) {
1788166023Srrs			if (how_indx < sizeof(asoc->cookie_how))
1789166023Srrs				asoc->cookie_how[how_indx] = 10;
1790163953Srrs			return (NULL);
1791163953Srrs		}
1792163953Srrs		if ((asoc->state & SCTP_STATE_COOKIE_WAIT) ||
1793163953Srrs		    (asoc->state & SCTP_STATE_COOKIE_ECHOED)) {
1794163953Srrs			*notification = SCTP_NOTIFY_ASSOC_UP;
1795163953Srrs
1796163953Srrs			if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1797163953Srrs			    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
1798163953Srrs			    (inp->sctp_socket->so_qlimit == 0)) {
1799237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1800172090Srrs				struct socket *so;
1801172090Srrs
1802172090Srrs#endif
1803163953Srrs				stcb->sctp_ep->sctp_flags |=
1804163953Srrs				    SCTP_PCB_FLAGS_CONNECTED;
1805237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1806172090Srrs				so = SCTP_INP_SO(stcb->sctp_ep);
1807172090Srrs				atomic_add_int(&stcb->asoc.refcnt, 1);
1808172090Srrs				SCTP_TCB_UNLOCK(stcb);
1809172090Srrs				SCTP_SOCKET_LOCK(so, 1);
1810172090Srrs				SCTP_TCB_LOCK(stcb);
1811172090Srrs				atomic_add_int(&stcb->asoc.refcnt, -1);
1812172090Srrs				if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
1813172090Srrs					SCTP_SOCKET_UNLOCK(so, 1);
1814172090Srrs					return (NULL);
1815172090Srrs				}
1816172090Srrs#endif
1817172090Srrs				soisconnected(stcb->sctp_socket);
1818237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1819172090Srrs				SCTP_SOCKET_UNLOCK(so, 1);
1820172090Srrs#endif
1821163953Srrs			}
1822166675Srrs			if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)
1823166675Srrs				SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
1824166675Srrs			else
1825166675Srrs				SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
1826166675Srrs			SCTP_STAT_INCR_GAUGE32(sctps_currestab);
1827166675Srrs		} else if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
1828166675Srrs			SCTP_STAT_INCR_COUNTER32(sctps_restartestab);
1829166675Srrs		} else {
1830166675Srrs			SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
1831163953Srrs		}
1832171943Srrs		SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
1833163953Srrs		if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
1834163953Srrs			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1835163953Srrs			    stcb->sctp_ep, stcb, asoc->primary_destination);
1836163953Srrs		}
1837163953Srrs		sctp_stop_all_cookie_timers(stcb);
1838165220Srrs		sctp_toss_old_cookies(stcb, asoc);
1839163953Srrs		sctp_send_cookie_ack(stcb);
1840164205Srrs		if (spec_flag) {
1841164205Srrs			/*
1842164205Srrs			 * only if we have retrans set do we do this. What
1843164205Srrs			 * this call does is get only the COOKIE-ACK out and
1844164205Srrs			 * then when we return the normal call to
1845164205Srrs			 * sctp_chunk_output will get the retrans out behind
1846164205Srrs			 * this.
1847164205Srrs			 */
1848172090Srrs			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_COOKIE_ACK, SCTP_SO_NOT_LOCKED);
1849164205Srrs		}
1850166023Srrs		if (how_indx < sizeof(asoc->cookie_how))
1851166023Srrs			asoc->cookie_how[how_indx] = 11;
1852166023Srrs
1853163953Srrs		return (stcb);
1854163953Srrs	}
1855163953Srrs	if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag &&
1856163953Srrs	    ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) &&
1857163953Srrs	    cookie->tie_tag_my_vtag == asoc->my_vtag_nonce &&
1858163953Srrs	    cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce &&
1859163953Srrs	    cookie->tie_tag_peer_vtag != 0) {
1860163953Srrs		struct sctpasochead *head;
1861163953Srrs
1862252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1863252585Stuexen		struct socket *so;
1864252585Stuexen
1865252585Stuexen#endif
1866252585Stuexen
1867185694Srrs		if (asoc->peer_supports_nat) {
1868185694Srrs			/*
1869252585Stuexen			 * This is a gross gross hack. Just call the
1870185694Srrs			 * cookie_new code since we are allowing a duplicate
1871185694Srrs			 * association. I hope this works...
1872185694Srrs			 */
1873237715Stuexen			return (sctp_process_cookie_new(m, iphlen, offset, src, dst,
1874237715Stuexen			    sh, cookie, cookie_len,
1875185694Srrs			    inp, netp, init_src, notification,
1876185694Srrs			    auth_skipped, auth_offset, auth_len,
1877281955Shiren			    mflowtype, mflowid,
1878185694Srrs			    vrf_id, port));
1879185694Srrs		}
1880163953Srrs		/*
1881163953Srrs		 * case A in Section 5.2.4 Table 2: XXMM (peer restarted)
1882163953Srrs		 */
1883165220Srrs		/* temp code */
1884166023Srrs		if (how_indx < sizeof(asoc->cookie_how))
1885166023Srrs			asoc->cookie_how[how_indx] = 12;
1886283822Stuexen		sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net,
1887283822Stuexen		    SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
1888283822Stuexen		sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
1889283822Stuexen		    SCTP_FROM_SCTP_INPUT + SCTP_LOC_17);
1890165647Srrs
1891163953Srrs		/* notify upper layer */
1892163953Srrs		*notification = SCTP_NOTIFY_ASSOC_RESTART;
1893165220Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
1894166675Srrs		if ((SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN) &&
1895166675Srrs		    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
1896166675Srrs		    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) {
1897166675Srrs			SCTP_STAT_INCR_GAUGE32(sctps_currestab);
1898166675Srrs		}
1899166675Srrs		if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
1900166675Srrs			SCTP_STAT_INCR_GAUGE32(sctps_restartestab);
1901166675Srrs		} else if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
1902166675Srrs			SCTP_STAT_INCR_GAUGE32(sctps_collisionestab);
1903166675Srrs		}
1904165647Srrs		if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
1905171943Srrs			SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
1906165647Srrs			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1907165647Srrs			    stcb->sctp_ep, stcb, asoc->primary_destination);
1908165647Srrs
1909165647Srrs		} else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) {
1910165647Srrs			/* move to OPEN state, if not in SHUTDOWN_SENT */
1911171943Srrs			SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
1912165647Srrs		}
1913165647Srrs		asoc->pre_open_streams =
1914165647Srrs		    ntohs(initack_cp->init.num_outbound_streams);
1915165647Srrs		asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn);
1916165647Srrs		asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number;
1917179157Srrs		asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
1918165647Srrs
1919165647Srrs		asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
1920165647Srrs
1921165647Srrs		asoc->str_reset_seq_in = asoc->init_seq_number;
1922165647Srrs
1923165647Srrs		asoc->advanced_peer_ack_point = asoc->last_acked_seq;
1924170138Srrs		if (asoc->mapping_array) {
1925165647Srrs			memset(asoc->mapping_array, 0,
1926165647Srrs			    asoc->mapping_array_size);
1927170138Srrs		}
1928205627Srrs		if (asoc->nr_mapping_array) {
1929185694Srrs			memset(asoc->nr_mapping_array, 0,
1930206137Stuexen			    asoc->mapping_array_size);
1931185694Srrs		}
1932165220Srrs		SCTP_TCB_UNLOCK(stcb);
1933252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1934252585Stuexen		so = SCTP_INP_SO(stcb->sctp_ep);
1935252585Stuexen		SCTP_SOCKET_LOCK(so, 1);
1936252585Stuexen#endif
1937165220Srrs		SCTP_INP_INFO_WLOCK();
1938165220Srrs		SCTP_INP_WLOCK(stcb->sctp_ep);
1939165220Srrs		SCTP_TCB_LOCK(stcb);
1940165220Srrs		atomic_add_int(&stcb->asoc.refcnt, -1);
1941163953Srrs		/* send up all the data */
1942164205Srrs		SCTP_TCB_SEND_LOCK(stcb);
1943165220Srrs
1944252585Stuexen		sctp_report_all_outbound(stcb, 0, 1, SCTP_SO_LOCKED);
1945165220Srrs		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
1946243157Stuexen			stcb->asoc.strmout[i].chunks_on_queues = 0;
1947270363Stuexen#if defined(SCTP_DETAILED_STR_STATS)
1948270363Stuexen			for (j = 0; j < SCTP_PR_SCTP_MAX + 1; j++) {
1949270363Stuexen				asoc->strmout[i].abandoned_sent[j] = 0;
1950270363Stuexen				asoc->strmout[i].abandoned_unsent[j] = 0;
1951270363Stuexen			}
1952270363Stuexen#else
1953270363Stuexen			asoc->strmout[i].abandoned_sent[0] = 0;
1954270363Stuexen			asoc->strmout[i].abandoned_unsent[0] = 0;
1955270363Stuexen#endif
1956165220Srrs			stcb->asoc.strmout[i].stream_no = i;
1957242627Stuexen			stcb->asoc.strmout[i].next_sequence_send = 0;
1958165220Srrs			stcb->asoc.strmout[i].last_msg_incomplete = 0;
1959165220Srrs		}
1960163953Srrs		/* process the INIT-ACK info (my info) */
1961163953Srrs		asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
1962163953Srrs		asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
1963163953Srrs
1964163953Srrs		/* pull from vtag hash */
1965163953Srrs		LIST_REMOVE(stcb, sctp_asocs);
1966163953Srrs		/* re-insert to new vtag position */
1967179783Srrs		head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag,
1968179783Srrs		    SCTP_BASE_INFO(hashasocmark))];
1969163953Srrs		/*
1970163953Srrs		 * put it in the bucket in the vtag hash of assoc's for the
1971163953Srrs		 * system
1972163953Srrs		 */
1973163953Srrs		LIST_INSERT_HEAD(head, stcb, sctp_asocs);
1974163953Srrs
1975164205Srrs		SCTP_TCB_SEND_UNLOCK(stcb);
1976165220Srrs		SCTP_INP_WUNLOCK(stcb->sctp_ep);
1977165220Srrs		SCTP_INP_INFO_WUNLOCK();
1978252585Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
1979252585Stuexen		SCTP_SOCKET_UNLOCK(so, 1);
1980252585Stuexen#endif
1981252585Stuexen		asoc->total_flight = 0;
1982252585Stuexen		asoc->total_flight_count = 0;
1983252585Stuexen		/* process the INIT info (peer's info) */
1984228653Stuexen		retval = sctp_process_init(init_cp, stcb);
1985163953Srrs		if (retval < 0) {
1986166023Srrs			if (how_indx < sizeof(asoc->cookie_how))
1987166023Srrs				asoc->cookie_how[how_indx] = 13;
1988166023Srrs
1989163953Srrs			return (NULL);
1990163953Srrs		}
1991163953Srrs		/*
1992163953Srrs		 * since we did not send a HB make sure we don't double
1993163953Srrs		 * things
1994163953Srrs		 */
1995163953Srrs		net->hb_responded = 1;
1996163953Srrs
1997228653Stuexen		if (sctp_load_addresses_from_init(stcb, m,
1998163953Srrs		    init_offset + sizeof(struct sctp_init_chunk),
1999237715Stuexen		    initack_offset, src, dst, init_src)) {
2000166023Srrs			if (how_indx < sizeof(asoc->cookie_how))
2001166023Srrs				asoc->cookie_how[how_indx] = 14;
2002166023Srrs
2003163953Srrs			return (NULL);
2004163953Srrs		}
2005163953Srrs		/* respond with a COOKIE-ACK */
2006163953Srrs		sctp_stop_all_cookie_timers(stcb);
2007165220Srrs		sctp_toss_old_cookies(stcb, asoc);
2008163953Srrs		sctp_send_cookie_ack(stcb);
2009166023Srrs		if (how_indx < sizeof(asoc->cookie_how))
2010166023Srrs			asoc->cookie_how[how_indx] = 15;
2011163953Srrs
2012163953Srrs		return (stcb);
2013163953Srrs	}
2014166023Srrs	if (how_indx < sizeof(asoc->cookie_how))
2015166023Srrs		asoc->cookie_how[how_indx] = 16;
2016163953Srrs	/* all other cases... */
2017163953Srrs	return (NULL);
2018163953Srrs}
2019163953Srrs
2020166086Srrs
2021163953Srrs/*
2022163953Srrs * handle a state cookie for a new association m: input packet mbuf chain--
2023163953Srrs * assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a "split" mbuf
2024163953Srrs * and the cookie signature does not exist offset: offset into mbuf to the
2025163953Srrs * cookie-echo chunk length: length of the cookie chunk to: where the init
2026163953Srrs * was from returns a new TCB
2027163953Srrs */
2028237049Stuexenstatic struct sctp_tcb *
2029163953Srrssctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
2030237715Stuexen    struct sockaddr *src, struct sockaddr *dst,
2031163953Srrs    struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
2032163953Srrs    struct sctp_inpcb *inp, struct sctp_nets **netp,
2033163953Srrs    struct sockaddr *init_src, int *notification,
2034169352Srrs    int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
2035281955Shiren    uint8_t mflowtype, uint32_t mflowid,
2036179157Srrs    uint32_t vrf_id, uint16_t port)
2037163953Srrs{
2038163953Srrs	struct sctp_tcb *stcb;
2039163953Srrs	struct sctp_init_chunk *init_cp, init_buf;
2040163953Srrs	struct sctp_init_ack_chunk *initack_cp, initack_buf;
2041271746Stuexen	union sctp_sockstore store;
2042163953Srrs	struct sctp_association *asoc;
2043163953Srrs	int init_offset, initack_offset, initack_limit;
2044163953Srrs	int retval;
2045163953Srrs	int error = 0;
2046166675Srrs	uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE];
2047163953Srrs
2048237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2049172090Srrs	struct socket *so;
2050172090Srrs
2051172090Srrs	so = SCTP_INP_SO(inp);
2052172090Srrs#endif
2053172090Srrs
2054163953Srrs	/*
2055163953Srrs	 * find and validate the INIT chunk in the cookie (peer's info) the
2056163953Srrs	 * INIT should start after the cookie-echo header struct (chunk
2057163953Srrs	 * header, state cookie header struct)
2058163953Srrs	 */
2059163953Srrs	init_offset = offset + sizeof(struct sctp_cookie_echo_chunk);
2060163953Srrs	init_cp = (struct sctp_init_chunk *)
2061163953Srrs	    sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk),
2062163953Srrs	    (uint8_t *) & init_buf);
2063163953Srrs	if (init_cp == NULL) {
2064163953Srrs		/* could not pull a INIT chunk in cookie */
2065169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT1,
2066169420Srrs		    "process_cookie_new: could not pull INIT chunk hdr\n");
2067163953Srrs		return (NULL);
2068163953Srrs	}
2069163953Srrs	if (init_cp->ch.chunk_type != SCTP_INITIATION) {
2070169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT1, "HUH? process_cookie_new: could not find INIT chunk!\n");
2071163953Srrs		return (NULL);
2072163953Srrs	}
2073228907Stuexen	initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length));
2074163953Srrs	/*
2075163953Srrs	 * find and validate the INIT-ACK chunk in the cookie (my info) the
2076163953Srrs	 * INIT-ACK follows the INIT chunk
2077163953Srrs	 */
2078163953Srrs	initack_cp = (struct sctp_init_ack_chunk *)
2079163953Srrs	    sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk),
2080163953Srrs	    (uint8_t *) & initack_buf);
2081163953Srrs	if (initack_cp == NULL) {
2082163953Srrs		/* could not pull INIT-ACK chunk in cookie */
2083169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: could not pull INIT-ACK chunk hdr\n");
2084163953Srrs		return (NULL);
2085163953Srrs	}
2086163953Srrs	if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) {
2087163953Srrs		return (NULL);
2088163953Srrs	}
2089163953Srrs	/*
2090163953Srrs	 * NOTE: We can't use the INIT_ACK's chk_length to determine the
2091163953Srrs	 * "initack_limit" value.  This is because the chk_length field
2092163953Srrs	 * includes the length of the cookie, but the cookie is omitted when
2093163953Srrs	 * the INIT and INIT_ACK are tacked onto the cookie...
2094163953Srrs	 */
2095163953Srrs	initack_limit = offset + cookie_len;
2096163953Srrs
2097163953Srrs	/*
2098163953Srrs	 * now that we know the INIT/INIT-ACK are in place, create a new TCB
2099163953Srrs	 * and popluate
2100163953Srrs	 */
2101171531Srrs
2102171531Srrs	/*
2103171531Srrs	 * Here we do a trick, we set in NULL for the proc/thread argument.
2104171531Srrs	 * We do this since in effect we only use the p argument when the
2105171531Srrs	 * socket is unbound and we must do an implicit bind. Since we are
2106171531Srrs	 * getting a cookie, we cannot be unbound.
2107171531Srrs	 */
2108206137Stuexen	stcb = sctp_aloc_assoc(inp, init_src, &error,
2109171531Srrs	    ntohl(initack_cp->init.initiate_tag), vrf_id,
2110294215Stuexen	    ntohs(initack_cp->init.num_outbound_streams),
2111171531Srrs	    (struct thread *)NULL
2112171531Srrs	    );
2113163953Srrs	if (stcb == NULL) {
2114163953Srrs		struct mbuf *op_err;
2115163953Srrs
2116163953Srrs		/* memory problem? */
2117169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT1,
2118169420Srrs		    "process_cookie_new: no room for another TCB!\n");
2119267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
2120163953Srrs		sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
2121237715Stuexen		    src, dst, sh, op_err,
2122281955Shiren		    mflowtype, mflowid,
2123237049Stuexen		    vrf_id, port);
2124163953Srrs		return (NULL);
2125163953Srrs	}
2126163953Srrs	/* get the correct sctp_nets */
2127169420Srrs	if (netp)
2128169420Srrs		*netp = sctp_findnet(stcb, init_src);
2129169420Srrs
2130163953Srrs	asoc = &stcb->asoc;
2131163953Srrs	/* get scope variables out of cookie */
2132246595Stuexen	asoc->scope.ipv4_local_scope = cookie->ipv4_scope;
2133246595Stuexen	asoc->scope.site_scope = cookie->site_scope;
2134246595Stuexen	asoc->scope.local_scope = cookie->local_scope;
2135246595Stuexen	asoc->scope.loopback_scope = cookie->loopback_scope;
2136163953Srrs
2137246595Stuexen	if ((asoc->scope.ipv4_addr_legal != cookie->ipv4_addr_legal) ||
2138246595Stuexen	    (asoc->scope.ipv6_addr_legal != cookie->ipv6_addr_legal)) {
2139163953Srrs		struct mbuf *op_err;
2140163953Srrs
2141163953Srrs		/*
2142163953Srrs		 * Houston we have a problem. The EP changed while the
2143163953Srrs		 * cookie was in flight. Only recourse is to abort the
2144163953Srrs		 * association.
2145163953Srrs		 */
2146170140Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
2147267723Stuexen		op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
2148163953Srrs		sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
2149237715Stuexen		    src, dst, sh, op_err,
2150281955Shiren		    mflowtype, mflowid,
2151237049Stuexen		    vrf_id, port);
2152237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2153172090Srrs		SCTP_TCB_UNLOCK(stcb);
2154172090Srrs		SCTP_SOCKET_LOCK(so, 1);
2155172090Srrs		SCTP_TCB_LOCK(stcb);
2156172090Srrs#endif
2157171943Srrs		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
2158283822Stuexen		    SCTP_FROM_SCTP_INPUT + SCTP_LOC_18);
2159237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2160172090Srrs		SCTP_SOCKET_UNLOCK(so, 1);
2161172090Srrs#endif
2162172090Srrs		atomic_subtract_int(&stcb->asoc.refcnt, 1);
2163163953Srrs		return (NULL);
2164163953Srrs	}
2165163953Srrs	/* process the INIT-ACK info (my info) */
2166185694Srrs	asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
2167163953Srrs	asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
2168163953Srrs	asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams);
2169163953Srrs	asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn);
2170163953Srrs	asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number;
2171179157Srrs	asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
2172163953Srrs	asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
2173163953Srrs	asoc->str_reset_seq_in = asoc->init_seq_number;
2174163953Srrs
2175163953Srrs	asoc->advanced_peer_ack_point = asoc->last_acked_seq;
2176163953Srrs
2177163953Srrs	/* process the INIT info (peer's info) */
2178169420Srrs	if (netp)
2179228653Stuexen		retval = sctp_process_init(init_cp, stcb);
2180169420Srrs	else
2181169420Srrs		retval = 0;
2182163953Srrs	if (retval < 0) {
2183170140Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
2184237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2185172090Srrs		SCTP_TCB_UNLOCK(stcb);
2186172090Srrs		SCTP_SOCKET_LOCK(so, 1);
2187172090Srrs		SCTP_TCB_LOCK(stcb);
2188172090Srrs#endif
2189283822Stuexen		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
2190283822Stuexen		    SCTP_FROM_SCTP_INPUT + SCTP_LOC_19);
2191237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2192172090Srrs		SCTP_SOCKET_UNLOCK(so, 1);
2193172090Srrs#endif
2194172090Srrs		atomic_subtract_int(&stcb->asoc.refcnt, 1);
2195163953Srrs		return (NULL);
2196163953Srrs	}
2197163953Srrs	/* load all addresses */
2198228653Stuexen	if (sctp_load_addresses_from_init(stcb, m,
2199237715Stuexen	    init_offset + sizeof(struct sctp_init_chunk), initack_offset,
2200237715Stuexen	    src, dst, init_src)) {
2201170140Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
2202237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2203172090Srrs		SCTP_TCB_UNLOCK(stcb);
2204172090Srrs		SCTP_SOCKET_LOCK(so, 1);
2205172090Srrs		SCTP_TCB_LOCK(stcb);
2206172090Srrs#endif
2207283822Stuexen		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
2208283822Stuexen		    SCTP_FROM_SCTP_INPUT + SCTP_LOC_20);
2209237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2210172090Srrs		SCTP_SOCKET_UNLOCK(so, 1);
2211172090Srrs#endif
2212172090Srrs		atomic_subtract_int(&stcb->asoc.refcnt, 1);
2213163953Srrs		return (NULL);
2214163953Srrs	}
2215163953Srrs	/*
2216163953Srrs	 * verify any preceding AUTH chunk that was skipped
2217163953Srrs	 */
2218163953Srrs	/* pull the local authentication parameters from the cookie/init-ack */
2219163953Srrs	sctp_auth_get_cookie_params(stcb, m,
2220163953Srrs	    initack_offset + sizeof(struct sctp_init_ack_chunk),
2221163953Srrs	    initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)));
2222163953Srrs	if (auth_skipped) {
2223163953Srrs		struct sctp_auth_chunk *auth;
2224163953Srrs
2225163953Srrs		auth = (struct sctp_auth_chunk *)
2226166675Srrs		    sctp_m_getptr(m, auth_offset, auth_len, auth_chunk_buf);
2227169420Srrs		if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, auth_offset)) {
2228163953Srrs			/* auth HMAC failed, dump the assoc and packet */
2229169420Srrs			SCTPDBG(SCTP_DEBUG_AUTH1,
2230169420Srrs			    "COOKIE-ECHO: AUTH failed\n");
2231171440Srrs			atomic_add_int(&stcb->asoc.refcnt, 1);
2232237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2233172090Srrs			SCTP_TCB_UNLOCK(stcb);
2234172090Srrs			SCTP_SOCKET_LOCK(so, 1);
2235172090Srrs			SCTP_TCB_LOCK(stcb);
2236172090Srrs#endif
2237283822Stuexen			(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
2238283822Stuexen			    SCTP_FROM_SCTP_INPUT + SCTP_LOC_21);
2239237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2240172090Srrs			SCTP_SOCKET_UNLOCK(so, 1);
2241172090Srrs#endif
2242172090Srrs			atomic_subtract_int(&stcb->asoc.refcnt, 1);
2243163953Srrs			return (NULL);
2244163953Srrs		} else {
2245163953Srrs			/* remaining chunks checked... good to go */
2246163953Srrs			stcb->asoc.authenticated = 1;
2247163953Srrs		}
2248163953Srrs	}
2249163953Srrs	/* update current state */
2250169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
2251171943Srrs	SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
2252163953Srrs	if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
2253163953Srrs		sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
2254163953Srrs		    stcb->sctp_ep, stcb, asoc->primary_destination);
2255163953Srrs	}
2256165220Srrs	sctp_stop_all_cookie_timers(stcb);
2257163953Srrs	SCTP_STAT_INCR_COUNTER32(sctps_passiveestab);
2258163953Srrs	SCTP_STAT_INCR_GAUGE32(sctps_currestab);
2259163953Srrs
2260163953Srrs	/*
2261163953Srrs	 * if we're doing ASCONFs, check to see if we have any new local
2262163953Srrs	 * addresses that need to get added to the peer (eg. addresses
2263163953Srrs	 * changed while cookie echo in flight).  This needs to be done
2264163953Srrs	 * after we go to the OPEN state to do the correct asconf
2265163953Srrs	 * processing. else, make sure we have the correct addresses in our
2266163953Srrs	 * lists
2267163953Srrs	 */
2268163953Srrs
2269163953Srrs	/* warning, we re-use sin, sin6, sa_store here! */
2270163953Srrs	/* pull in local_address (our "from" address) */
2271221249Stuexen	switch (cookie->laddr_type) {
2272221249Stuexen#ifdef INET
2273221249Stuexen	case SCTP_IPV4_ADDRESS:
2274163953Srrs		/* source addr is IPv4 */
2275271746Stuexen		memset(&store.sin, 0, sizeof(struct sockaddr_in));
2276271746Stuexen		store.sin.sin_family = AF_INET;
2277271746Stuexen		store.sin.sin_len = sizeof(struct sockaddr_in);
2278271746Stuexen		store.sin.sin_addr.s_addr = cookie->laddress[0];
2279221249Stuexen		break;
2280221249Stuexen#endif
2281221249Stuexen#ifdef INET6
2282221249Stuexen	case SCTP_IPV6_ADDRESS:
2283163953Srrs		/* source addr is IPv6 */
2284271746Stuexen		memset(&store.sin6, 0, sizeof(struct sockaddr_in6));
2285271746Stuexen		store.sin6.sin6_family = AF_INET6;
2286271746Stuexen		store.sin6.sin6_len = sizeof(struct sockaddr_in6);
2287271746Stuexen		store.sin6.sin6_scope_id = cookie->scope_id;
2288271746Stuexen		memcpy(&store.sin6.sin6_addr, cookie->laddress, sizeof(struct in6_addr));
2289221249Stuexen		break;
2290221249Stuexen#endif
2291221249Stuexen	default:
2292170140Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
2293237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2294172090Srrs		SCTP_TCB_UNLOCK(stcb);
2295172090Srrs		SCTP_SOCKET_LOCK(so, 1);
2296172090Srrs		SCTP_TCB_LOCK(stcb);
2297172090Srrs#endif
2298283822Stuexen		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
2299283822Stuexen		    SCTP_FROM_SCTP_INPUT + SCTP_LOC_22);
2300237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2301172090Srrs		SCTP_SOCKET_UNLOCK(so, 1);
2302172090Srrs#endif
2303172090Srrs		atomic_subtract_int(&stcb->asoc.refcnt, 1);
2304163953Srrs		return (NULL);
2305163953Srrs	}
2306163953Srrs
2307163953Srrs	/* set up to notify upper layer */
2308163953Srrs	*notification = SCTP_NOTIFY_ASSOC_UP;
2309163953Srrs	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2310163953Srrs	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
2311163953Srrs	    (inp->sctp_socket->so_qlimit == 0)) {
2312163953Srrs		/*
2313163953Srrs		 * This is an endpoint that called connect() how it got a
2314163953Srrs		 * cookie that is NEW is a bit of a mystery. It must be that
2315163953Srrs		 * the INIT was sent, but before it got there.. a complete
2316163953Srrs		 * INIT/INIT-ACK/COOKIE arrived. But of course then it
2317163953Srrs		 * should have went to the other code.. not here.. oh well..
2318163953Srrs		 * a bit of protection is worth having..
2319163953Srrs		 */
2320163953Srrs		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
2321237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2322172090Srrs		atomic_add_int(&stcb->asoc.refcnt, 1);
2323172090Srrs		SCTP_TCB_UNLOCK(stcb);
2324172090Srrs		SCTP_SOCKET_LOCK(so, 1);
2325172090Srrs		SCTP_TCB_LOCK(stcb);
2326172090Srrs		atomic_subtract_int(&stcb->asoc.refcnt, 1);
2327172090Srrs		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
2328172090Srrs			SCTP_SOCKET_UNLOCK(so, 1);
2329172090Srrs			return (NULL);
2330172090Srrs		}
2331172090Srrs#endif
2332172090Srrs		soisconnected(stcb->sctp_socket);
2333237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2334172090Srrs		SCTP_SOCKET_UNLOCK(so, 1);
2335172090Srrs#endif
2336163953Srrs	} else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
2337163953Srrs	    (inp->sctp_socket->so_qlimit)) {
2338163953Srrs		/*
2339163953Srrs		 * We don't want to do anything with this one. Since it is
2340163953Srrs		 * the listening guy. The timer will get started for
2341163953Srrs		 * accepted connections in the caller.
2342163953Srrs		 */
2343163953Srrs		;
2344163953Srrs	}
2345163953Srrs	/* since we did not send a HB make sure we don't double things */
2346169420Srrs	if ((netp) && (*netp))
2347169420Srrs		(*netp)->hb_responded = 1;
2348163953Srrs
2349163953Srrs	if (stcb->asoc.sctp_autoclose_ticks &&
2350163953Srrs	    sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) {
2351163953Srrs		sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL);
2352163953Srrs	}
2353171440Srrs	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
2354294208Stuexen	if ((netp != NULL) && (*netp != NULL)) {
2355283741Stuexen		/* calculate the RTT and set the encaps port */
2356169420Srrs		(*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp,
2357218186Srrs		    &cookie->time_entered, sctp_align_unsafe_makecopy,
2358219397Srrs		    SCTP_RTT_FROM_NON_DATA);
2359294208Stuexen#if defined(INET) || defined(INET6)
2360294208Stuexen		if (((*netp)->port == 0) && (port != 0)) {
2361294208Stuexen			sctp_pathmtu_adjustment(stcb, (*netp)->mtu - sizeof(struct udphdr));
2362294208Stuexen		}
2363283741Stuexen		(*netp)->port = port;
2364294208Stuexen#endif
2365170642Srrs	}
2366172190Srrs	/* respond with a COOKIE-ACK */
2367163953Srrs	sctp_send_cookie_ack(stcb);
2368172190Srrs
2369172190Srrs	/*
2370172190Srrs	 * check the address lists for any ASCONFs that need to be sent
2371172190Srrs	 * AFTER the cookie-ack is sent
2372172190Srrs	 */
2373172190Srrs	sctp_check_address_list(stcb, m,
2374172190Srrs	    initack_offset + sizeof(struct sctp_init_ack_chunk),
2375172190Srrs	    initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)),
2376271746Stuexen	    &store.sa, cookie->local_scope, cookie->site_scope,
2377172190Srrs	    cookie->ipv4_scope, cookie->loopback_scope);
2378172190Srrs
2379172190Srrs
2380163953Srrs	return (stcb);
2381163953Srrs}
2382163953Srrs
2383185694Srrs/*
2384185694Srrs * CODE LIKE THIS NEEDS TO RUN IF the peer supports the NAT extension, i.e
2385185694Srrs * we NEED to make sure we are not already using the vtag. If so we
2386185694Srrs * need to send back an ABORT-TRY-AGAIN-WITH-NEW-TAG No middle box bit!
2387185694Srrs	head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag,
2388185694Srrs							    SCTP_BASE_INFO(hashasocmark))];
2389185694Srrs	LIST_FOREACH(stcb, head, sctp_asocs) {
2390185694Srrs	        if ((stcb->asoc.my_vtag == tag) && (stcb->rport == rport) && (inp == stcb->sctp_ep))  {
2391185694Srrs		       -- SEND ABORT - TRY AGAIN --
2392185694Srrs		}
2393185694Srrs	}
2394185694Srrs*/
2395163953Srrs
2396163953Srrs/*
2397163953Srrs * handles a COOKIE-ECHO message stcb: modified to either a new or left as
2398163953Srrs * existing (non-NULL) TCB
2399163953Srrs */
2400163953Srrsstatic struct mbuf *
2401163953Srrssctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
2402237715Stuexen    struct sockaddr *src, struct sockaddr *dst,
2403163953Srrs    struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp,
2404163953Srrs    struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp,
2405169352Srrs    int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
2406237049Stuexen    struct sctp_tcb **locked_tcb,
2407281955Shiren    uint8_t mflowtype, uint32_t mflowid,
2408237049Stuexen    uint32_t vrf_id, uint16_t port)
2409163953Srrs{
2410163953Srrs	struct sctp_state_cookie *cookie;
2411163953Srrs	struct sctp_tcb *l_stcb = *stcb;
2412163953Srrs	struct sctp_inpcb *l_inp;
2413163953Srrs	struct sockaddr *to;
2414163953Srrs	struct sctp_pcb *ep;
2415163953Srrs	struct mbuf *m_sig;
2416163953Srrs	uint8_t calc_sig[SCTP_SIGNATURE_SIZE], tmp_sig[SCTP_SIGNATURE_SIZE];
2417163953Srrs	uint8_t *sig;
2418163953Srrs	uint8_t cookie_ok = 0;
2419237541Stuexen	unsigned int sig_offset, cookie_offset;
2420163953Srrs	unsigned int cookie_len;
2421163953Srrs	struct timeval now;
2422163953Srrs	struct timeval time_expires;
2423163953Srrs	int notification = 0;
2424163953Srrs	struct sctp_nets *netl;
2425163953Srrs	int had_a_existing_tcb = 0;
2426216887Stuexen	int send_int_conf = 0;
2427163953Srrs
2428221249Stuexen#ifdef INET
2429221249Stuexen	struct sockaddr_in sin;
2430221249Stuexen
2431221249Stuexen#endif
2432221249Stuexen#ifdef INET6
2433221249Stuexen	struct sockaddr_in6 sin6;
2434221249Stuexen
2435221249Stuexen#endif
2436221249Stuexen
2437169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT2,
2438169420Srrs	    "sctp_handle_cookie: handling COOKIE-ECHO\n");
2439163953Srrs
2440163953Srrs	if (inp_p == NULL) {
2441163953Srrs		return (NULL);
2442163953Srrs	}
2443163953Srrs	cookie = &cp->cookie;
2444163953Srrs	cookie_offset = offset + sizeof(struct sctp_chunkhdr);
2445163953Srrs	cookie_len = ntohs(cp->ch.chunk_length);
2446163953Srrs
2447294176Stuexen	if ((cookie->peerport != sh->src_port) ||
2448294176Stuexen	    (cookie->myport != sh->dest_port) ||
2449163953Srrs	    (cookie->my_vtag != sh->v_tag)) {
2450163953Srrs		/*
2451163953Srrs		 * invalid ports or bad tag.  Note that we always leave the
2452163953Srrs		 * v_tag in the header in network order and when we stored
2453163953Srrs		 * it in the my_vtag slot we also left it in network order.
2454169352Srrs		 * This maintains the match even though it may be in the
2455163953Srrs		 * opposite byte order of the machine :->
2456163953Srrs		 */
2457163953Srrs		return (NULL);
2458163953Srrs	}
2459237541Stuexen	if (cookie_len < sizeof(struct sctp_cookie_echo_chunk) +
2460163953Srrs	    sizeof(struct sctp_init_chunk) +
2461163953Srrs	    sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) {
2462237541Stuexen		/* cookie too small */
2463163953Srrs		return (NULL);
2464163953Srrs	}
2465163953Srrs	/*
2466163953Srrs	 * split off the signature into its own mbuf (since it should not be
2467163953Srrs	 * calculated in the sctp_hmac_m() call).
2468163953Srrs	 */
2469163953Srrs	sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE;
2470243882Sglebius	m_sig = m_split(m, sig_offset, M_NOWAIT);
2471163953Srrs	if (m_sig == NULL) {
2472163953Srrs		/* out of memory or ?? */
2473163953Srrs		return (NULL);
2474163953Srrs	}
2475178202Srrs#ifdef SCTP_MBUF_LOGGING
2476179783Srrs	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
2477283708Stuexen		sctp_log_mbc(m_sig, SCTP_MBUF_SPLIT);
2478178202Srrs	}
2479178202Srrs#endif
2480178202Srrs
2481163953Srrs	/*
2482163953Srrs	 * compute the signature/digest for the cookie
2483163953Srrs	 */
2484163953Srrs	ep = &(*inp_p)->sctp_ep;
2485163953Srrs	l_inp = *inp_p;
2486163953Srrs	if (l_stcb) {
2487163953Srrs		SCTP_TCB_UNLOCK(l_stcb);
2488163953Srrs	}
2489163953Srrs	SCTP_INP_RLOCK(l_inp);
2490163953Srrs	if (l_stcb) {
2491163953Srrs		SCTP_TCB_LOCK(l_stcb);
2492163953Srrs	}
2493163953Srrs	/* which cookie is it? */
2494163953Srrs	if ((cookie->time_entered.tv_sec < (long)ep->time_of_secret_change) &&
2495163953Srrs	    (ep->current_secret_number != ep->last_secret_number)) {
2496163953Srrs		/* it's the old cookie */
2497169378Srrs		(void)sctp_hmac_m(SCTP_HMAC,
2498163953Srrs		    (uint8_t *) ep->secret_key[(int)ep->last_secret_number],
2499170462Srrs		    SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0);
2500163953Srrs	} else {
2501163953Srrs		/* it's the current cookie */
2502169378Srrs		(void)sctp_hmac_m(SCTP_HMAC,
2503163953Srrs		    (uint8_t *) ep->secret_key[(int)ep->current_secret_number],
2504170462Srrs		    SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0);
2505163953Srrs	}
2506163953Srrs	/* get the signature */
2507163953Srrs	SCTP_INP_RUNLOCK(l_inp);
2508163953Srrs	sig = (uint8_t *) sctp_m_getptr(m_sig, 0, SCTP_SIGNATURE_SIZE, (uint8_t *) & tmp_sig);
2509163953Srrs	if (sig == NULL) {
2510163953Srrs		/* couldn't find signature */
2511164085Srrs		sctp_m_freem(m_sig);
2512163953Srrs		return (NULL);
2513163953Srrs	}
2514163953Srrs	/* compare the received digest with the computed digest */
2515163953Srrs	if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) != 0) {
2516163953Srrs		/* try the old cookie? */
2517163953Srrs		if ((cookie->time_entered.tv_sec == (long)ep->time_of_secret_change) &&
2518163953Srrs		    (ep->current_secret_number != ep->last_secret_number)) {
2519163953Srrs			/* compute digest with old */
2520169378Srrs			(void)sctp_hmac_m(SCTP_HMAC,
2521163953Srrs			    (uint8_t *) ep->secret_key[(int)ep->last_secret_number],
2522170462Srrs			    SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0);
2523163953Srrs			/* compare */
2524163953Srrs			if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) == 0)
2525163953Srrs				cookie_ok = 1;
2526163953Srrs		}
2527163953Srrs	} else {
2528163953Srrs		cookie_ok = 1;
2529163953Srrs	}
2530163953Srrs
2531163953Srrs	/*
2532163953Srrs	 * Now before we continue we must reconstruct our mbuf so that
2533163953Srrs	 * normal processing of any other chunks will work.
2534163953Srrs	 */
2535163953Srrs	{
2536163953Srrs		struct mbuf *m_at;
2537163953Srrs
2538163953Srrs		m_at = m;
2539165647Srrs		while (SCTP_BUF_NEXT(m_at) != NULL) {
2540165647Srrs			m_at = SCTP_BUF_NEXT(m_at);
2541163953Srrs		}
2542165647Srrs		SCTP_BUF_NEXT(m_at) = m_sig;
2543163953Srrs	}
2544163953Srrs
2545163953Srrs	if (cookie_ok == 0) {
2546169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT2, "handle_cookie_echo: cookie signature validation failed!\n");
2547169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT2,
2548169420Srrs		    "offset = %u, cookie_offset = %u, sig_offset = %u\n",
2549169420Srrs		    (uint32_t) offset, cookie_offset, sig_offset);
2550163953Srrs		return (NULL);
2551163953Srrs	}
2552163953Srrs	/*
2553163953Srrs	 * check the cookie timestamps to be sure it's not stale
2554163953Srrs	 */
2555169378Srrs	(void)SCTP_GETTIME_TIMEVAL(&now);
2556163953Srrs	/* Expire time is in Ticks, so we convert to seconds */
2557169655Srrs	time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life);
2558163953Srrs	time_expires.tv_usec = cookie->time_entered.tv_usec;
2559180387Srrs	/*
2560180387Srrs	 * TODO sctp_constants.h needs alternative time macros when _KERNEL
2561180387Srrs	 * is undefined.
2562180387Srrs	 */
2563163953Srrs	if (timevalcmp(&now, &time_expires, >)) {
2564163953Srrs		/* cookie is stale! */
2565163953Srrs		struct mbuf *op_err;
2566294158Stuexen		struct sctp_error_stale_cookie *cause;
2567163953Srrs		uint32_t tim;
2568163953Srrs
2569294158Stuexen		op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_stale_cookie),
2570243882Sglebius		    0, M_NOWAIT, 1, MT_DATA);
2571163953Srrs		if (op_err == NULL) {
2572163953Srrs			/* FOOBAR */
2573163953Srrs			return (NULL);
2574163953Srrs		}
2575163953Srrs		/* Set the len */
2576294158Stuexen		SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_stale_cookie);
2577294158Stuexen		cause = mtod(op_err, struct sctp_error_stale_cookie *);
2578294158Stuexen		cause->cause.code = htons(SCTP_CAUSE_STALE_COOKIE);
2579294158Stuexen		cause->cause.length = htons((sizeof(struct sctp_paramhdr) +
2580163953Srrs		    (sizeof(uint32_t))));
2581163953Srrs		/* seconds to usec */
2582163953Srrs		tim = (now.tv_sec - time_expires.tv_sec) * 1000000;
2583163953Srrs		/* add in usec */
2584163953Srrs		if (tim == 0)
2585163953Srrs			tim = now.tv_usec - cookie->time_entered.tv_usec;
2586294158Stuexen		cause->stale_time = htonl(tim);
2587237715Stuexen		sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err,
2588284633Stuexen		    mflowtype, mflowid, l_inp->fibnum,
2589179157Srrs		    vrf_id, port);
2590163953Srrs		return (NULL);
2591163953Srrs	}
2592163953Srrs	/*
2593163953Srrs	 * Now we must see with the lookup address if we have an existing
2594163953Srrs	 * asoc. This will only happen if we were in the COOKIE-WAIT state
2595163953Srrs	 * and a INIT collided with us and somewhere the peer sent the
2596163953Srrs	 * cookie on another address besides the single address our assoc
2597163953Srrs	 * had for him. In this case we will have one of the tie-tags set at
2598163953Srrs	 * least AND the address field in the cookie can be used to look it
2599163953Srrs	 * up.
2600163953Srrs	 */
2601163953Srrs	to = NULL;
2602221249Stuexen	switch (cookie->addr_type) {
2603221249Stuexen#ifdef INET6
2604221249Stuexen	case SCTP_IPV6_ADDRESS:
2605163953Srrs		memset(&sin6, 0, sizeof(sin6));
2606163953Srrs		sin6.sin6_family = AF_INET6;
2607163953Srrs		sin6.sin6_len = sizeof(sin6);
2608163953Srrs		sin6.sin6_port = sh->src_port;
2609163953Srrs		sin6.sin6_scope_id = cookie->scope_id;
2610163953Srrs		memcpy(&sin6.sin6_addr.s6_addr, cookie->address,
2611163953Srrs		    sizeof(sin6.sin6_addr.s6_addr));
2612163953Srrs		to = (struct sockaddr *)&sin6;
2613221249Stuexen		break;
2614221249Stuexen#endif
2615221249Stuexen#ifdef INET
2616221249Stuexen	case SCTP_IPV4_ADDRESS:
2617163953Srrs		memset(&sin, 0, sizeof(sin));
2618163953Srrs		sin.sin_family = AF_INET;
2619163953Srrs		sin.sin_len = sizeof(sin);
2620163953Srrs		sin.sin_port = sh->src_port;
2621163953Srrs		sin.sin_addr.s_addr = cookie->address[0];
2622163953Srrs		to = (struct sockaddr *)&sin;
2623221249Stuexen		break;
2624221249Stuexen#endif
2625221249Stuexen	default:
2626169420Srrs		/* This should not happen */
2627169420Srrs		return (NULL);
2628163953Srrs	}
2629283712Stuexen	if (*stcb == NULL) {
2630163953Srrs		/* Yep, lets check */
2631237715Stuexen		*stcb = sctp_findassociation_ep_addr(inp_p, to, netp, dst, NULL);
2632163953Srrs		if (*stcb == NULL) {
2633163953Srrs			/*
2634163953Srrs			 * We should have only got back the same inp. If we
2635163953Srrs			 * got back a different ep we have a problem. The
2636163953Srrs			 * original findep got back l_inp and now
2637163953Srrs			 */
2638163953Srrs			if (l_inp != *inp_p) {
2639169420Srrs				SCTP_PRINTF("Bad problem find_ep got a diff inp then special_locate?\n");
2640163953Srrs			}
2641165220Srrs		} else {
2642165220Srrs			if (*locked_tcb == NULL) {
2643165220Srrs				/*
2644165220Srrs				 * In this case we found the assoc only
2645165220Srrs				 * after we locked the create lock. This
2646165220Srrs				 * means we are in a colliding case and we
2647165220Srrs				 * must make sure that we unlock the tcb if
2648165220Srrs				 * its one of the cases where we throw away
2649165220Srrs				 * the incoming packets.
2650165220Srrs				 */
2651165220Srrs				*locked_tcb = *stcb;
2652165220Srrs
2653165220Srrs				/*
2654165220Srrs				 * We must also increment the inp ref count
2655165220Srrs				 * since the ref_count flags was set when we
2656165220Srrs				 * did not find the TCB, now we found it
2657165220Srrs				 * which reduces the refcount.. we must
2658165220Srrs				 * raise it back out to balance it all :-)
2659165220Srrs				 */
2660165220Srrs				SCTP_INP_INCR_REF((*stcb)->sctp_ep);
2661165220Srrs				if ((*stcb)->sctp_ep != l_inp) {
2662169420Srrs					SCTP_PRINTF("Huh? ep:%p diff then l_inp:%p?\n",
2663240148Stuexen					    (void *)(*stcb)->sctp_ep, (void *)l_inp);
2664165220Srrs				}
2665165220Srrs			}
2666163953Srrs		}
2667163953Srrs	}
2668163953Srrs	cookie_len -= SCTP_SIGNATURE_SIZE;
2669163953Srrs	if (*stcb == NULL) {
2670163953Srrs		/* this is the "normal" case... get a new TCB */
2671237715Stuexen		*stcb = sctp_process_cookie_new(m, iphlen, offset, src, dst, sh,
2672237715Stuexen		    cookie, cookie_len, *inp_p,
2673237715Stuexen		    netp, to, &notification,
2674237049Stuexen		    auth_skipped, auth_offset, auth_len,
2675281955Shiren		    mflowtype, mflowid,
2676237049Stuexen		    vrf_id, port);
2677163953Srrs	} else {
2678163953Srrs		/* this is abnormal... cookie-echo on existing TCB */
2679163953Srrs		had_a_existing_tcb = 1;
2680237715Stuexen		*stcb = sctp_process_cookie_existing(m, iphlen, offset,
2681237715Stuexen		    src, dst, sh,
2682185694Srrs		    cookie, cookie_len, *inp_p, *stcb, netp, to,
2683237049Stuexen		    &notification, auth_skipped, auth_offset, auth_len,
2684281955Shiren		    mflowtype, mflowid,
2685237049Stuexen		    vrf_id, port);
2686163953Srrs	}
2687163953Srrs
2688163953Srrs	if (*stcb == NULL) {
2689163953Srrs		/* still no TCB... must be bad cookie-echo */
2690163953Srrs		return (NULL);
2691163953Srrs	}
2692284634Stuexen	if (*netp != NULL) {
2693281955Shiren		(*netp)->flowtype = mflowtype;
2694284634Stuexen		(*netp)->flowid = mflowid;
2695218335Stuexen	}
2696163953Srrs	/*
2697163953Srrs	 * Ok, we built an association so confirm the address we sent the
2698163953Srrs	 * INIT-ACK to.
2699163953Srrs	 */
2700163953Srrs	netl = sctp_findnet(*stcb, to);
2701163953Srrs	/*
2702163953Srrs	 * This code should in theory NOT run but
2703163953Srrs	 */
2704163953Srrs	if (netl == NULL) {
2705163953Srrs		/* TSNH! Huh, why do I need to add this address here? */
2706228907Stuexen		if (sctp_add_remote_addr(*stcb, to, NULL, SCTP_DONOT_SETSCOPE, SCTP_IN_COOKIE_PROC)) {
2707228907Stuexen			return (NULL);
2708228907Stuexen		}
2709163953Srrs		netl = sctp_findnet(*stcb, to);
2710163953Srrs	}
2711163953Srrs	if (netl) {
2712163953Srrs		if (netl->dest_state & SCTP_ADDR_UNCONFIRMED) {
2713163953Srrs			netl->dest_state &= ~SCTP_ADDR_UNCONFIRMED;
2714169420Srrs			(void)sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL,
2715163953Srrs			    netl);
2716216887Stuexen			send_int_conf = 1;
2717163953Srrs		}
2718163953Srrs	}
2719224641Stuexen	sctp_start_net_timers(*stcb);
2720163953Srrs	if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
2721163953Srrs		if (!had_a_existing_tcb ||
2722163953Srrs		    (((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
2723163953Srrs			/*
2724163953Srrs			 * If we have a NEW cookie or the connect never
2725163953Srrs			 * reached the connected state during collision we
2726163953Srrs			 * must do the TCP accept thing.
2727163953Srrs			 */
2728163953Srrs			struct socket *so, *oso;
2729163953Srrs			struct sctp_inpcb *inp;
2730163953Srrs
2731163953Srrs			if (notification == SCTP_NOTIFY_ASSOC_RESTART) {
2732163953Srrs				/*
2733163953Srrs				 * For a restart we will keep the same
2734163953Srrs				 * socket, no need to do anything. I THINK!!
2735163953Srrs				 */
2736228653Stuexen				sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
2737216887Stuexen				if (send_int_conf) {
2738216887Stuexen					sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
2739216887Stuexen					    (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
2740216887Stuexen				}
2741163953Srrs				return (m);
2742163953Srrs			}
2743163953Srrs			oso = (*inp_p)->sctp_socket;
2744171858Srrs			atomic_add_int(&(*stcb)->asoc.refcnt, 1);
2745163953Srrs			SCTP_TCB_UNLOCK((*stcb));
2746218757Sbz			CURVNET_SET(oso->so_vnet);
2747166086Srrs			so = sonewconn(oso, 0
2748163953Srrs			    );
2749218757Sbz			CURVNET_RESTORE();
2750163953Srrs			SCTP_TCB_LOCK((*stcb));
2751171858Srrs			atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
2752171858Srrs
2753163953Srrs			if (so == NULL) {
2754163953Srrs				struct mbuf *op_err;
2755163953Srrs
2756237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2757172090Srrs				struct socket *pcb_so;
2758172090Srrs
2759172090Srrs#endif
2760163953Srrs				/* Too many sockets */
2761169420Srrs				SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n");
2762267723Stuexen				op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
2763163953Srrs				sctp_abort_association(*inp_p, NULL, m, iphlen,
2764237715Stuexen				    src, dst, sh, op_err,
2765281955Shiren				    mflowtype, mflowid,
2766237049Stuexen				    vrf_id, port);
2767237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2768172090Srrs				pcb_so = SCTP_INP_SO(*inp_p);
2769172090Srrs				atomic_add_int(&(*stcb)->asoc.refcnt, 1);
2770172090Srrs				SCTP_TCB_UNLOCK((*stcb));
2771172090Srrs				SCTP_SOCKET_LOCK(pcb_so, 1);
2772172090Srrs				SCTP_TCB_LOCK((*stcb));
2773172090Srrs				atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
2774172090Srrs#endif
2775283822Stuexen				(void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC,
2776283822Stuexen				    SCTP_FROM_SCTP_INPUT + SCTP_LOC_23);
2777237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2778172090Srrs				SCTP_SOCKET_UNLOCK(pcb_so, 1);
2779172090Srrs#endif
2780163953Srrs				return (NULL);
2781163953Srrs			}
2782163953Srrs			inp = (struct sctp_inpcb *)so->so_pcb;
2783166086Srrs			SCTP_INP_INCR_REF(inp);
2784166086Srrs			/*
2785166086Srrs			 * We add the unbound flag here so that if we get an
2786166086Srrs			 * soabort() before we get the move_pcb done, we
2787166086Srrs			 * will properly cleanup.
2788166086Srrs			 */
2789163953Srrs			inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE |
2790163953Srrs			    SCTP_PCB_FLAGS_CONNECTED |
2791163953Srrs			    SCTP_PCB_FLAGS_IN_TCPPOOL |
2792166086Srrs			    SCTP_PCB_FLAGS_UNBOUND |
2793163953Srrs			    (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) |
2794163953Srrs			    SCTP_PCB_FLAGS_DONT_WAKE);
2795163953Srrs			inp->sctp_features = (*inp_p)->sctp_features;
2796172091Srrs			inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features;
2797163953Srrs			inp->sctp_socket = so;
2798163953Srrs			inp->sctp_frag_point = (*inp_p)->sctp_frag_point;
2799283724Stuexen			inp->max_cwnd = (*inp_p)->max_cwnd;
2800211944Stuexen			inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off;
2801270356Stuexen			inp->ecn_supported = (*inp_p)->ecn_supported;
2802270357Stuexen			inp->prsctp_supported = (*inp_p)->prsctp_supported;
2803270362Stuexen			inp->auth_supported = (*inp_p)->auth_supported;
2804270362Stuexen			inp->asconf_supported = (*inp_p)->asconf_supported;
2805270361Stuexen			inp->reconfig_supported = (*inp_p)->reconfig_supported;
2806270359Stuexen			inp->nrsack_supported = (*inp_p)->nrsack_supported;
2807270360Stuexen			inp->pktdrop_supported = (*inp_p)->pktdrop_supported;
2808163953Srrs			inp->partial_delivery_point = (*inp_p)->partial_delivery_point;
2809163953Srrs			inp->sctp_context = (*inp_p)->sctp_context;
2810233660Srrs			inp->local_strreset_support = (*inp_p)->local_strreset_support;
2811284633Stuexen			inp->fibnum = (*inp_p)->fibnum;
2812163953Srrs			inp->inp_starting_point_for_iterator = NULL;
2813163953Srrs			/*
2814163953Srrs			 * copy in the authentication parameters from the
2815163953Srrs			 * original endpoint
2816163953Srrs			 */
2817163953Srrs			if (inp->sctp_ep.local_hmacs)
2818163953Srrs				sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
2819163953Srrs			inp->sctp_ep.local_hmacs =
2820163953Srrs			    sctp_copy_hmaclist((*inp_p)->sctp_ep.local_hmacs);
2821163953Srrs			if (inp->sctp_ep.local_auth_chunks)
2822163953Srrs				sctp_free_chunklist(inp->sctp_ep.local_auth_chunks);
2823163953Srrs			inp->sctp_ep.local_auth_chunks =
2824163953Srrs			    sctp_copy_chunklist((*inp_p)->sctp_ep.local_auth_chunks);
2825163953Srrs
2826163953Srrs			/*
2827163953Srrs			 * Now we must move it from one hash table to
2828163953Srrs			 * another and get the tcb in the right place.
2829163953Srrs			 */
2830207924Srrs
2831207924Srrs			/*
2832207924Srrs			 * This is where the one-2-one socket is put into
2833207924Srrs			 * the accept state waiting for the accept!
2834207924Srrs			 */
2835207924Srrs			if (*stcb) {
2836207924Srrs				(*stcb)->asoc.state |= SCTP_STATE_IN_ACCEPT_QUEUE;
2837207924Srrs			}
2838163953Srrs			sctp_move_pcb_and_assoc(*inp_p, inp, *stcb);
2839170056Srrs
2840170056Srrs			atomic_add_int(&(*stcb)->asoc.refcnt, 1);
2841170056Srrs			SCTP_TCB_UNLOCK((*stcb));
2842170056Srrs
2843175845Srwatson			sctp_pull_off_control_to_new_inp((*inp_p), inp, *stcb,
2844175845Srwatson			    0);
2845170056Srrs			SCTP_TCB_LOCK((*stcb));
2846170056Srrs			atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
2847163953Srrs
2848170056Srrs
2849166086Srrs			/*
2850166086Srrs			 * now we must check to see if we were aborted while
2851166086Srrs			 * the move was going on and the lock/unlock
2852166086Srrs			 * happened.
2853166086Srrs			 */
2854166086Srrs			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
2855166086Srrs				/*
2856166086Srrs				 * yep it was, we leave the assoc attached
2857166086Srrs				 * to the socket since the sctp_inpcb_free()
2858166086Srrs				 * call will send an abort for us.
2859166086Srrs				 */
2860166086Srrs				SCTP_INP_DECR_REF(inp);
2861166086Srrs				return (NULL);
2862166086Srrs			}
2863166086Srrs			SCTP_INP_DECR_REF(inp);
2864163953Srrs			/* Switch over to the new guy */
2865163953Srrs			*inp_p = inp;
2866172090Srrs			sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
2867216887Stuexen			if (send_int_conf) {
2868216887Stuexen				sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
2869216887Stuexen				    (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
2870216887Stuexen			}
2871166086Srrs			/*
2872166086Srrs			 * Pull it from the incomplete queue and wake the
2873166086Srrs			 * guy
2874166086Srrs			 */
2875237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2876172090Srrs			atomic_add_int(&(*stcb)->asoc.refcnt, 1);
2877172090Srrs			SCTP_TCB_UNLOCK((*stcb));
2878172090Srrs			SCTP_SOCKET_LOCK(so, 1);
2879172090Srrs#endif
2880166086Srrs			soisconnected(so);
2881237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2882172118Srrs			SCTP_TCB_LOCK((*stcb));
2883172118Srrs			atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
2884172090Srrs			SCTP_SOCKET_UNLOCK(so, 1);
2885172090Srrs#endif
2886163953Srrs			return (m);
2887163953Srrs		}
2888163953Srrs	}
2889238454Stuexen	if (notification) {
2890238454Stuexen		sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
2891163953Srrs	}
2892238454Stuexen	if (send_int_conf) {
2893238454Stuexen		sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
2894238454Stuexen		    (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
2895238454Stuexen	}
2896163953Srrs	return (m);
2897163953Srrs}
2898163953Srrs
2899163953Srrsstatic void
2900228653Stuexensctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
2901163953Srrs    struct sctp_tcb *stcb, struct sctp_nets *net)
2902163953Srrs{
2903163953Srrs	/* cp must not be used, others call this without a c-ack :-) */
2904163953Srrs	struct sctp_association *asoc;
2905163953Srrs
2906169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT2,
2907169420Srrs	    "sctp_handle_cookie_ack: handling COOKIE-ACK\n");
2908271746Stuexen	if ((stcb == NULL) || (net == NULL)) {
2909163953Srrs		return;
2910271746Stuexen	}
2911163953Srrs	asoc = &stcb->asoc;
2912163953Srrs
2913163953Srrs	sctp_stop_all_cookie_timers(stcb);
2914163953Srrs	/* process according to association state */
2915163953Srrs	if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) {
2916163953Srrs		/* state change only needed when I am in right state */
2917169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
2918171943Srrs		SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
2919224641Stuexen		sctp_start_net_timers(stcb);
2920163953Srrs		if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
2921163953Srrs			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
2922163953Srrs			    stcb->sctp_ep, stcb, asoc->primary_destination);
2923163953Srrs
2924163953Srrs		}
2925163953Srrs		/* update RTO */
2926163953Srrs		SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
2927163953Srrs		SCTP_STAT_INCR_GAUGE32(sctps_currestab);
2928163953Srrs		if (asoc->overall_error_count == 0) {
2929163953Srrs			net->RTO = sctp_calculate_rto(stcb, asoc, net,
2930218186Srrs			    &asoc->time_entered, sctp_align_safe_nocopy,
2931219397Srrs			    SCTP_RTT_FROM_NON_DATA);
2932163953Srrs		}
2933169378Srrs		(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
2934172090Srrs		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
2935163953Srrs		if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2936163953Srrs		    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
2937237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2938172090Srrs			struct socket *so;
2939172090Srrs
2940172090Srrs#endif
2941163953Srrs			stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
2942237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2943172090Srrs			so = SCTP_INP_SO(stcb->sctp_ep);
2944172090Srrs			atomic_add_int(&stcb->asoc.refcnt, 1);
2945172090Srrs			SCTP_TCB_UNLOCK(stcb);
2946172090Srrs			SCTP_SOCKET_LOCK(so, 1);
2947172090Srrs			SCTP_TCB_LOCK(stcb);
2948172090Srrs			atomic_subtract_int(&stcb->asoc.refcnt, 1);
2949218641Srrs#endif
2950218641Srrs			if ((stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) == 0) {
2951218641Srrs				soisconnected(stcb->sctp_socket);
2952172090Srrs			}
2953237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
2954172090Srrs			SCTP_SOCKET_UNLOCK(so, 1);
2955172090Srrs#endif
2956163953Srrs		}
2957163953Srrs		/*
2958163953Srrs		 * since we did not send a HB make sure we don't double
2959163953Srrs		 * things
2960163953Srrs		 */
2961163953Srrs		net->hb_responded = 1;
2962163953Srrs
2963218641Srrs		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
2964218641Srrs			/*
2965218641Srrs			 * We don't need to do the asconf thing, nor hb or
2966218641Srrs			 * autoclose if the socket is closed.
2967218641Srrs			 */
2968218641Srrs			goto closed_socket;
2969218641Srrs		}
2970218641Srrs		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
2971218641Srrs		    stcb, net);
2972218641Srrs
2973218641Srrs
2974163953Srrs		if (stcb->asoc.sctp_autoclose_ticks &&
2975163953Srrs		    sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTOCLOSE)) {
2976163953Srrs			sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE,
2977163953Srrs			    stcb->sctp_ep, stcb, NULL);
2978163953Srrs		}
2979163953Srrs		/*
2980171572Srrs		 * send ASCONF if parameters are pending and ASCONFs are
2981171572Srrs		 * allowed (eg. addresses changed when init/cookie echo were
2982171572Srrs		 * in flight)
2983163953Srrs		 */
2984163953Srrs		if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) &&
2985270362Stuexen		    (stcb->asoc.asconf_supported == 1) &&
2986163953Srrs		    (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) {
2987171572Srrs#ifdef SCTP_TIMER_BASED_ASCONF
2988163953Srrs			sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
2989163953Srrs			    stcb->sctp_ep, stcb,
2990163953Srrs			    stcb->asoc.primary_destination);
2991171572Srrs#else
2992172190Srrs			sctp_send_asconf(stcb, stcb->asoc.primary_destination,
2993172190Srrs			    SCTP_ADDR_NOT_LOCKED);
2994171572Srrs#endif
2995163953Srrs		}
2996163953Srrs	}
2997218641Srrsclosed_socket:
2998163953Srrs	/* Toss the cookie if I can */
2999163953Srrs	sctp_toss_old_cookies(stcb, asoc);
3000163953Srrs	if (!TAILQ_EMPTY(&asoc->sent_queue)) {
3001163953Srrs		/* Restart the timer if we have pending data */
3002163953Srrs		struct sctp_tmit_chunk *chk;
3003163953Srrs
3004163953Srrs		chk = TAILQ_FIRST(&asoc->sent_queue);
3005216822Stuexen		sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo);
3006163953Srrs	}
3007163953Srrs}
3008163953Srrs
3009163953Srrsstatic void
3010163953Srrssctp_handle_ecn_echo(struct sctp_ecne_chunk *cp,
3011163953Srrs    struct sctp_tcb *stcb)
3012163953Srrs{
3013163953Srrs	struct sctp_nets *net;
3014163953Srrs	struct sctp_tmit_chunk *lchk;
3015218072Srrs	struct sctp_ecne_chunk bkup;
3016228907Stuexen	uint8_t override_bit;
3017218072Srrs	uint32_t tsn, window_data_tsn;
3018218072Srrs	int len;
3019218232Srrs	unsigned int pkt_cnt;
3020163953Srrs
3021218072Srrs	len = ntohs(cp->ch.chunk_length);
3022218072Srrs	if ((len != sizeof(struct sctp_ecne_chunk)) &&
3023218072Srrs	    (len != sizeof(struct old_sctp_ecne_chunk))) {
3024163953Srrs		return;
3025163953Srrs	}
3026218072Srrs	if (len == sizeof(struct old_sctp_ecne_chunk)) {
3027218072Srrs		/* Its the old format */
3028218072Srrs		memcpy(&bkup, cp, sizeof(struct old_sctp_ecne_chunk));
3029218072Srrs		bkup.num_pkts_since_cwr = htonl(1);
3030218072Srrs		cp = &bkup;
3031218072Srrs	}
3032163953Srrs	SCTP_STAT_INCR(sctps_recvecne);
3033163953Srrs	tsn = ntohl(cp->tsn);
3034218072Srrs	pkt_cnt = ntohl(cp->num_pkts_since_cwr);
3035218072Srrs	lchk = TAILQ_LAST(&stcb->asoc.send_queue, sctpchunk_listhead);
3036163953Srrs	if (lchk == NULL) {
3037218129Srrs		window_data_tsn = stcb->asoc.sending_seq - 1;
3038163953Srrs	} else {
3039218129Srrs		window_data_tsn = lchk->rec.data.TSN_seq;
3040163953Srrs	}
3041163953Srrs
3042218072Srrs	/* Find where it was sent to if possible. */
3043163953Srrs	net = NULL;
3044216822Stuexen	TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) {
3045163953Srrs		if (lchk->rec.data.TSN_seq == tsn) {
3046163953Srrs			net = lchk->whoTo;
3047218186Srrs			net->ecn_prev_cwnd = lchk->rec.data.cwnd_at_send;
3048163953Srrs			break;
3049163953Srrs		}
3050216825Stuexen		if (SCTP_TSN_GT(lchk->rec.data.TSN_seq, tsn)) {
3051163953Srrs			break;
3052216825Stuexen		}
3053163953Srrs	}
3054218072Srrs	if (net == NULL) {
3055163953Srrs		/*
3056218072Srrs		 * What to do. A previous send of a CWR was possibly lost.
3057218072Srrs		 * See how old it is, we may have it marked on the actual
3058218072Srrs		 * net.
3059218072Srrs		 */
3060218072Srrs		TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3061218072Srrs			if (tsn == net->last_cwr_tsn) {
3062218072Srrs				/* Found him, send it off */
3063228907Stuexen				break;
3064218072Srrs			}
3065218072Srrs		}
3066228907Stuexen		if (net == NULL) {
3067228907Stuexen			/*
3068228907Stuexen			 * If we reach here, we need to send a special CWR
3069228907Stuexen			 * that says hey, we did this a long time ago and
3070228907Stuexen			 * you lost the response.
3071228907Stuexen			 */
3072228907Stuexen			net = TAILQ_FIRST(&stcb->asoc.nets);
3073228907Stuexen			if (net == NULL) {
3074228907Stuexen				/* TSNH */
3075228907Stuexen				return;
3076228907Stuexen			}
3077228907Stuexen			override_bit = SCTP_CWR_REDUCE_OVERRIDE;
3078228907Stuexen		} else {
3079228907Stuexen			override_bit = 0;
3080228907Stuexen		}
3081228907Stuexen	} else {
3082228907Stuexen		override_bit = 0;
3083218072Srrs	}
3084218129Srrs	if (SCTP_TSN_GT(tsn, net->cwr_window_tsn) &&
3085218129Srrs	    ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) {
3086218072Srrs		/*
3087171440Srrs		 * JRS - Use the congestion control given in the pluggable
3088171440Srrs		 * CC module
3089171440Srrs		 */
3090218129Srrs		stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 0, pkt_cnt);
3091171440Srrs		/*
3092218072Srrs		 * We reduce once every RTT. So we will only lower cwnd at
3093218072Srrs		 * the next sending seq i.e. the window_data_tsn
3094163953Srrs		 */
3095218072Srrs		net->cwr_window_tsn = window_data_tsn;
3096218072Srrs		net->ecn_ce_pkt_cnt += pkt_cnt;
3097218072Srrs		net->lost_cnt = pkt_cnt;
3098218072Srrs		net->last_cwr_tsn = tsn;
3099218072Srrs	} else {
3100218072Srrs		override_bit |= SCTP_CWR_IN_SAME_WINDOW;
3101218129Srrs		if (SCTP_TSN_GT(tsn, net->last_cwr_tsn) &&
3102218129Srrs		    ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) {
3103218072Srrs			/*
3104218129Srrs			 * Another loss in the same window update how many
3105218129Srrs			 * marks/packets lost we have had.
3106218072Srrs			 */
3107218129Srrs			int cnt = 1;
3108218072Srrs
3109218072Srrs			if (pkt_cnt > net->lost_cnt) {
3110218072Srrs				/* Should be the case */
3111218129Srrs				cnt = (pkt_cnt - net->lost_cnt);
3112218129Srrs				net->ecn_ce_pkt_cnt += cnt;
3113218072Srrs			}
3114218129Srrs			net->lost_cnt = pkt_cnt;
3115218072Srrs			net->last_cwr_tsn = tsn;
3116218129Srrs			/*
3117218129Srrs			 * Most CC functions will ignore this call, since we
3118218129Srrs			 * are in-window yet of the initial CE the peer saw.
3119218129Srrs			 */
3120218129Srrs			stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 1, cnt);
3121218072Srrs		}
3122163953Srrs	}
3123163953Srrs	/*
3124163953Srrs	 * We always send a CWR this way if our previous one was lost our
3125163953Srrs	 * peer will get an update, or if it is not time again to reduce we
3126218072Srrs	 * still get the cwr to the peer. Note we set the override when we
3127218072Srrs	 * could not find the TSN on the chunk or the destination network.
3128163953Srrs	 */
3129218072Srrs	sctp_send_cwr(stcb, net, net->last_cwr_tsn, override_bit);
3130163953Srrs}
3131163953Srrs
3132163953Srrsstatic void
3133218072Srrssctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sctp_nets *net)
3134163953Srrs{
3135163953Srrs	/*
3136163953Srrs	 * Here we get a CWR from the peer. We must look in the outqueue and
3137240520Seadler	 * make sure that we have a covered ECNE in the control chunk part.
3138163953Srrs	 * If so remove it.
3139163953Srrs	 */
3140163953Srrs	struct sctp_tmit_chunk *chk;
3141163953Srrs	struct sctp_ecne_chunk *ecne;
3142218072Srrs	int override;
3143218072Srrs	uint32_t cwr_tsn;
3144163953Srrs
3145218072Srrs	cwr_tsn = ntohl(cp->tsn);
3146218072Srrs	override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE;
3147163953Srrs	TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
3148163953Srrs		if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) {
3149163953Srrs			continue;
3150163953Srrs		}
3151218072Srrs		if ((override == 0) && (chk->whoTo != net)) {
3152218072Srrs			/* Must be from the right src unless override is set */
3153218072Srrs			continue;
3154218072Srrs		}
3155163953Srrs		ecne = mtod(chk->data, struct sctp_ecne_chunk *);
3156218072Srrs		if (SCTP_TSN_GE(cwr_tsn, ntohl(ecne->tsn))) {
3157163953Srrs			/* this covers this ECNE, we can remove it */
3158163953Srrs			stcb->asoc.ecn_echo_cnt_onq--;
3159163953Srrs			TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk,
3160163953Srrs			    sctp_next);
3161283718Stuexen			sctp_m_freem(chk->data);
3162283718Stuexen			chk->data = NULL;
3163163953Srrs			stcb->asoc.ctrl_queue_cnt--;
3164221627Stuexen			sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
3165218072Srrs			if (override == 0) {
3166218072Srrs				break;
3167218072Srrs			}
3168163953Srrs		}
3169163953Srrs	}
3170163953Srrs}
3171163953Srrs
3172163953Srrsstatic void
3173228653Stuexensctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSED,
3174163953Srrs    struct sctp_tcb *stcb, struct sctp_nets *net)
3175163953Srrs{
3176163953Srrs	struct sctp_association *asoc;
3177163953Srrs
3178237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3179172090Srrs	struct socket *so;
3180172090Srrs
3181172090Srrs#endif
3182172090Srrs
3183169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT2,
3184169420Srrs	    "sctp_handle_shutdown_complete: handling SHUTDOWN-COMPLETE\n");
3185163953Srrs	if (stcb == NULL)
3186163953Srrs		return;
3187163953Srrs
3188163953Srrs	asoc = &stcb->asoc;
3189163953Srrs	/* process according to association state */
3190163953Srrs	if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) {
3191163953Srrs		/* unexpected SHUTDOWN-COMPLETE... so ignore... */
3192171990Srrs		SCTPDBG(SCTP_DEBUG_INPUT2,
3193171990Srrs		    "sctp_handle_shutdown_complete: not in SCTP_STATE_SHUTDOWN_ACK_SENT --- ignore\n");
3194163953Srrs		SCTP_TCB_UNLOCK(stcb);
3195163953Srrs		return;
3196163953Srrs	}
3197163953Srrs	/* notify upper layer protocol */
3198163953Srrs	if (stcb->sctp_socket) {
3199172090Srrs		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
3200163953Srrs	}
3201252585Stuexen#ifdef INVARIANTS
3202252585Stuexen	if (!TAILQ_EMPTY(&asoc->send_queue) ||
3203252585Stuexen	    !TAILQ_EMPTY(&asoc->sent_queue) ||
3204252585Stuexen	    !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
3205252585Stuexen		panic("Queues are not empty when handling SHUTDOWN-COMPLETE");
3206252585Stuexen	}
3207252585Stuexen#endif
3208163953Srrs	/* stop the timer */
3209283822Stuexen	sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net,
3210283822Stuexen	    SCTP_FROM_SCTP_INPUT + SCTP_LOC_24);
3211163953Srrs	SCTP_STAT_INCR_COUNTER32(sctps_shutdown);
3212163953Srrs	/* free the TCB */
3213171990Srrs	SCTPDBG(SCTP_DEBUG_INPUT2,
3214171990Srrs	    "sctp_handle_shutdown_complete: calls free-asoc\n");
3215237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3216172090Srrs	so = SCTP_INP_SO(stcb->sctp_ep);
3217172090Srrs	atomic_add_int(&stcb->asoc.refcnt, 1);
3218172090Srrs	SCTP_TCB_UNLOCK(stcb);
3219172090Srrs	SCTP_SOCKET_LOCK(so, 1);
3220172090Srrs	SCTP_TCB_LOCK(stcb);
3221172090Srrs	atomic_subtract_int(&stcb->asoc.refcnt, 1);
3222172090Srrs#endif
3223283822Stuexen	(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
3224283822Stuexen	    SCTP_FROM_SCTP_INPUT + SCTP_LOC_25);
3225237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
3226172090Srrs	SCTP_SOCKET_UNLOCK(so, 1);
3227172090Srrs#endif
3228163953Srrs	return;
3229163953Srrs}
3230163953Srrs
3231163953Srrsstatic int
3232163953Srrsprocess_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
3233163953Srrs    struct sctp_nets *net, uint8_t flg)
3234163953Srrs{
3235163953Srrs	switch (desc->chunk_type) {
3236211969Stuexen	case SCTP_DATA:
3237163953Srrs		/* find the tsn to resend (possibly */
3238163953Srrs		{
3239163953Srrs			uint32_t tsn;
3240163953Srrs			struct sctp_tmit_chunk *tp1;
3241163953Srrs
3242163953Srrs			tsn = ntohl(desc->tsn_ifany);
3243216822Stuexen			TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
3244163953Srrs				if (tp1->rec.data.TSN_seq == tsn) {
3245163953Srrs					/* found it */
3246163953Srrs					break;
3247163953Srrs				}
3248216825Stuexen				if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, tsn)) {
3249163953Srrs					/* not found */
3250163953Srrs					tp1 = NULL;
3251163953Srrs					break;
3252163953Srrs				}
3253163953Srrs			}
3254163953Srrs			if (tp1 == NULL) {
3255163953Srrs				/*
3256163953Srrs				 * Do it the other way , aka without paying
3257163953Srrs				 * attention to queue seq order.
3258163953Srrs				 */
3259163953Srrs				SCTP_STAT_INCR(sctps_pdrpdnfnd);
3260216822Stuexen				TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
3261163953Srrs					if (tp1->rec.data.TSN_seq == tsn) {
3262163953Srrs						/* found it */
3263163953Srrs						break;
3264163953Srrs					}
3265163953Srrs				}
3266163953Srrs			}
3267163953Srrs			if (tp1 == NULL) {
3268163953Srrs				SCTP_STAT_INCR(sctps_pdrptsnnf);
3269163953Srrs			}
3270163953Srrs			if ((tp1) && (tp1->sent < SCTP_DATAGRAM_ACKED)) {
3271163953Srrs				uint8_t *ddp;
3272163953Srrs
3273214877Stuexen				if (((flg & SCTP_BADCRC) == 0) &&
3274214877Stuexen				    ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) {
3275214877Stuexen					return (0);
3276214877Stuexen				}
3277163953Srrs				if ((stcb->asoc.peers_rwnd == 0) &&
3278163953Srrs				    ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) {
3279163953Srrs					SCTP_STAT_INCR(sctps_pdrpdiwnp);
3280163953Srrs					return (0);
3281163953Srrs				}
3282163953Srrs				if (stcb->asoc.peers_rwnd == 0 &&
3283163953Srrs				    (flg & SCTP_FROM_MIDDLE_BOX)) {
3284163953Srrs					SCTP_STAT_INCR(sctps_pdrpdizrw);
3285163953Srrs					return (0);
3286163953Srrs				}
3287163953Srrs				ddp = (uint8_t *) (mtod(tp1->data, caddr_t)+
3288163953Srrs				    sizeof(struct sctp_data_chunk));
3289163953Srrs				{
3290163953Srrs					unsigned int iii;
3291163953Srrs
3292163953Srrs					for (iii = 0; iii < sizeof(desc->data_bytes);
3293163953Srrs					    iii++) {
3294163953Srrs						if (ddp[iii] != desc->data_bytes[iii]) {
3295163953Srrs							SCTP_STAT_INCR(sctps_pdrpbadd);
3296163953Srrs							return (-1);
3297163953Srrs						}
3298163953Srrs					}
3299163953Srrs				}
3300163953Srrs
3301163953Srrs				if (tp1->do_rtt) {
3302163953Srrs					/*
3303163953Srrs					 * this guy had a RTO calculation
3304163953Srrs					 * pending on it, cancel it
3305163953Srrs					 */
3306219397Srrs					if (tp1->whoTo->rto_needed == 0) {
3307219397Srrs						tp1->whoTo->rto_needed = 1;
3308219397Srrs					}
3309163953Srrs					tp1->do_rtt = 0;
3310163953Srrs				}
3311163953Srrs				SCTP_STAT_INCR(sctps_pdrpmark);
3312163953Srrs				if (tp1->sent != SCTP_DATAGRAM_RESEND)
3313163953Srrs					sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
3314163953Srrs				/*
3315163953Srrs				 * mark it as if we were doing a FR, since
3316163953Srrs				 * we will be getting gap ack reports behind
3317163953Srrs				 * the info from the router.
3318163953Srrs				 */
3319163953Srrs				tp1->rec.data.doing_fast_retransmit = 1;
3320163953Srrs				/*
3321163953Srrs				 * mark the tsn with what sequences can
3322163953Srrs				 * cause a new FR.
3323163953Srrs				 */
3324163953Srrs				if (TAILQ_EMPTY(&stcb->asoc.send_queue)) {
3325163953Srrs					tp1->rec.data.fast_retran_tsn = stcb->asoc.sending_seq;
3326163953Srrs				} else {
3327163953Srrs					tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq;
3328163953Srrs				}
3329163953Srrs
3330163953Srrs				/* restart the timer */
3331163953Srrs				sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
3332283822Stuexen				    stcb, tp1->whoTo,
3333283822Stuexen				    SCTP_FROM_SCTP_INPUT + SCTP_LOC_26);
3334163953Srrs				sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
3335163953Srrs				    stcb, tp1->whoTo);
3336163953Srrs
3337163953Srrs				/* fix counts and things */
3338179783Srrs				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
3339170744Srrs					sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP,
3340170744Srrs					    tp1->whoTo->flight_size,
3341170744Srrs					    tp1->book_size,
3342170744Srrs					    (uintptr_t) stcb,
3343170744Srrs					    tp1->rec.data.TSN_seq);
3344170744Srrs				}
3345190689Srrs				if (tp1->sent < SCTP_DATAGRAM_RESEND) {
3346190689Srrs					sctp_flight_size_decrease(tp1);
3347190689Srrs					sctp_total_flight_decrease(stcb, tp1);
3348190689Srrs				}
3349216502Stuexen				tp1->sent = SCTP_DATAGRAM_RESEND;
3350163953Srrs			} {
3351163953Srrs				/* audit code */
3352163953Srrs				unsigned int audit;
3353163953Srrs
3354163953Srrs				audit = 0;
3355163953Srrs				TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
3356163953Srrs					if (tp1->sent == SCTP_DATAGRAM_RESEND)
3357163953Srrs						audit++;
3358163953Srrs				}
3359163953Srrs				TAILQ_FOREACH(tp1, &stcb->asoc.control_send_queue,
3360163953Srrs				    sctp_next) {
3361163953Srrs					if (tp1->sent == SCTP_DATAGRAM_RESEND)
3362163953Srrs						audit++;
3363163953Srrs				}
3364163953Srrs				if (audit != stcb->asoc.sent_queue_retran_cnt) {
3365169420Srrs					SCTP_PRINTF("**Local Audit finds cnt:%d asoc cnt:%d\n",
3366163953Srrs					    audit, stcb->asoc.sent_queue_retran_cnt);
3367163953Srrs#ifndef SCTP_AUDITING_ENABLED
3368163953Srrs					stcb->asoc.sent_queue_retran_cnt = audit;
3369163953Srrs#endif
3370163953Srrs				}
3371163953Srrs			}
3372163953Srrs		}
3373163953Srrs		break;
3374163953Srrs	case SCTP_ASCONF:
3375163953Srrs		{
3376163953Srrs			struct sctp_tmit_chunk *asconf;
3377163953Srrs
3378163953Srrs			TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue,
3379163953Srrs			    sctp_next) {
3380163953Srrs				if (asconf->rec.chunk_id.id == SCTP_ASCONF) {
3381163953Srrs					break;
3382163953Srrs				}
3383163953Srrs			}
3384163953Srrs			if (asconf) {
3385163953Srrs				if (asconf->sent != SCTP_DATAGRAM_RESEND)
3386163953Srrs					sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
3387163953Srrs				asconf->sent = SCTP_DATAGRAM_RESEND;
3388163953Srrs				asconf->snd_count--;
3389163953Srrs			}
3390163953Srrs		}
3391163953Srrs		break;
3392163953Srrs	case SCTP_INITIATION:
3393163953Srrs		/* resend the INIT */
3394163953Srrs		stcb->asoc.dropped_special_cnt++;
3395163953Srrs		if (stcb->asoc.dropped_special_cnt < SCTP_RETRY_DROPPED_THRESH) {
3396163953Srrs			/*
3397163953Srrs			 * If we can get it in, in a few attempts we do
3398163953Srrs			 * this, otherwise we let the timer fire.
3399163953Srrs			 */
3400163953Srrs			sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep,
3401283822Stuexen			    stcb, net,
3402283822Stuexen			    SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
3403172090Srrs			sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
3404163953Srrs		}
3405163953Srrs		break;
3406163953Srrs	case SCTP_SELECTIVE_ACK:
3407206137Stuexen	case SCTP_NR_SELECTIVE_ACK:
3408163953Srrs		/* resend the sack */
3409221627Stuexen		sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
3410163953Srrs		break;
3411163953Srrs	case SCTP_HEARTBEAT_REQUEST:
3412163953Srrs		/* resend a demand HB */
3413171440Srrs		if ((stcb->asoc.overall_error_count + 3) < stcb->asoc.max_send_times) {
3414171440Srrs			/*
3415171440Srrs			 * Only retransmit if we KNOW we wont destroy the
3416171440Srrs			 * tcb
3417171440Srrs			 */
3418224641Stuexen			sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
3419171440Srrs		}
3420163953Srrs		break;
3421163953Srrs	case SCTP_SHUTDOWN:
3422163953Srrs		sctp_send_shutdown(stcb, net);
3423163953Srrs		break;
3424163953Srrs	case SCTP_SHUTDOWN_ACK:
3425163953Srrs		sctp_send_shutdown_ack(stcb, net);
3426163953Srrs		break;
3427163953Srrs	case SCTP_COOKIE_ECHO:
3428163953Srrs		{
3429163953Srrs			struct sctp_tmit_chunk *cookie;
3430163953Srrs
3431163953Srrs			cookie = NULL;
3432163953Srrs			TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue,
3433163953Srrs			    sctp_next) {
3434163953Srrs				if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) {
3435163953Srrs					break;
3436163953Srrs				}
3437163953Srrs			}
3438163953Srrs			if (cookie) {
3439163953Srrs				if (cookie->sent != SCTP_DATAGRAM_RESEND)
3440163953Srrs					sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
3441163953Srrs				cookie->sent = SCTP_DATAGRAM_RESEND;
3442163953Srrs				sctp_stop_all_cookie_timers(stcb);
3443163953Srrs			}
3444163953Srrs		}
3445163953Srrs		break;
3446163953Srrs	case SCTP_COOKIE_ACK:
3447163953Srrs		sctp_send_cookie_ack(stcb);
3448163953Srrs		break;
3449163953Srrs	case SCTP_ASCONF_ACK:
3450163953Srrs		/* resend last asconf ack */
3451171990Srrs		sctp_send_asconf_ack(stcb);
3452163953Srrs		break;
3453163953Srrs	case SCTP_FORWARD_CUM_TSN:
3454163953Srrs		send_forward_tsn(stcb, &stcb->asoc);
3455163953Srrs		break;
3456163953Srrs		/* can't do anything with these */
3457163953Srrs	case SCTP_PACKET_DROPPED:
3458163953Srrs	case SCTP_INITIATION_ACK:	/* this should not happen */
3459163953Srrs	case SCTP_HEARTBEAT_ACK:
3460163953Srrs	case SCTP_ABORT_ASSOCIATION:
3461163953Srrs	case SCTP_OPERATION_ERROR:
3462163953Srrs	case SCTP_SHUTDOWN_COMPLETE:
3463163953Srrs	case SCTP_ECN_ECHO:
3464163953Srrs	case SCTP_ECN_CWR:
3465163953Srrs	default:
3466163953Srrs		break;
3467163953Srrs	}
3468163953Srrs	return (0);
3469163953Srrs}
3470163953Srrs
3471163953Srrsvoid
3472240198Stuexensctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list)
3473163953Srrs{
3474240198Stuexen	uint32_t i;
3475163953Srrs	uint16_t temp;
3476163953Srrs
3477163953Srrs	/*
3478163953Srrs	 * We set things to 0xffff since this is the last delivered sequence
3479163953Srrs	 * and we will be sending in 0 after the reset.
3480163953Srrs	 */
3481163953Srrs
3482163953Srrs	if (number_entries) {
3483163953Srrs		for (i = 0; i < number_entries; i++) {
3484163953Srrs			temp = ntohs(list[i]);
3485163953Srrs			if (temp >= stcb->asoc.streamincnt) {
3486163953Srrs				continue;
3487163953Srrs			}
3488163953Srrs			stcb->asoc.strmin[temp].last_sequence_delivered = 0xffff;
3489163953Srrs		}
3490163953Srrs	} else {
3491163953Srrs		list = NULL;
3492163953Srrs		for (i = 0; i < stcb->asoc.streamincnt; i++) {
3493163953Srrs			stcb->asoc.strmin[i].last_sequence_delivered = 0xffff;
3494163953Srrs		}
3495163953Srrs	}
3496172090Srrs	sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);
3497163953Srrs}
3498163953Srrs
3499163953Srrsstatic void
3500252585Stuexensctp_reset_out_streams(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list)
3501163953Srrs{
3502252585Stuexen	uint32_t i;
3503252585Stuexen	uint16_t temp;
3504163953Srrs
3505252585Stuexen	if (number_entries > 0) {
3506163953Srrs		for (i = 0; i < number_entries; i++) {
3507163953Srrs			temp = ntohs(list[i]);
3508163953Srrs			if (temp >= stcb->asoc.streamoutcnt) {
3509163953Srrs				/* no such stream */
3510163953Srrs				continue;
3511163953Srrs			}
3512242627Stuexen			stcb->asoc.strmout[temp].next_sequence_send = 0;
3513163953Srrs		}
3514252585Stuexen	} else {
3515252585Stuexen		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
3516252585Stuexen			stcb->asoc.strmout[i].next_sequence_send = 0;
3517252585Stuexen		}
3518163953Srrs	}
3519172090Srrs	sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);
3520163953Srrs}
3521163953Srrs
3522294140Stuexenstatic void
3523294140Stuexensctp_reset_clear_pending(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t * list)
3524294140Stuexen{
3525294140Stuexen	uint32_t i;
3526294140Stuexen	uint16_t temp;
3527163953Srrs
3528294140Stuexen	if (number_entries > 0) {
3529294140Stuexen		for (i = 0; i < number_entries; i++) {
3530294140Stuexen			temp = ntohs(list[i]);
3531294140Stuexen			if (temp >= stcb->asoc.streamoutcnt) {
3532294140Stuexen				/* no such stream */
3533294140Stuexen				continue;
3534294140Stuexen			}
3535294140Stuexen			stcb->asoc.strmout[temp].state = SCTP_STREAM_OPEN;
3536294140Stuexen		}
3537294140Stuexen	} else {
3538294140Stuexen		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
3539294140Stuexen			stcb->asoc.strmout[i].state = SCTP_STREAM_OPEN;
3540294140Stuexen		}
3541294140Stuexen	}
3542294140Stuexen}
3543294140Stuexen
3544294140Stuexen
3545273275Stuexenstruct sctp_stream_reset_request *
3546163953Srrssctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk)
3547163953Srrs{
3548163953Srrs	struct sctp_association *asoc;
3549240198Stuexen	struct sctp_chunkhdr *ch;
3550273275Stuexen	struct sctp_stream_reset_request *r;
3551163953Srrs	struct sctp_tmit_chunk *chk;
3552163953Srrs	int len, clen;
3553163953Srrs
3554163953Srrs	asoc = &stcb->asoc;
3555163953Srrs	if (TAILQ_EMPTY(&stcb->asoc.control_send_queue)) {
3556169208Srrs		asoc->stream_reset_outstanding = 0;
3557163953Srrs		return (NULL);
3558163953Srrs	}
3559163953Srrs	if (stcb->asoc.str_reset == NULL) {
3560169208Srrs		asoc->stream_reset_outstanding = 0;
3561163953Srrs		return (NULL);
3562163953Srrs	}
3563163953Srrs	chk = stcb->asoc.str_reset;
3564163953Srrs	if (chk->data == NULL) {
3565163953Srrs		return (NULL);
3566163953Srrs	}
3567163953Srrs	if (bchk) {
3568163953Srrs		/* he wants a copy of the chk pointer */
3569163953Srrs		*bchk = chk;
3570163953Srrs	}
3571163953Srrs	clen = chk->send_size;
3572240198Stuexen	ch = mtod(chk->data, struct sctp_chunkhdr *);
3573273275Stuexen	r = (struct sctp_stream_reset_request *)(ch + 1);
3574163953Srrs	if (ntohl(r->request_seq) == seq) {
3575163953Srrs		/* found it */
3576163953Srrs		return (r);
3577163953Srrs	}
3578163953Srrs	len = SCTP_SIZE32(ntohs(r->ph.param_length));
3579163953Srrs	if (clen > (len + (int)sizeof(struct sctp_chunkhdr))) {
3580163953Srrs		/* move to the next one, there can only be a max of two */
3581273275Stuexen		r = (struct sctp_stream_reset_request *)((caddr_t)r + len);
3582163953Srrs		if (ntohl(r->request_seq) == seq) {
3583163953Srrs			return (r);
3584163953Srrs		}
3585163953Srrs	}
3586163953Srrs	/* that seq is not here */
3587163953Srrs	return (NULL);
3588163953Srrs}
3589163953Srrs
3590163953Srrsstatic void
3591163953Srrssctp_clean_up_stream_reset(struct sctp_tcb *stcb)
3592163953Srrs{
3593163953Srrs	struct sctp_association *asoc;
3594163953Srrs	struct sctp_tmit_chunk *chk = stcb->asoc.str_reset;
3595163953Srrs
3596163953Srrs	if (stcb->asoc.str_reset == NULL) {
3597163953Srrs		return;
3598163953Srrs	}
3599166675Srrs	asoc = &stcb->asoc;
3600166675Srrs
3601283822Stuexen	sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb,
3602283822Stuexen	    chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_28);
3603163953Srrs	TAILQ_REMOVE(&asoc->control_send_queue,
3604163953Srrs	    chk,
3605163953Srrs	    sctp_next);
3606163953Srrs	if (chk->data) {
3607163953Srrs		sctp_m_freem(chk->data);
3608163953Srrs		chk->data = NULL;
3609163953Srrs	}
3610163953Srrs	asoc->ctrl_queue_cnt--;
3611221627Stuexen	sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
3612172156Srrs	/* sa_ignore NO_NULL_CHK */
3613163953Srrs	stcb->asoc.str_reset = NULL;
3614163953Srrs}
3615163953Srrs
3616163953Srrs
3617163953Srrsstatic int
3618163953Srrssctp_handle_stream_reset_response(struct sctp_tcb *stcb,
3619163953Srrs    uint32_t seq, uint32_t action,
3620164139Srrs    struct sctp_stream_reset_response *respin)
3621163953Srrs{
3622163953Srrs	uint16_t type;
3623163953Srrs	int lparm_len;
3624163953Srrs	struct sctp_association *asoc = &stcb->asoc;
3625163953Srrs	struct sctp_tmit_chunk *chk;
3626273275Stuexen	struct sctp_stream_reset_request *req_param;
3627273275Stuexen	struct sctp_stream_reset_out_request *req_out_param;
3628273275Stuexen	struct sctp_stream_reset_in_request *req_in_param;
3629252585Stuexen	uint32_t number_entries;
3630163953Srrs
3631163953Srrs	if (asoc->stream_reset_outstanding == 0) {
3632163953Srrs		/* duplicate */
3633163953Srrs		return (0);
3634163953Srrs	}
3635163953Srrs	if (seq == stcb->asoc.str_reset_seq_out) {
3636273275Stuexen		req_param = sctp_find_stream_reset(stcb, seq, &chk);
3637273275Stuexen		if (req_param != NULL) {
3638163953Srrs			stcb->asoc.str_reset_seq_out++;
3639273275Stuexen			type = ntohs(req_param->ph.param_type);
3640273275Stuexen			lparm_len = ntohs(req_param->ph.param_length);
3641163953Srrs			if (type == SCTP_STR_RESET_OUT_REQUEST) {
3642294140Stuexen				int no_clear = 0;
3643294140Stuexen
3644273275Stuexen				req_out_param = (struct sctp_stream_reset_out_request *)req_param;
3645164139Srrs				number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t);
3646163953Srrs				asoc->stream_reset_out_is_outstanding = 0;
3647163953Srrs				if (asoc->stream_reset_outstanding)
3648163953Srrs					asoc->stream_reset_outstanding--;
3649235064Stuexen				if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
3650163953Srrs					/* do it */
3651273275Stuexen					sctp_reset_out_streams(stcb, number_entries, req_out_param->list_of_streams);
3652235066Stuexen				} else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
3653273275Stuexen					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED);
3654294140Stuexen				} else if (action == SCTP_STREAM_RESET_RESULT_IN_PROGRESS) {
3655294140Stuexen					/*
3656294140Stuexen					 * Set it up so we don't stop
3657294140Stuexen					 * retransmitting
3658294140Stuexen					 */
3659294213Stuexen					asoc->stream_reset_outstanding++;
3660294140Stuexen					stcb->asoc.str_reset_seq_out--;
3661294140Stuexen					asoc->stream_reset_out_is_outstanding = 1;
3662294140Stuexen					no_clear = 1;
3663163953Srrs				} else {
3664273275Stuexen					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, req_out_param->list_of_streams, SCTP_SO_NOT_LOCKED);
3665163953Srrs				}
3666294140Stuexen				if (no_clear == 0) {
3667294140Stuexen					sctp_reset_clear_pending(stcb, number_entries, req_out_param->list_of_streams);
3668294140Stuexen				}
3669163953Srrs			} else if (type == SCTP_STR_RESET_IN_REQUEST) {
3670273275Stuexen				req_in_param = (struct sctp_stream_reset_in_request *)req_param;
3671164139Srrs				number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t);
3672163953Srrs				if (asoc->stream_reset_outstanding)
3673163953Srrs					asoc->stream_reset_outstanding--;
3674235066Stuexen				if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
3675235066Stuexen					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_IN, stcb,
3676273275Stuexen					    number_entries, req_in_param->list_of_streams, SCTP_SO_NOT_LOCKED);
3677235066Stuexen				} else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) {
3678233660Srrs					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb,
3679273275Stuexen					    number_entries, req_in_param->list_of_streams, SCTP_SO_NOT_LOCKED);
3680163953Srrs				}
3681233660Srrs			} else if (type == SCTP_STR_RESET_ADD_OUT_STREAMS) {
3682188854Srrs				/* Ok we now may have more streams */
3683233660Srrs				int num_stream;
3684233660Srrs
3685233660Srrs				num_stream = stcb->asoc.strm_pending_add_size;
3686233660Srrs				if (num_stream > (stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt)) {
3687233660Srrs					/* TSNH */
3688233660Srrs					num_stream = stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt;
3689233660Srrs				}
3690233660Srrs				stcb->asoc.strm_pending_add_size = 0;
3691189121Srrs				if (asoc->stream_reset_outstanding)
3692189121Srrs					asoc->stream_reset_outstanding--;
3693235064Stuexen				if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
3694188854Srrs					/* Put the new streams into effect */
3695294140Stuexen					int i;
3696294140Stuexen
3697294140Stuexen					for (i = asoc->streamoutcnt; i < (asoc->streamoutcnt + num_stream); i++) {
3698294140Stuexen						asoc->strmout[i].state = SCTP_STREAM_OPEN;
3699294140Stuexen					}
3700294140Stuexen					asoc->streamoutcnt += num_stream;
3701233660Srrs					sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0);
3702235066Stuexen				} else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
3703235066Stuexen					sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
3704235066Stuexen					    SCTP_STREAM_CHANGE_DENIED);
3705188854Srrs				} else {
3706233660Srrs					sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
3707235066Stuexen					    SCTP_STREAM_CHANGE_FAILED);
3708188854Srrs				}
3709233660Srrs			} else if (type == SCTP_STR_RESET_ADD_IN_STREAMS) {
3710233660Srrs				if (asoc->stream_reset_outstanding)
3711233660Srrs					asoc->stream_reset_outstanding--;
3712235066Stuexen				if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
3713233660Srrs					sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
3714235066Stuexen					    SCTP_STREAM_CHANGE_DENIED);
3715235066Stuexen				} else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) {
3716235066Stuexen					sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
3717235066Stuexen					    SCTP_STREAM_CHANGE_FAILED);
3718233660Srrs				}
3719163953Srrs			} else if (type == SCTP_STR_RESET_TSN_REQUEST) {
3720163953Srrs				/**
3721163953Srrs				 * a) Adopt the new in tsn.
3722163953Srrs				 * b) reset the map
3723163953Srrs				 * c) Adopt the new out-tsn
3724163953Srrs				 */
3725163953Srrs				struct sctp_stream_reset_response_tsn *resp;
3726163953Srrs				struct sctp_forward_tsn_chunk fwdtsn;
3727163953Srrs				int abort_flag = 0;
3728163953Srrs
3729163953Srrs				if (respin == NULL) {
3730163953Srrs					/* huh ? */
3731163953Srrs					return (0);
3732163953Srrs				}
3733277807Sdelphij				if (ntohs(respin->ph.param_length) < sizeof(struct sctp_stream_reset_response_tsn)) {
3734277807Sdelphij					return (0);
3735277807Sdelphij				}
3736235064Stuexen				if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
3737163953Srrs					resp = (struct sctp_stream_reset_response_tsn *)respin;
3738163953Srrs					asoc->stream_reset_outstanding--;
3739163953Srrs					fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk));
3740163953Srrs					fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN;
3741163953Srrs					fwdtsn.new_cumulative_tsn = htonl(ntohl(resp->senders_next_tsn) - 1);
3742170992Srrs					sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0);
3743163953Srrs					if (abort_flag) {
3744163953Srrs						return (1);
3745163953Srrs					}
3746163953Srrs					stcb->asoc.highest_tsn_inside_map = (ntohl(resp->senders_next_tsn) - 1);
3747179783Srrs					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
3748179783Srrs						sctp_log_map(0, 7, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
3749179783Srrs					}
3750180955Srrs					stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map;
3751163953Srrs					stcb->asoc.mapping_array_base_tsn = ntohl(resp->senders_next_tsn);
3752163953Srrs					memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size);
3753185694Srrs
3754205627Srrs					stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map;
3755206137Stuexen					memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size);
3756205627Srrs
3757163953Srrs					stcb->asoc.sending_seq = ntohl(resp->receivers_next_tsn);
3758163953Srrs					stcb->asoc.last_acked_seq = stcb->asoc.cumulative_tsn;
3759163953Srrs
3760163953Srrs					sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL);
3761163953Srrs					sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL);
3762233660Srrs					sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 0);
3763235066Stuexen				} else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
3764235066Stuexen					sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1),
3765235066Stuexen					    SCTP_ASSOC_RESET_DENIED);
3766233660Srrs				} else {
3767233660Srrs					sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1),
3768235066Stuexen					    SCTP_ASSOC_RESET_FAILED);
3769163953Srrs				}
3770163953Srrs			}
3771163953Srrs			/* get rid of the request and get the request flags */
3772163953Srrs			if (asoc->stream_reset_outstanding == 0) {
3773163953Srrs				sctp_clean_up_stream_reset(stcb);
3774163953Srrs			}
3775163953Srrs		}
3776163953Srrs	}
3777294140Stuexen	if (asoc->stream_reset_outstanding == 0) {
3778294141Stuexen		sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED);
3779294140Stuexen	}
3780163953Srrs	return (0);
3781163953Srrs}
3782163953Srrs
3783163953Srrsstatic void
3784163953Srrssctp_handle_str_reset_request_in(struct sctp_tcb *stcb,
3785163953Srrs    struct sctp_tmit_chunk *chk,
3786170992Srrs    struct sctp_stream_reset_in_request *req, int trunc)
3787163953Srrs{
3788163953Srrs	uint32_t seq;
3789163953Srrs	int len, i;
3790163953Srrs	int number_entries;
3791163953Srrs	uint16_t temp;
3792163953Srrs
3793163953Srrs	/*
3794163953Srrs	 * peer wants me to send a str-reset to him for my outgoing seq's if
3795163953Srrs	 * seq_in is right.
3796163953Srrs	 */
3797163953Srrs	struct sctp_association *asoc = &stcb->asoc;
3798163953Srrs
3799163953Srrs	seq = ntohl(req->request_seq);
3800163953Srrs	if (asoc->str_reset_seq_in == seq) {
3801235064Stuexen		asoc->last_reset_action[1] = asoc->last_reset_action[0];
3802235064Stuexen		if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) {
3803235064Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
3804235064Stuexen		} else if (trunc) {
3805170992Srrs			/* Can't do it, since they exceeded our buffer size  */
3806235064Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
3807170992Srrs		} else if (stcb->asoc.stream_reset_out_is_outstanding == 0) {
3808163953Srrs			len = ntohs(req->ph.param_length);
3809163953Srrs			number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t));
3810294140Stuexen			if (number_entries) {
3811294140Stuexen				for (i = 0; i < number_entries; i++) {
3812294140Stuexen					temp = ntohs(req->list_of_streams[i]);
3813294140Stuexen					if (temp >= stcb->asoc.streamoutcnt) {
3814294140Stuexen						asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
3815294140Stuexen						goto bad_boy;
3816294140Stuexen					}
3817294140Stuexen					req->list_of_streams[i] = temp;
3818294140Stuexen				}
3819294140Stuexen				for (i = 0; i < number_entries; i++) {
3820294140Stuexen					if (stcb->asoc.strmout[req->list_of_streams[i]].state == SCTP_STREAM_OPEN) {
3821294140Stuexen						stcb->asoc.strmout[req->list_of_streams[i]].state = SCTP_STREAM_RESET_PENDING;
3822294140Stuexen					}
3823294140Stuexen				}
3824294140Stuexen			} else {
3825294140Stuexen				/* Its all */
3826294140Stuexen				for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
3827294140Stuexen					if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN)
3828294140Stuexen						stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING;
3829294140Stuexen				}
3830163953Srrs			}
3831235064Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
3832163953Srrs		} else {
3833163953Srrs			/* Can't do it, since we have sent one out */
3834235064Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS;
3835163953Srrs		}
3836294140Stuexenbad_boy:
3837233660Srrs		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
3838163953Srrs		asoc->str_reset_seq_in++;
3839163953Srrs	} else if (asoc->str_reset_seq_in - 1 == seq) {
3840163953Srrs		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
3841163953Srrs	} else if (asoc->str_reset_seq_in - 2 == seq) {
3842163953Srrs		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
3843163953Srrs	} else {
3844235064Stuexen		sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
3845163953Srrs	}
3846294141Stuexen	sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_NOT_LOCKED);
3847163953Srrs}
3848163953Srrs
3849163953Srrsstatic int
3850163953Srrssctp_handle_str_reset_request_tsn(struct sctp_tcb *stcb,
3851163953Srrs    struct sctp_tmit_chunk *chk,
3852163953Srrs    struct sctp_stream_reset_tsn_request *req)
3853163953Srrs{
3854163953Srrs	/* reset all in and out and update the tsn */
3855163953Srrs	/*
3856163953Srrs	 * A) reset my str-seq's on in and out. B) Select a receive next,
3857163953Srrs	 * and set cum-ack to it. Also process this selected number as a
3858163953Srrs	 * fwd-tsn as well. C) set in the response my next sending seq.
3859163953Srrs	 */
3860163953Srrs	struct sctp_forward_tsn_chunk fwdtsn;
3861163953Srrs	struct sctp_association *asoc = &stcb->asoc;
3862163953Srrs	int abort_flag = 0;
3863163953Srrs	uint32_t seq;
3864163953Srrs
3865163953Srrs	seq = ntohl(req->request_seq);
3866163953Srrs	if (asoc->str_reset_seq_in == seq) {
3867235283Stuexen		asoc->last_reset_action[1] = stcb->asoc.last_reset_action[0];
3868235064Stuexen		if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) {
3869235064Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
3870235283Stuexen		} else {
3871235064Stuexen			fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk));
3872235283Stuexen			fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN;
3873235283Stuexen			fwdtsn.ch.chunk_flags = 0;
3874235283Stuexen			fwdtsn.new_cumulative_tsn = htonl(stcb->asoc.highest_tsn_inside_map + 1);
3875235283Stuexen			sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0);
3876235283Stuexen			if (abort_flag) {
3877235283Stuexen				return (1);
3878235283Stuexen			}
3879235283Stuexen			asoc->highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA;
3880235283Stuexen			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
3881235283Stuexen				sctp_log_map(0, 10, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
3882235283Stuexen			}
3883235283Stuexen			asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->highest_tsn_inside_map;
3884235283Stuexen			asoc->mapping_array_base_tsn = asoc->highest_tsn_inside_map + 1;
3885235283Stuexen			memset(asoc->mapping_array, 0, asoc->mapping_array_size);
3886235283Stuexen			asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map;
3887235283Stuexen			memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size);
3888235283Stuexen			atomic_add_int(&asoc->sending_seq, 1);
3889235283Stuexen			/* save off historical data for retrans */
3890235283Stuexen			asoc->last_sending_seq[1] = asoc->last_sending_seq[0];
3891235283Stuexen			asoc->last_sending_seq[0] = asoc->sending_seq;
3892235283Stuexen			asoc->last_base_tsnsent[1] = asoc->last_base_tsnsent[0];
3893235283Stuexen			asoc->last_base_tsnsent[0] = asoc->mapping_array_base_tsn;
3894235283Stuexen			sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL);
3895235283Stuexen			sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL);
3896235283Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
3897235283Stuexen			sctp_notify_stream_reset_tsn(stcb, asoc->sending_seq, (asoc->mapping_array_base_tsn + 1), 0);
3898163953Srrs		}
3899235283Stuexen		sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0],
3900235283Stuexen		    asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]);
3901163953Srrs		asoc->str_reset_seq_in++;
3902163953Srrs	} else if (asoc->str_reset_seq_in - 1 == seq) {
3903163953Srrs		sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0],
3904235064Stuexen		    asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]);
3905163953Srrs	} else if (asoc->str_reset_seq_in - 2 == seq) {
3906163953Srrs		sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[1],
3907235064Stuexen		    asoc->last_sending_seq[1], asoc->last_base_tsnsent[1]);
3908163953Srrs	} else {
3909235064Stuexen		sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
3910163953Srrs	}
3911163953Srrs	return (0);
3912163953Srrs}
3913163953Srrs
3914163953Srrsstatic void
3915163953Srrssctp_handle_str_reset_request_out(struct sctp_tcb *stcb,
3916163953Srrs    struct sctp_tmit_chunk *chk,
3917170992Srrs    struct sctp_stream_reset_out_request *req, int trunc)
3918163953Srrs{
3919163953Srrs	uint32_t seq, tsn;
3920163953Srrs	int number_entries, len;
3921163953Srrs	struct sctp_association *asoc = &stcb->asoc;
3922163953Srrs
3923163953Srrs	seq = ntohl(req->request_seq);
3924163953Srrs
3925163953Srrs	/* now if its not a duplicate we process it */
3926163953Srrs	if (asoc->str_reset_seq_in == seq) {
3927163953Srrs		len = ntohs(req->ph.param_length);
3928163953Srrs		number_entries = ((len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t));
3929163953Srrs		/*
3930163953Srrs		 * the sender is resetting, handle the list issue.. we must
3931163953Srrs		 * a) verify if we can do the reset, if so no problem b) If
3932163953Srrs		 * we can't do the reset we must copy the request. c) queue
3933163953Srrs		 * it, and setup the data in processor to trigger it off
3934163953Srrs		 * when needed and dequeue all the queued data.
3935163953Srrs		 */
3936163953Srrs		tsn = ntohl(req->send_reset_at_tsn);
3937163953Srrs
3938163953Srrs		/* move the reset action back one */
3939163953Srrs		asoc->last_reset_action[1] = asoc->last_reset_action[0];
3940235064Stuexen		if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) {
3941235064Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
3942235064Stuexen		} else if (trunc) {
3943235064Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
3944216825Stuexen		} else if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) {
3945163953Srrs			/* we can do it now */
3946163953Srrs			sctp_reset_in_stream(stcb, number_entries, req->list_of_streams);
3947235064Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
3948163953Srrs		} else {
3949163953Srrs			/*
3950163953Srrs			 * we must queue it up and thus wait for the TSN's
3951163953Srrs			 * to arrive that are at or before tsn
3952163953Srrs			 */
3953163953Srrs			struct sctp_stream_reset_list *liste;
3954163953Srrs			int siz;
3955163953Srrs
3956163953Srrs			siz = sizeof(struct sctp_stream_reset_list) + (number_entries * sizeof(uint16_t));
3957163953Srrs			SCTP_MALLOC(liste, struct sctp_stream_reset_list *,
3958170091Srrs			    siz, SCTP_M_STRESET);
3959163953Srrs			if (liste == NULL) {
3960163953Srrs				/* gak out of memory */
3961235064Stuexen				asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
3962235064Stuexen				sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
3963163953Srrs				return;
3964163953Srrs			}
3965294140Stuexen			liste->seq = seq;
3966163953Srrs			liste->tsn = tsn;
3967163953Srrs			liste->number_entries = number_entries;
3968240198Stuexen			memcpy(&liste->list_of_streams, req->list_of_streams, number_entries * sizeof(uint16_t));
3969163953Srrs			TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp);
3970294140Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_IN_PROGRESS;
3971163953Srrs		}
3972233660Srrs		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
3973163953Srrs		asoc->str_reset_seq_in++;
3974163953Srrs	} else if ((asoc->str_reset_seq_in - 1) == seq) {
3975163953Srrs		/*
3976163953Srrs		 * one seq back, just echo back last action since my
3977163953Srrs		 * response was lost.
3978163953Srrs		 */
3979163953Srrs		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
3980163953Srrs	} else if ((asoc->str_reset_seq_in - 2) == seq) {
3981163953Srrs		/*
3982163953Srrs		 * two seq back, just echo back last action since my
3983163953Srrs		 * response was lost.
3984163953Srrs		 */
3985163953Srrs		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
3986163953Srrs	} else {
3987235064Stuexen		sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
3988163953Srrs	}
3989163953Srrs}
3990163953Srrs
3991188854Srrsstatic void
3992188854Srrssctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk,
3993188854Srrs    struct sctp_stream_reset_add_strm *str_add)
3994188854Srrs{
3995188854Srrs	/*
3996188854Srrs	 * Peer is requesting to add more streams. If its within our
3997188854Srrs	 * max-streams we will allow it.
3998188854Srrs	 */
3999233660Srrs	uint32_t num_stream, i;
4000188854Srrs	uint32_t seq;
4001189121Srrs	struct sctp_association *asoc = &stcb->asoc;
4002216822Stuexen	struct sctp_queued_to_read *ctl, *nctl;
4003188854Srrs
4004188854Srrs	/* Get the number. */
4005188854Srrs	seq = ntohl(str_add->request_seq);
4006188854Srrs	num_stream = ntohs(str_add->number_of_streams);
4007188854Srrs	/* Now what would be the new total? */
4008189121Srrs	if (asoc->str_reset_seq_in == seq) {
4009189121Srrs		num_stream += stcb->asoc.streamincnt;
4010235064Stuexen		stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0];
4011235064Stuexen		if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) {
4012235064Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
4013235064Stuexen		} else if ((num_stream > stcb->asoc.max_inbound_streams) ||
4014233660Srrs		    (num_stream > 0xffff)) {
4015189121Srrs			/* We must reject it they ask for to many */
4016189121Srrs	denied:
4017235064Stuexen			stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
4018189121Srrs		} else {
4019189121Srrs			/* Ok, we can do that :-) */
4020189121Srrs			struct sctp_stream_in *oldstrm;
4021189121Srrs
4022189121Srrs			/* save off the old */
4023189121Srrs			oldstrm = stcb->asoc.strmin;
4024189121Srrs			SCTP_MALLOC(stcb->asoc.strmin, struct sctp_stream_in *,
4025189121Srrs			    (num_stream * sizeof(struct sctp_stream_in)),
4026189121Srrs			    SCTP_M_STRMI);
4027189121Srrs			if (stcb->asoc.strmin == NULL) {
4028189121Srrs				stcb->asoc.strmin = oldstrm;
4029189121Srrs				goto denied;
4030189121Srrs			}
4031189121Srrs			/* copy off the old data */
4032189121Srrs			for (i = 0; i < stcb->asoc.streamincnt; i++) {
4033189121Srrs				TAILQ_INIT(&stcb->asoc.strmin[i].inqueue);
4034189121Srrs				stcb->asoc.strmin[i].stream_no = i;
4035189121Srrs				stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered;
4036189121Srrs				stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started;
4037189121Srrs				/* now anything on those queues? */
4038216822Stuexen				TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next, nctl) {
4039189121Srrs					TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next);
4040189121Srrs					TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next);
4041189121Srrs				}
4042189121Srrs			}
4043189121Srrs			/* Init the new streams */
4044189121Srrs			for (i = stcb->asoc.streamincnt; i < num_stream; i++) {
4045189121Srrs				TAILQ_INIT(&stcb->asoc.strmin[i].inqueue);
4046189121Srrs				stcb->asoc.strmin[i].stream_no = i;
4047189121Srrs				stcb->asoc.strmin[i].last_sequence_delivered = 0xffff;
4048189121Srrs				stcb->asoc.strmin[i].delivery_started = 0;
4049189121Srrs			}
4050189121Srrs			SCTP_FREE(oldstrm, SCTP_M_STRMI);
4051189121Srrs			/* update the size */
4052189121Srrs			stcb->asoc.streamincnt = num_stream;
4053235064Stuexen			stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
4054233660Srrs			sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0);
4055189121Srrs		}
4056233660Srrs		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
4057233660Srrs		asoc->str_reset_seq_in++;
4058189121Srrs	} else if ((asoc->str_reset_seq_in - 1) == seq) {
4059189121Srrs		/*
4060189121Srrs		 * one seq back, just echo back last action since my
4061189121Srrs		 * response was lost.
4062189121Srrs		 */
4063189121Srrs		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
4064189121Srrs	} else if ((asoc->str_reset_seq_in - 2) == seq) {
4065189121Srrs		/*
4066189121Srrs		 * two seq back, just echo back last action since my
4067189121Srrs		 * response was lost.
4068189121Srrs		 */
4069189121Srrs		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
4070188854Srrs	} else {
4071235064Stuexen		sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
4072188854Srrs
4073188854Srrs	}
4074188854Srrs}
4075188854Srrs
4076233660Srrsstatic void
4077233660Srrssctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk,
4078233660Srrs    struct sctp_stream_reset_add_strm *str_add)
4079233660Srrs{
4080233660Srrs	/*
4081233660Srrs	 * Peer is requesting to add more streams. If its within our
4082233660Srrs	 * max-streams we will allow it.
4083233660Srrs	 */
4084233660Srrs	uint16_t num_stream;
4085233660Srrs	uint32_t seq;
4086233660Srrs	struct sctp_association *asoc = &stcb->asoc;
4087233660Srrs
4088233660Srrs	/* Get the number. */
4089233660Srrs	seq = ntohl(str_add->request_seq);
4090233660Srrs	num_stream = ntohs(str_add->number_of_streams);
4091233660Srrs	/* Now what would be the new total? */
4092233660Srrs	if (asoc->str_reset_seq_in == seq) {
4093235064Stuexen		stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0];
4094235064Stuexen		if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) {
4095235064Stuexen			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
4096235064Stuexen		} else if (stcb->asoc.stream_reset_outstanding) {
4097233660Srrs			/* We must reject it we have something pending */
4098235064Stuexen			stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS;
4099233660Srrs		} else {
4100233660Srrs			/* Ok, we can do that :-) */
4101233660Srrs			int mychk;
4102233660Srrs
4103233660Srrs			mychk = stcb->asoc.streamoutcnt;
4104233660Srrs			mychk += num_stream;
4105233660Srrs			if (mychk < 0x10000) {
4106235064Stuexen				stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
4107294140Stuexen				if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, num_stream, 0, 1)) {
4108235064Stuexen					stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
4109233660Srrs				}
4110233660Srrs			} else {
4111235064Stuexen				stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
4112233660Srrs			}
4113233660Srrs		}
4114233660Srrs		sctp_add_stream_reset_result(chk, seq, stcb->asoc.last_reset_action[0]);
4115233660Srrs		asoc->str_reset_seq_in++;
4116233660Srrs	} else if ((asoc->str_reset_seq_in - 1) == seq) {
4117233660Srrs		/*
4118233660Srrs		 * one seq back, just echo back last action since my
4119233660Srrs		 * response was lost.
4120233660Srrs		 */
4121233660Srrs		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
4122233660Srrs	} else if ((asoc->str_reset_seq_in - 2) == seq) {
4123233660Srrs		/*
4124233660Srrs		 * two seq back, just echo back last action since my
4125233660Srrs		 * response was lost.
4126233660Srrs		 */
4127233660Srrs		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
4128233660Srrs	} else {
4129235064Stuexen		sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
4130233660Srrs	}
4131233660Srrs}
4132233660Srrs
4133170992Srrs#ifdef __GNUC__
4134170992Srrs__attribute__((noinline))
4135170992Srrs#endif
4136170992Srrs	static int
4137170992Srrs	    sctp_handle_stream_reset(struct sctp_tcb *stcb, struct mbuf *m, int offset,
4138240198Stuexen        struct sctp_chunkhdr *ch_req)
4139163953Srrs{
4140277807Sdelphij	uint16_t remaining_length, param_len, ptype;
4141170992Srrs	struct sctp_paramhdr pstore;
4142170992Srrs	uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE];
4143233660Srrs	uint32_t seq = 0;
4144163953Srrs	int num_req = 0;
4145170992Srrs	int trunc = 0;
4146163953Srrs	struct sctp_tmit_chunk *chk;
4147163953Srrs	struct sctp_chunkhdr *ch;
4148163953Srrs	struct sctp_paramhdr *ph;
4149166675Srrs	int ret_code = 0;
4150166675Srrs	int num_param = 0;
4151163953Srrs
4152163953Srrs	/* now it may be a reset or a reset-response */
4153277807Sdelphij	remaining_length = ntohs(ch_req->chunk_length) - sizeof(struct sctp_chunkhdr);
4154163953Srrs
4155163953Srrs	/* setup for adding the response */
4156163953Srrs	sctp_alloc_a_chunk(stcb, chk);
4157163953Srrs	if (chk == NULL) {
4158163953Srrs		return (ret_code);
4159163953Srrs	}
4160273002Stuexen	chk->copy_by_ref = 0;
4161163953Srrs	chk->rec.chunk_id.id = SCTP_STREAM_RESET;
4162169208Srrs	chk->rec.chunk_id.can_take_data = 0;
4163273002Stuexen	chk->flags = 0;
4164163953Srrs	chk->asoc = &stcb->asoc;
4165163953Srrs	chk->no_fr_allowed = 0;
4166163953Srrs	chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr);
4167166023Srrs	chk->book_size_scale = 0;
4168243882Sglebius	chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
4169163953Srrs	if (chk->data == NULL) {
4170163953Srrsstrres_nochunk:
4171163953Srrs		if (chk->data) {
4172163953Srrs			sctp_m_freem(chk->data);
4173163953Srrs			chk->data = NULL;
4174163953Srrs		}
4175221627Stuexen		sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
4176163953Srrs		return (ret_code);
4177163953Srrs	}
4178165647Srrs	SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
4179163953Srrs
4180163953Srrs	/* setup chunk parameters */
4181163953Srrs	chk->sent = SCTP_DATAGRAM_UNSENT;
4182163953Srrs	chk->snd_count = 0;
4183224641Stuexen	chk->whoTo = NULL;
4184163953Srrs
4185163953Srrs	ch = mtod(chk->data, struct sctp_chunkhdr *);
4186163953Srrs	ch->chunk_type = SCTP_STREAM_RESET;
4187163953Srrs	ch->chunk_flags = 0;
4188163953Srrs	ch->chunk_length = htons(chk->send_size);
4189165647Srrs	SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size);
4190170992Srrs	offset += sizeof(struct sctp_chunkhdr);
4191277807Sdelphij	while (remaining_length >= sizeof(struct sctp_paramhdr)) {
4192170992Srrs		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(pstore), (uint8_t *) & pstore);
4193277807Sdelphij		if (ph == NULL) {
4194277807Sdelphij			/* TSNH */
4195170992Srrs			break;
4196277807Sdelphij		}
4197163953Srrs		param_len = ntohs(ph->param_length);
4198277807Sdelphij		if ((param_len > remaining_length) ||
4199277807Sdelphij		    (param_len < (sizeof(struct sctp_paramhdr) + sizeof(uint32_t)))) {
4200277807Sdelphij			/* bad parameter length */
4201163953Srrs			break;
4202163953Srrs		}
4203277807Sdelphij		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, sizeof(cstore)),
4204170992Srrs		    (uint8_t *) & cstore);
4205277807Sdelphij		if (ph == NULL) {
4206277807Sdelphij			/* TSNH */
4207277807Sdelphij			break;
4208277807Sdelphij		}
4209163953Srrs		ptype = ntohs(ph->param_type);
4210163953Srrs		num_param++;
4211277807Sdelphij		if (param_len > sizeof(cstore)) {
4212170992Srrs			trunc = 1;
4213170992Srrs		} else {
4214170992Srrs			trunc = 0;
4215170992Srrs		}
4216163953Srrs		if (num_param > SCTP_MAX_RESET_PARAMS) {
4217163953Srrs			/* hit the max of parameters already sorry.. */
4218163953Srrs			break;
4219163953Srrs		}
4220163953Srrs		if (ptype == SCTP_STR_RESET_OUT_REQUEST) {
4221163953Srrs			struct sctp_stream_reset_out_request *req_out;
4222163953Srrs
4223277807Sdelphij			if (param_len < sizeof(struct sctp_stream_reset_out_request)) {
4224277807Sdelphij				break;
4225277807Sdelphij			}
4226163953Srrs			req_out = (struct sctp_stream_reset_out_request *)ph;
4227163953Srrs			num_req++;
4228163953Srrs			if (stcb->asoc.stream_reset_outstanding) {
4229163953Srrs				seq = ntohl(req_out->response_seq);
4230163953Srrs				if (seq == stcb->asoc.str_reset_seq_out) {
4231163953Srrs					/* implicit ack */
4232235064Stuexen					(void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_RESULT_PERFORMED, NULL);
4233163953Srrs				}
4234163953Srrs			}
4235170992Srrs			sctp_handle_str_reset_request_out(stcb, chk, req_out, trunc);
4236233660Srrs		} else if (ptype == SCTP_STR_RESET_ADD_OUT_STREAMS) {
4237188854Srrs			struct sctp_stream_reset_add_strm *str_add;
4238188854Srrs
4239277807Sdelphij			if (param_len < sizeof(struct sctp_stream_reset_add_strm)) {
4240277807Sdelphij				break;
4241277807Sdelphij			}
4242188854Srrs			str_add = (struct sctp_stream_reset_add_strm *)ph;
4243188854Srrs			num_req++;
4244188854Srrs			sctp_handle_str_reset_add_strm(stcb, chk, str_add);
4245233660Srrs		} else if (ptype == SCTP_STR_RESET_ADD_IN_STREAMS) {
4246233660Srrs			struct sctp_stream_reset_add_strm *str_add;
4247233660Srrs
4248277807Sdelphij			if (param_len < sizeof(struct sctp_stream_reset_add_strm)) {
4249277807Sdelphij				break;
4250277807Sdelphij			}
4251233660Srrs			str_add = (struct sctp_stream_reset_add_strm *)ph;
4252233660Srrs			num_req++;
4253233660Srrs			sctp_handle_str_reset_add_out_strm(stcb, chk, str_add);
4254163953Srrs		} else if (ptype == SCTP_STR_RESET_IN_REQUEST) {
4255163953Srrs			struct sctp_stream_reset_in_request *req_in;
4256163953Srrs
4257163953Srrs			num_req++;
4258163953Srrs			req_in = (struct sctp_stream_reset_in_request *)ph;
4259170992Srrs			sctp_handle_str_reset_request_in(stcb, chk, req_in, trunc);
4260163953Srrs		} else if (ptype == SCTP_STR_RESET_TSN_REQUEST) {
4261163953Srrs			struct sctp_stream_reset_tsn_request *req_tsn;
4262163953Srrs
4263163953Srrs			num_req++;
4264163953Srrs			req_tsn = (struct sctp_stream_reset_tsn_request *)ph;
4265163953Srrs			if (sctp_handle_str_reset_request_tsn(stcb, chk, req_tsn)) {
4266163953Srrs				ret_code = 1;
4267163953Srrs				goto strres_nochunk;
4268163953Srrs			}
4269163953Srrs			/* no more */
4270163953Srrs			break;
4271163953Srrs		} else if (ptype == SCTP_STR_RESET_RESPONSE) {
4272163953Srrs			struct sctp_stream_reset_response *resp;
4273163953Srrs			uint32_t result;
4274163953Srrs
4275277807Sdelphij			if (param_len < sizeof(struct sctp_stream_reset_response)) {
4276277807Sdelphij				break;
4277277807Sdelphij			}
4278163953Srrs			resp = (struct sctp_stream_reset_response *)ph;
4279163953Srrs			seq = ntohl(resp->response_seq);
4280163953Srrs			result = ntohl(resp->result);
4281163953Srrs			if (sctp_handle_stream_reset_response(stcb, seq, result, resp)) {
4282163953Srrs				ret_code = 1;
4283163953Srrs				goto strres_nochunk;
4284163953Srrs			}
4285163953Srrs		} else {
4286163953Srrs			break;
4287163953Srrs		}
4288170992Srrs		offset += SCTP_SIZE32(param_len);
4289277807Sdelphij		if (remaining_length >= SCTP_SIZE32(param_len)) {
4290277807Sdelphij			remaining_length -= SCTP_SIZE32(param_len);
4291277807Sdelphij		} else {
4292277807Sdelphij			remaining_length = 0;
4293277807Sdelphij		}
4294163953Srrs	}
4295163953Srrs	if (num_req == 0) {
4296163953Srrs		/* we have no response free the stuff */
4297163953Srrs		goto strres_nochunk;
4298163953Srrs	}
4299163953Srrs	/* ok we have a chunk to link in */
4300163953Srrs	TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue,
4301163953Srrs	    chk,
4302163953Srrs	    sctp_next);
4303163953Srrs	stcb->asoc.ctrl_queue_cnt++;
4304163953Srrs	return (ret_code);
4305163953Srrs}
4306163953Srrs
4307163953Srrs/*
4308163953Srrs * Handle a router or endpoints report of a packet loss, there are two ways
4309163953Srrs * to handle this, either we get the whole packet and must disect it
4310163953Srrs * ourselves (possibly with truncation and or corruption) or it is a summary
4311163953Srrs * from a middle box that did the disectting for us.
4312163953Srrs */
4313163953Srrsstatic void
4314163953Srrssctp_handle_packet_dropped(struct sctp_pktdrop_chunk *cp,
4315170781Srrs    struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t limit)
4316163953Srrs{
4317163953Srrs	uint32_t bottle_bw, on_queue;
4318163953Srrs	uint16_t trunc_len;
4319163953Srrs	unsigned int chlen;
4320163953Srrs	unsigned int at;
4321163953Srrs	struct sctp_chunk_desc desc;
4322163953Srrs	struct sctp_chunkhdr *ch;
4323163953Srrs
4324163953Srrs	chlen = ntohs(cp->ch.chunk_length);
4325163953Srrs	chlen -= sizeof(struct sctp_pktdrop_chunk);
4326163953Srrs	/* XXX possible chlen underflow */
4327163953Srrs	if (chlen == 0) {
4328163953Srrs		ch = NULL;
4329163953Srrs		if (cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)
4330163953Srrs			SCTP_STAT_INCR(sctps_pdrpbwrpt);
4331163953Srrs	} else {
4332163953Srrs		ch = (struct sctp_chunkhdr *)(cp->data + sizeof(struct sctphdr));
4333163953Srrs		chlen -= sizeof(struct sctphdr);
4334163953Srrs		/* XXX possible chlen underflow */
4335163953Srrs		memset(&desc, 0, sizeof(desc));
4336163953Srrs	}
4337163953Srrs	trunc_len = (uint16_t) ntohs(cp->trunc_len);
4338170781Srrs	if (trunc_len > limit) {
4339170781Srrs		trunc_len = limit;
4340170781Srrs	}
4341163953Srrs	/* now the chunks themselves */
4342163953Srrs	while ((ch != NULL) && (chlen >= sizeof(struct sctp_chunkhdr))) {
4343163953Srrs		desc.chunk_type = ch->chunk_type;
4344163953Srrs		/* get amount we need to move */
4345163953Srrs		at = ntohs(ch->chunk_length);
4346163953Srrs		if (at < sizeof(struct sctp_chunkhdr)) {
4347163953Srrs			/* corrupt chunk, maybe at the end? */
4348163953Srrs			SCTP_STAT_INCR(sctps_pdrpcrupt);
4349163953Srrs			break;
4350163953Srrs		}
4351163953Srrs		if (trunc_len == 0) {
4352163953Srrs			/* we are supposed to have all of it */
4353163953Srrs			if (at > chlen) {
4354163953Srrs				/* corrupt skip it */
4355163953Srrs				SCTP_STAT_INCR(sctps_pdrpcrupt);
4356163953Srrs				break;
4357163953Srrs			}
4358163953Srrs		} else {
4359163953Srrs			/* is there enough of it left ? */
4360163953Srrs			if (desc.chunk_type == SCTP_DATA) {
4361163953Srrs				if (chlen < (sizeof(struct sctp_data_chunk) +
4362163953Srrs				    sizeof(desc.data_bytes))) {
4363163953Srrs					break;
4364163953Srrs				}
4365163953Srrs			} else {
4366163953Srrs				if (chlen < sizeof(struct sctp_chunkhdr)) {
4367163953Srrs					break;
4368163953Srrs				}
4369163953Srrs			}
4370163953Srrs		}
4371163953Srrs		if (desc.chunk_type == SCTP_DATA) {
4372163953Srrs			/* can we get out the tsn? */
4373163953Srrs			if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX))
4374163953Srrs				SCTP_STAT_INCR(sctps_pdrpmbda);
4375163953Srrs
4376163953Srrs			if (chlen >= (sizeof(struct sctp_data_chunk) + sizeof(uint32_t))) {
4377163953Srrs				/* yep */
4378163953Srrs				struct sctp_data_chunk *dcp;
4379163953Srrs				uint8_t *ddp;
4380163953Srrs				unsigned int iii;
4381163953Srrs
4382163953Srrs				dcp = (struct sctp_data_chunk *)ch;
4383163953Srrs				ddp = (uint8_t *) (dcp + 1);
4384163953Srrs				for (iii = 0; iii < sizeof(desc.data_bytes); iii++) {
4385163953Srrs					desc.data_bytes[iii] = ddp[iii];
4386163953Srrs				}
4387163953Srrs				desc.tsn_ifany = dcp->dp.tsn;
4388163953Srrs			} else {
4389163953Srrs				/* nope we are done. */
4390163953Srrs				SCTP_STAT_INCR(sctps_pdrpnedat);
4391163953Srrs				break;
4392163953Srrs			}
4393163953Srrs		} else {
4394163953Srrs			if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX))
4395163953Srrs				SCTP_STAT_INCR(sctps_pdrpmbct);
4396163953Srrs		}
4397163953Srrs
4398163953Srrs		if (process_chunk_drop(stcb, &desc, net, cp->ch.chunk_flags)) {
4399163953Srrs			SCTP_STAT_INCR(sctps_pdrppdbrk);
4400163953Srrs			break;
4401163953Srrs		}
4402163953Srrs		if (SCTP_SIZE32(at) > chlen) {
4403163953Srrs			break;
4404163953Srrs		}
4405163953Srrs		chlen -= SCTP_SIZE32(at);
4406163953Srrs		if (chlen < sizeof(struct sctp_chunkhdr)) {
4407163953Srrs			/* done, none left */
4408163953Srrs			break;
4409163953Srrs		}
4410163953Srrs		ch = (struct sctp_chunkhdr *)((caddr_t)ch + SCTP_SIZE32(at));
4411163953Srrs	}
4412163953Srrs	/* Now update any rwnd --- possibly */
4413163953Srrs	if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) == 0) {
4414163953Srrs		/* From a peer, we get a rwnd report */
4415163953Srrs		uint32_t a_rwnd;
4416163953Srrs
4417163953Srrs		SCTP_STAT_INCR(sctps_pdrpfehos);
4418163953Srrs
4419163953Srrs		bottle_bw = ntohl(cp->bottle_bw);
4420163953Srrs		on_queue = ntohl(cp->current_onq);
4421163953Srrs		if (bottle_bw && on_queue) {
4422163953Srrs			/* a rwnd report is in here */
4423163953Srrs			if (bottle_bw > on_queue)
4424163953Srrs				a_rwnd = bottle_bw - on_queue;
4425163953Srrs			else
4426163953Srrs				a_rwnd = 0;
4427163953Srrs
4428163953Srrs			if (a_rwnd == 0)
4429163953Srrs				stcb->asoc.peers_rwnd = 0;
4430163953Srrs			else {
4431163953Srrs				if (a_rwnd > stcb->asoc.total_flight) {
4432163953Srrs					stcb->asoc.peers_rwnd =
4433163953Srrs					    a_rwnd - stcb->asoc.total_flight;
4434163953Srrs				} else {
4435163953Srrs					stcb->asoc.peers_rwnd = 0;
4436163953Srrs				}
4437163953Srrs				if (stcb->asoc.peers_rwnd <
4438163953Srrs				    stcb->sctp_ep->sctp_ep.sctp_sws_sender) {
4439163953Srrs					/* SWS sender side engages */
4440163953Srrs					stcb->asoc.peers_rwnd = 0;
4441163953Srrs				}
4442163953Srrs			}
4443163953Srrs		}
4444163953Srrs	} else {
4445163953Srrs		SCTP_STAT_INCR(sctps_pdrpfmbox);
4446163953Srrs	}
4447163953Srrs
4448163953Srrs	/* now middle boxes in sat networks get a cwnd bump */
4449163953Srrs	if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) &&
4450163953Srrs	    (stcb->asoc.sat_t3_loss_recovery == 0) &&
4451163953Srrs	    (stcb->asoc.sat_network)) {
4452163953Srrs		/*
4453163953Srrs		 * This is debateable but for sat networks it makes sense
4454163953Srrs		 * Note if a T3 timer has went off, we will prohibit any
4455163953Srrs		 * changes to cwnd until we exit the t3 loss recovery.
4456163953Srrs		 */
4457171440Srrs		stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped(stcb,
4458171440Srrs		    net, cp, &bottle_bw, &on_queue);
4459163953Srrs	}
4460163953Srrs}
4461163953Srrs
4462163953Srrs/*
4463163953Srrs * handles all control chunks in a packet inputs: - m: mbuf chain, assumed to
4464163953Srrs * still contain IP/SCTP header - stcb: is the tcb found for this packet -
4465163953Srrs * offset: offset into the mbuf chain to first chunkhdr - length: is the
4466163953Srrs * length of the complete packet outputs: - length: modified to remaining
4467163953Srrs * length after control processing - netp: modified to new sctp_nets after
4468163953Srrs * cookie-echo processing - return NULL to discard the packet (ie. no asoc,
4469163953Srrs * bad packet,...) otherwise return the tcb for this packet
4470163953Srrs */
4471170099Srrs#ifdef __GNUC__
4472170099Srrs__attribute__((noinline))
4473170099Srrs#endif
4474170099Srrs	static struct sctp_tcb *
4475170099Srrs	         sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
4476237715Stuexen             struct sockaddr *src, struct sockaddr *dst,
4477170099Srrs             struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp,
4478170099Srrs             struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen,
4479284633Stuexen             uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum,
4480179157Srrs             uint32_t vrf_id, uint16_t port)
4481163953Srrs{
4482163953Srrs	struct sctp_association *asoc;
4483267723Stuexen	struct mbuf *op_err;
4484267723Stuexen	char msg[SCTP_DIAG_INFO_LEN];
4485163953Srrs	uint32_t vtag_in;
4486163953Srrs	int num_chunks = 0;	/* number of control chunks processed */
4487170140Srrs	uint32_t chk_length;
4488163953Srrs	int ret;
4489168299Srrs	int abort_no_unlock = 0;
4490218186Srrs	int ecne_seen = 0;
4491163953Srrs
4492163953Srrs	/*
4493163953Srrs	 * How big should this be, and should it be alloc'd? Lets try the
4494163953Srrs	 * d-mtu-ceiling for now (2k) and that should hopefully work ...
4495163953Srrs	 * until we get into jumbo grams and such..
4496163953Srrs	 */
4497166675Srrs	uint8_t chunk_buf[SCTP_CHUNK_BUFFER_SIZE];
4498163953Srrs	struct sctp_tcb *locked_tcb = stcb;
4499163953Srrs	int got_auth = 0;
4500163953Srrs	uint32_t auth_offset = 0, auth_len = 0;
4501163953Srrs	int auth_skipped = 0;
4502171990Srrs	int asconf_cnt = 0;
4503163953Srrs
4504237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4505172090Srrs	struct socket *so;
4506172090Srrs
4507172090Srrs#endif
4508172090Srrs
4509169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n",
4510240148Stuexen	    iphlen, *offset, length, (void *)stcb);
4511163953Srrs
4512163953Srrs	/* validate chunk header length... */
4513163953Srrs	if (ntohs(ch->chunk_length) < sizeof(*ch)) {
4514170056Srrs		SCTPDBG(SCTP_DEBUG_INPUT1, "Invalid header length %d\n",
4515170056Srrs		    ntohs(ch->chunk_length));
4516170091Srrs		if (locked_tcb) {
4517170091Srrs			SCTP_TCB_UNLOCK(locked_tcb);
4518170091Srrs		}
4519163953Srrs		return (NULL);
4520163953Srrs	}
4521163953Srrs	/*
4522163953Srrs	 * validate the verification tag
4523163953Srrs	 */
4524163953Srrs	vtag_in = ntohl(sh->v_tag);
4525163953Srrs
4526165220Srrs	if (locked_tcb) {
4527165220Srrs		SCTP_TCB_LOCK_ASSERT(locked_tcb);
4528165220Srrs	}
4529163953Srrs	if (ch->chunk_type == SCTP_INITIATION) {
4530170056Srrs		SCTPDBG(SCTP_DEBUG_INPUT1, "Its an INIT of len:%d vtag:%x\n",
4531170056Srrs		    ntohs(ch->chunk_length), vtag_in);
4532163953Srrs		if (vtag_in != 0) {
4533163953Srrs			/* protocol error- silently discard... */
4534163953Srrs			SCTP_STAT_INCR(sctps_badvtag);
4535169378Srrs			if (locked_tcb) {
4536163953Srrs				SCTP_TCB_UNLOCK(locked_tcb);
4537169378Srrs			}
4538163953Srrs			return (NULL);
4539163953Srrs		}
4540163953Srrs	} else if (ch->chunk_type != SCTP_COOKIE_ECHO) {
4541163953Srrs		/*
4542163953Srrs		 * If there is no stcb, skip the AUTH chunk and process
4543163953Srrs		 * later after a stcb is found (to validate the lookup was
4544163953Srrs		 * valid.
4545163953Srrs		 */
4546163953Srrs		if ((ch->chunk_type == SCTP_AUTHENTICATION) &&
4547179783Srrs		    (stcb == NULL) &&
4548270362Stuexen		    (inp->auth_supported == 1)) {
4549163953Srrs			/* save this chunk for later processing */
4550163953Srrs			auth_skipped = 1;
4551163953Srrs			auth_offset = *offset;
4552163953Srrs			auth_len = ntohs(ch->chunk_length);
4553163953Srrs
4554163953Srrs			/* (temporarily) move past this chunk */
4555163953Srrs			*offset += SCTP_SIZE32(auth_len);
4556163953Srrs			if (*offset >= length) {
4557163953Srrs				/* no more data left in the mbuf chain */
4558163953Srrs				*offset = length;
4559170091Srrs				if (locked_tcb) {
4560170091Srrs					SCTP_TCB_UNLOCK(locked_tcb);
4561170091Srrs				}
4562163953Srrs				return (NULL);
4563163953Srrs			}
4564163953Srrs			ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
4565163953Srrs			    sizeof(struct sctp_chunkhdr), chunk_buf);
4566163953Srrs		}
4567169420Srrs		if (ch == NULL) {
4568169420Srrs			/* Help */
4569169420Srrs			*offset = length;
4570170091Srrs			if (locked_tcb) {
4571170091Srrs				SCTP_TCB_UNLOCK(locked_tcb);
4572170091Srrs			}
4573169420Srrs			return (NULL);
4574169420Srrs		}
4575163953Srrs		if (ch->chunk_type == SCTP_COOKIE_ECHO) {
4576163953Srrs			goto process_control_chunks;
4577163953Srrs		}
4578163953Srrs		/*
4579163953Srrs		 * first check if it's an ASCONF with an unknown src addr we
4580163953Srrs		 * need to look inside to find the association
4581163953Srrs		 */
4582163953Srrs		if (ch->chunk_type == SCTP_ASCONF && stcb == NULL) {
4583171990Srrs			struct sctp_chunkhdr *asconf_ch = ch;
4584171990Srrs			uint32_t asconf_offset = 0, asconf_len = 0;
4585171990Srrs
4586163953Srrs			/* inp's refcount may be reduced */
4587163953Srrs			SCTP_INP_INCR_REF(inp);
4588163953Srrs
4589171990Srrs			asconf_offset = *offset;
4590171990Srrs			do {
4591171990Srrs				asconf_len = ntohs(asconf_ch->chunk_length);
4592171990Srrs				if (asconf_len < sizeof(struct sctp_asconf_paramhdr))
4593171990Srrs					break;
4594228653Stuexen				stcb = sctp_findassociation_ep_asconf(m,
4595237715Stuexen				    *offset,
4596237715Stuexen				    dst,
4597237715Stuexen				    sh, &inp, netp, vrf_id);
4598171990Srrs				if (stcb != NULL)
4599171990Srrs					break;
4600171990Srrs				asconf_offset += SCTP_SIZE32(asconf_len);
4601171990Srrs				asconf_ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, asconf_offset,
4602171990Srrs				    sizeof(struct sctp_chunkhdr), chunk_buf);
4603171990Srrs			} while (asconf_ch != NULL && asconf_ch->chunk_type == SCTP_ASCONF);
4604163953Srrs			if (stcb == NULL) {
4605163953Srrs				/*
4606163953Srrs				 * reduce inp's refcount if not reduced in
4607163953Srrs				 * sctp_findassociation_ep_asconf().
4608163953Srrs				 */
4609163953Srrs				SCTP_INP_DECR_REF(inp);
4610171990Srrs			} else {
4611171990Srrs				locked_tcb = stcb;
4612163953Srrs			}
4613171990Srrs
4614163953Srrs			/* now go back and verify any auth chunk to be sure */
4615163953Srrs			if (auth_skipped && (stcb != NULL)) {
4616163953Srrs				struct sctp_auth_chunk *auth;
4617163953Srrs
4618163953Srrs				auth = (struct sctp_auth_chunk *)
4619163953Srrs				    sctp_m_getptr(m, auth_offset,
4620163953Srrs				    auth_len, chunk_buf);
4621163953Srrs				got_auth = 1;
4622163953Srrs				auth_skipped = 0;
4623169420Srrs				if ((auth == NULL) || sctp_handle_auth(stcb, auth, m,
4624163953Srrs				    auth_offset)) {
4625163953Srrs					/* auth HMAC failed so dump it */
4626163953Srrs					*offset = length;
4627170091Srrs					if (locked_tcb) {
4628170091Srrs						SCTP_TCB_UNLOCK(locked_tcb);
4629170091Srrs					}
4630163953Srrs					return (NULL);
4631163953Srrs				} else {
4632163953Srrs					/* remaining chunks are HMAC checked */
4633163953Srrs					stcb->asoc.authenticated = 1;
4634163953Srrs				}
4635163953Srrs			}
4636163953Srrs		}
4637163953Srrs		if (stcb == NULL) {
4638294174Stuexen			snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
4639267723Stuexen			op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
4640267723Stuexen			    msg);
4641163953Srrs			/* no association, so it's out of the blue... */
4642267723Stuexen			sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err,
4643284633Stuexen			    mflowtype, mflowid, inp->fibnum,
4644179157Srrs			    vrf_id, port);
4645163953Srrs			*offset = length;
4646169378Srrs			if (locked_tcb) {
4647163953Srrs				SCTP_TCB_UNLOCK(locked_tcb);
4648169378Srrs			}
4649163953Srrs			return (NULL);
4650163953Srrs		}
4651163953Srrs		asoc = &stcb->asoc;
4652163953Srrs		/* ABORT and SHUTDOWN can use either v_tag... */
4653163953Srrs		if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) ||
4654163953Srrs		    (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) ||
4655163953Srrs		    (ch->chunk_type == SCTP_PACKET_DROPPED)) {
4656252718Stuexen			/* Take the T-bit always into account. */
4657252718Stuexen			if ((((ch->chunk_flags & SCTP_HAD_NO_TCB) == 0) &&
4658252718Stuexen			    (vtag_in == asoc->my_vtag)) ||
4659252718Stuexen			    (((ch->chunk_flags & SCTP_HAD_NO_TCB) == SCTP_HAD_NO_TCB) &&
4660163953Srrs			    (vtag_in == asoc->peer_vtag))) {
4661163953Srrs				/* this is valid */
4662163953Srrs			} else {
4663163953Srrs				/* drop this packet... */
4664163953Srrs				SCTP_STAT_INCR(sctps_badvtag);
4665169378Srrs				if (locked_tcb) {
4666163953Srrs					SCTP_TCB_UNLOCK(locked_tcb);
4667169378Srrs				}
4668163953Srrs				return (NULL);
4669163953Srrs			}
4670163953Srrs		} else if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
4671163953Srrs			if (vtag_in != asoc->my_vtag) {
4672163953Srrs				/*
4673163953Srrs				 * this could be a stale SHUTDOWN-ACK or the
4674163953Srrs				 * peer never got the SHUTDOWN-COMPLETE and
4675163953Srrs				 * is still hung; we have started a new asoc
4676163953Srrs				 * but it won't complete until the shutdown
4677163953Srrs				 * is completed
4678163953Srrs				 */
4679169378Srrs				if (locked_tcb) {
4680163953Srrs					SCTP_TCB_UNLOCK(locked_tcb);
4681169378Srrs				}
4682294174Stuexen				snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
4683267723Stuexen				op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
4684267723Stuexen				    msg);
4685237715Stuexen				sctp_handle_ootb(m, iphlen, *offset, src, dst,
4686267723Stuexen				    sh, inp, op_err,
4687284633Stuexen				    mflowtype, mflowid, fibnum,
4688236450Stuexen				    vrf_id, port);
4689163953Srrs				return (NULL);
4690163953Srrs			}
4691163953Srrs		} else {
4692163953Srrs			/* for all other chunks, vtag must match */
4693163953Srrs			if (vtag_in != asoc->my_vtag) {
4694163953Srrs				/* invalid vtag... */
4695169420Srrs				SCTPDBG(SCTP_DEBUG_INPUT3,
4696169420Srrs				    "invalid vtag: %xh, expect %xh\n",
4697169420Srrs				    vtag_in, asoc->my_vtag);
4698163953Srrs				SCTP_STAT_INCR(sctps_badvtag);
4699169378Srrs				if (locked_tcb) {
4700163953Srrs					SCTP_TCB_UNLOCK(locked_tcb);
4701169378Srrs				}
4702163953Srrs				*offset = length;
4703163953Srrs				return (NULL);
4704163953Srrs			}
4705163953Srrs		}
4706163953Srrs	}			/* end if !SCTP_COOKIE_ECHO */
4707163953Srrs	/*
4708163953Srrs	 * process all control chunks...
4709163953Srrs	 */
4710163953Srrs	if (((ch->chunk_type == SCTP_SELECTIVE_ACK) ||
4711185694Srrs	    (ch->chunk_type == SCTP_NR_SELECTIVE_ACK) ||
4712163953Srrs	    (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) &&
4713163953Srrs	    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
4714163953Srrs		/* implied cookie-ack.. we must have lost the ack */
4715179783Srrs		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
4716171943Srrs			sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
4717171943Srrs			    stcb->asoc.overall_error_count,
4718171943Srrs			    0,
4719171943Srrs			    SCTP_FROM_SCTP_INPUT,
4720171943Srrs			    __LINE__);
4721171943Srrs		}
4722163953Srrs		stcb->asoc.overall_error_count = 0;
4723163953Srrs		sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb,
4724163953Srrs		    *netp);
4725163953Srrs	}
4726163953Srrsprocess_control_chunks:
4727163953Srrs	while (IS_SCTP_CONTROL(ch)) {
4728163953Srrs		/* validate chunk length */
4729163953Srrs		chk_length = ntohs(ch->chunk_length);
4730169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_process_control: processing a chunk type=%u, len=%u\n",
4731169420Srrs		    ch->chunk_type, chk_length);
4732170744Srrs		SCTP_LTRACE_CHK(inp, stcb, ch->chunk_type, chk_length);
4733170140Srrs		if (chk_length < sizeof(*ch) ||
4734170140Srrs		    (*offset + (int)chk_length) > length) {
4735163953Srrs			*offset = length;
4736169378Srrs			if (locked_tcb) {
4737163953Srrs				SCTP_TCB_UNLOCK(locked_tcb);
4738169378Srrs			}
4739163953Srrs			return (NULL);
4740163953Srrs		}
4741163953Srrs		SCTP_STAT_INCR_COUNTER64(sctps_incontrolchunks);
4742163953Srrs		/*
4743163953Srrs		 * INIT-ACK only gets the init ack "header" portion only
4744163953Srrs		 * because we don't have to process the peer's COOKIE. All
4745163953Srrs		 * others get a complete chunk.
4746163953Srrs		 */
4747169208Srrs		if ((ch->chunk_type == SCTP_INITIATION_ACK) ||
4748169208Srrs		    (ch->chunk_type == SCTP_INITIATION)) {
4749163953Srrs			/* get an init-ack chunk */
4750163953Srrs			ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
4751163953Srrs			    sizeof(struct sctp_init_ack_chunk), chunk_buf);
4752163953Srrs			if (ch == NULL) {
4753163953Srrs				*offset = length;
4754169378Srrs				if (locked_tcb) {
4755163953Srrs					SCTP_TCB_UNLOCK(locked_tcb);
4756169378Srrs				}
4757163953Srrs				return (NULL);
4758163953Srrs			}
4759170642Srrs		} else {
4760170786Srrs			/* For cookies and all other chunks. */
4761169208Srrs			if (chk_length > sizeof(chunk_buf)) {
4762169208Srrs				/*
4763169208Srrs				 * use just the size of the chunk buffer so
4764170642Srrs				 * the front part of our chunks fit in
4765170642Srrs				 * contiguous space up to the chunk buffer
4766170642Srrs				 * size (508 bytes). For chunks that need to
4767170786Srrs				 * get more than that they must use the
4768170642Srrs				 * sctp_m_getptr() function or other means
4769170786Srrs				 * (e.g. know how to parse mbuf chains).
4770170786Srrs				 * Cookies do this already.
4771169208Srrs				 */
4772169208Srrs				ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
4773169208Srrs				    (sizeof(chunk_buf) - 4),
4774169208Srrs				    chunk_buf);
4775169208Srrs				if (ch == NULL) {
4776169208Srrs					*offset = length;
4777169378Srrs					if (locked_tcb) {
4778169208Srrs						SCTP_TCB_UNLOCK(locked_tcb);
4779169378Srrs					}
4780169208Srrs					return (NULL);
4781169208Srrs				}
4782169208Srrs			} else {
4783169208Srrs				/* We can fit it all */
4784170642Srrs				ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
4785170642Srrs				    chk_length, chunk_buf);
4786170642Srrs				if (ch == NULL) {
4787170642Srrs					SCTP_PRINTF("sctp_process_control: Can't get the all data....\n");
4788170642Srrs					*offset = length;
4789170642Srrs					if (locked_tcb) {
4790170642Srrs						SCTP_TCB_UNLOCK(locked_tcb);
4791169208Srrs					}
4792170642Srrs					return (NULL);
4793163953Srrs				}
4794163953Srrs			}
4795163953Srrs		}
4796163953Srrs		num_chunks++;
4797163953Srrs		/* Save off the last place we got a control from */
4798163953Srrs		if (stcb != NULL) {
4799169420Srrs			if (((netp != NULL) && (*netp != NULL)) || (ch->chunk_type == SCTP_ASCONF)) {
4800163953Srrs				/*
4801163953Srrs				 * allow last_control to be NULL if
4802163953Srrs				 * ASCONF... ASCONF processing will find the
4803163953Srrs				 * right net later
4804163953Srrs				 */
4805169420Srrs				if ((netp != NULL) && (*netp != NULL))
4806169420Srrs					stcb->asoc.last_control_chunk_from = *netp;
4807163953Srrs			}
4808163953Srrs		}
4809163953Srrs#ifdef SCTP_AUDITING_ENABLED
4810163953Srrs		sctp_audit_log(0xB0, ch->chunk_type);
4811163953Srrs#endif
4812163953Srrs
4813163953Srrs		/* check to see if this chunk required auth, but isn't */
4814179783Srrs		if ((stcb != NULL) &&
4815270362Stuexen		    (stcb->asoc.auth_supported == 1) &&
4816179783Srrs		    sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) &&
4817163953Srrs		    !stcb->asoc.authenticated) {
4818163953Srrs			/* "silently" ignore */
4819163953Srrs			SCTP_STAT_INCR(sctps_recvauthmissing);
4820163953Srrs			goto next_chunk;
4821163953Srrs		}
4822163953Srrs		switch (ch->chunk_type) {
4823163953Srrs		case SCTP_INITIATION:
4824169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT\n");
4825229774Stuexen			/* The INIT chunk must be the only chunk. */
4826229774Stuexen			if ((num_chunks > 1) ||
4827229775Stuexen			    (length - *offset > (int)SCTP_SIZE32(chk_length))) {
4828294155Stuexen				/* RFC 4960 requires that no ABORT is sent */
4829163953Srrs				*offset = length;
4830294155Stuexen				if (locked_tcb) {
4831294155Stuexen					SCTP_TCB_UNLOCK(locked_tcb);
4832294155Stuexen				}
4833163953Srrs				return (NULL);
4834163953Srrs			}
4835229774Stuexen			/* Honor our resource limit. */
4836229774Stuexen			if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) {
4837267723Stuexen				op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
4838237715Stuexen				sctp_abort_association(inp, stcb, m, iphlen,
4839237715Stuexen				    src, dst, sh, op_err,
4840281955Shiren				    mflowtype, mflowid,
4841237049Stuexen				    vrf_id, port);
4842163953Srrs				*offset = length;
4843163953Srrs				return (NULL);
4844163953Srrs			}
4845237715Stuexen			sctp_handle_init(m, iphlen, *offset, src, dst, sh,
4846229774Stuexen			    (struct sctp_init_chunk *)ch, inp,
4847295208Stuexen			    stcb, *netp, &abort_no_unlock,
4848281955Shiren			    mflowtype, mflowid,
4849237049Stuexen			    vrf_id, port);
4850163953Srrs			*offset = length;
4851229774Stuexen			if ((!abort_no_unlock) && (locked_tcb)) {
4852163953Srrs				SCTP_TCB_UNLOCK(locked_tcb);
4853169378Srrs			}
4854163953Srrs			return (NULL);
4855163953Srrs			break;
4856170642Srrs		case SCTP_PAD_CHUNK:
4857170642Srrs			break;
4858163953Srrs		case SCTP_INITIATION_ACK:
4859169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n");
4860163953Srrs			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
4861163953Srrs				/* We are not interested anymore */
4862163953Srrs				if ((stcb) && (stcb->asoc.total_output_queue_size)) {
4863163953Srrs					;
4864163953Srrs				} else {
4865296052Stuexen					if ((locked_tcb != NULL) && (locked_tcb != stcb)) {
4866208876Srrs						/* Very unlikely */
4867163953Srrs						SCTP_TCB_UNLOCK(locked_tcb);
4868169378Srrs					}
4869163953Srrs					*offset = length;
4870163953Srrs					if (stcb) {
4871237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4872172090Srrs						so = SCTP_INP_SO(inp);
4873172090Srrs						atomic_add_int(&stcb->asoc.refcnt, 1);
4874172090Srrs						SCTP_TCB_UNLOCK(stcb);
4875172090Srrs						SCTP_SOCKET_LOCK(so, 1);
4876172090Srrs						SCTP_TCB_LOCK(stcb);
4877172090Srrs						atomic_subtract_int(&stcb->asoc.refcnt, 1);
4878172090Srrs#endif
4879283822Stuexen						(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
4880283822Stuexen						    SCTP_FROM_SCTP_INPUT + SCTP_LOC_29);
4881237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4882172090Srrs						SCTP_SOCKET_UNLOCK(so, 1);
4883172090Srrs#endif
4884163953Srrs					}
4885163953Srrs					return (NULL);
4886163953Srrs				}
4887163953Srrs			}
4888229775Stuexen			/* The INIT-ACK chunk must be the only chunk. */
4889163953Srrs			if ((num_chunks > 1) ||
4890229775Stuexen			    (length - *offset > (int)SCTP_SIZE32(chk_length))) {
4891163953Srrs				*offset = length;
4892169378Srrs				if (locked_tcb) {
4893163953Srrs					SCTP_TCB_UNLOCK(locked_tcb);
4894169378Srrs				}
4895163953Srrs				return (NULL);
4896163953Srrs			}
4897169420Srrs			if ((netp) && (*netp)) {
4898237715Stuexen				ret = sctp_handle_init_ack(m, iphlen, *offset,
4899237715Stuexen				    src, dst, sh,
4900237049Stuexen				    (struct sctp_init_ack_chunk *)ch,
4901237049Stuexen				    stcb, *netp,
4902237049Stuexen				    &abort_no_unlock,
4903281955Shiren				    mflowtype, mflowid,
4904237049Stuexen				    vrf_id);
4905169420Srrs			} else {
4906169420Srrs				ret = -1;
4907169420Srrs			}
4908229774Stuexen			*offset = length;
4909229774Stuexen			if (abort_no_unlock) {
4910229774Stuexen				return (NULL);
4911229774Stuexen			}
4912163953Srrs			/*
4913163953Srrs			 * Special case, I must call the output routine to
4914163953Srrs			 * get the cookie echoed
4915163953Srrs			 */
4916229774Stuexen			if ((stcb != NULL) && (ret == 0)) {
4917172090Srrs				sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
4918229774Stuexen			}
4919169378Srrs			if (locked_tcb) {
4920163953Srrs				SCTP_TCB_UNLOCK(locked_tcb);
4921169378Srrs			}
4922163953Srrs			return (NULL);
4923163953Srrs			break;
4924163953Srrs		case SCTP_SELECTIVE_ACK:
4925163953Srrs			{
4926163953Srrs				struct sctp_sack_chunk *sack;
4927163953Srrs				int abort_now = 0;
4928163953Srrs				uint32_t a_rwnd, cum_ack;
4929202526Stuexen				uint16_t num_seg, num_dup;
4930202526Stuexen				uint8_t flags;
4931202526Stuexen				int offset_seg, offset_dup;
4932163953Srrs
4933211944Stuexen				SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n");
4934211944Stuexen				SCTP_STAT_INCR(sctps_recvsacks);
4935202526Stuexen				if (stcb == NULL) {
4936202526Stuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing SACK chunk\n");
4937202526Stuexen					break;
4938169208Srrs				}
4939202526Stuexen				if (chk_length < sizeof(struct sctp_sack_chunk)) {
4940202526Stuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on SACK chunk, too small\n");
4941202526Stuexen					break;
4942202526Stuexen				}
4943171990Srrs				if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
4944171990Srrs					/*-
4945171990Srrs					 * If we have sent a shutdown-ack, we will pay no
4946171990Srrs					 * attention to a sack sent in to us since
4947171990Srrs					 * we don't care anymore.
4948171990Srrs					 */
4949184883Srrs					break;
4950171990Srrs				}
4951163953Srrs				sack = (struct sctp_sack_chunk *)ch;
4952202526Stuexen				flags = ch->chunk_flags;
4953163953Srrs				cum_ack = ntohl(sack->sack.cum_tsn_ack);
4954163953Srrs				num_seg = ntohs(sack->sack.num_gap_ack_blks);
4955202526Stuexen				num_dup = ntohs(sack->sack.num_dup_tsns);
4956163953Srrs				a_rwnd = (uint32_t) ntohl(sack->sack.a_rwnd);
4957202526Stuexen				if (sizeof(struct sctp_sack_chunk) +
4958202526Stuexen				    num_seg * sizeof(struct sctp_gap_ack_block) +
4959202526Stuexen				    num_dup * sizeof(uint32_t) != chk_length) {
4960202526Stuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of SACK chunk\n");
4961202526Stuexen					break;
4962202526Stuexen				}
4963202526Stuexen				offset_seg = *offset + sizeof(struct sctp_sack_chunk);
4964202526Stuexen				offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block);
4965170606Srrs				SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n",
4966202526Stuexen				    cum_ack, num_seg, a_rwnd);
4967163953Srrs				stcb->asoc.seen_a_sack_this_pkt = 1;
4968163953Srrs				if ((stcb->asoc.pr_sctp_cnt == 0) &&
4969163953Srrs				    (num_seg == 0) &&
4970216825Stuexen				    SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) &&
4971163953Srrs				    (stcb->asoc.saw_sack_with_frags == 0) &&
4972216188Stuexen				    (stcb->asoc.saw_sack_with_nr_frags == 0) &&
4973163953Srrs				    (!TAILQ_EMPTY(&stcb->asoc.sent_queue))
4974163953Srrs				    ) {
4975163953Srrs					/*
4976163953Srrs					 * We have a SIMPLE sack having no
4977163953Srrs					 * prior segments and data on sent
4978163953Srrs					 * queue to be acked.. Use the
4979163953Srrs					 * faster path sack processing. We
4980163953Srrs					 * also allow window update sacks
4981163953Srrs					 * with no missing segments to go
4982163953Srrs					 * this way too.
4983163953Srrs					 */
4984218186Srrs					sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now, ecne_seen);
4985163953Srrs				} else {
4986169420Srrs					if (netp && *netp)
4987228653Stuexen						sctp_handle_sack(m, offset_seg, offset_dup, stcb,
4988202526Stuexen						    num_seg, 0, num_dup, &abort_now, flags,
4989218186Srrs						    cum_ack, a_rwnd, ecne_seen);
4990163953Srrs				}
4991202526Stuexen				if (abort_now) {
4992202526Stuexen					/* ABORT signal from sack processing */
4993202526Stuexen					*offset = length;
4994202526Stuexen					return (NULL);
4995202526Stuexen				}
4996185694Srrs				if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
4997185694Srrs				    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
4998185694Srrs				    (stcb->asoc.stream_queue_cnt == 0)) {
4999185694Srrs					sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
5000185694Srrs				}
5001163953Srrs			}
5002163953Srrs			break;
5003185694Srrs			/*
5004185694Srrs			 * EY - nr_sack:  If the received chunk is an
5005185694Srrs			 * nr_sack chunk
5006185694Srrs			 */
5007185694Srrs		case SCTP_NR_SELECTIVE_ACK:
5008185694Srrs			{
5009185694Srrs				struct sctp_nr_sack_chunk *nr_sack;
5010185694Srrs				int abort_now = 0;
5011185694Srrs				uint32_t a_rwnd, cum_ack;
5012202526Stuexen				uint16_t num_seg, num_nr_seg, num_dup;
5013202526Stuexen				uint8_t flags;
5014202526Stuexen				int offset_seg, offset_dup;
5015185694Srrs
5016211944Stuexen				SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n");
5017211944Stuexen				SCTP_STAT_INCR(sctps_recvsacks);
5018212225Srrs				if (stcb == NULL) {
5019212225Srrs					SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing NR-SACK chunk\n");
5020212225Srrs					break;
5021212225Srrs				}
5022270359Stuexen				if (stcb->asoc.nrsack_supported == 0) {
5023185694Srrs					goto unknown_chunk;
5024185694Srrs				}
5025202526Stuexen				if (chk_length < sizeof(struct sctp_nr_sack_chunk)) {
5026202526Stuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on NR-SACK chunk, too small\n");
5027202526Stuexen					break;
5028202526Stuexen				}
5029185694Srrs				if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
5030185694Srrs					/*-
5031185694Srrs					 * If we have sent a shutdown-ack, we will pay no
5032185694Srrs					 * attention to a sack sent in to us since
5033185694Srrs					 * we don't care anymore.
5034185694Srrs					 */
5035202526Stuexen					break;
5036185694Srrs				}
5037185694Srrs				nr_sack = (struct sctp_nr_sack_chunk *)ch;
5038202526Stuexen				flags = ch->chunk_flags;
5039185694Srrs				cum_ack = ntohl(nr_sack->nr_sack.cum_tsn_ack);
5040185694Srrs				num_seg = ntohs(nr_sack->nr_sack.num_gap_ack_blks);
5041185694Srrs				num_nr_seg = ntohs(nr_sack->nr_sack.num_nr_gap_ack_blks);
5042202526Stuexen				num_dup = ntohs(nr_sack->nr_sack.num_dup_tsns);
5043185694Srrs				a_rwnd = (uint32_t) ntohl(nr_sack->nr_sack.a_rwnd);
5044202526Stuexen				if (sizeof(struct sctp_nr_sack_chunk) +
5045202526Stuexen				    (num_seg + num_nr_seg) * sizeof(struct sctp_gap_ack_block) +
5046202526Stuexen				    num_dup * sizeof(uint32_t) != chk_length) {
5047202526Stuexen					SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of NR_SACK chunk\n");
5048202526Stuexen					break;
5049202526Stuexen				}
5050202526Stuexen				offset_seg = *offset + sizeof(struct sctp_nr_sack_chunk);
5051202526Stuexen				offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block);
5052185694Srrs				SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n",
5053202526Stuexen				    cum_ack, num_seg, a_rwnd);
5054185694Srrs				stcb->asoc.seen_a_sack_this_pkt = 1;
5055185694Srrs				if ((stcb->asoc.pr_sctp_cnt == 0) &&
5056202526Stuexen				    (num_seg == 0) && (num_nr_seg == 0) &&
5057216825Stuexen				    SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) &&
5058185694Srrs				    (stcb->asoc.saw_sack_with_frags == 0) &&
5059216188Stuexen				    (stcb->asoc.saw_sack_with_nr_frags == 0) &&
5060202526Stuexen				    (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
5061185694Srrs					/*
5062185694Srrs					 * We have a SIMPLE sack having no
5063185694Srrs					 * prior segments and data on sent
5064202526Stuexen					 * queue to be acked. Use the faster
5065202526Stuexen					 * path sack processing. We also
5066202526Stuexen					 * allow window update sacks with no
5067202526Stuexen					 * missing segments to go this way
5068202526Stuexen					 * too.
5069185694Srrs					 */
5070218129Srrs					sctp_express_handle_sack(stcb, cum_ack, a_rwnd,
5071218186Srrs					    &abort_now, ecne_seen);
5072185694Srrs				} else {
5073185694Srrs					if (netp && *netp)
5074228653Stuexen						sctp_handle_sack(m, offset_seg, offset_dup, stcb,
5075202526Stuexen						    num_seg, num_nr_seg, num_dup, &abort_now, flags,
5076218186Srrs						    cum_ack, a_rwnd, ecne_seen);
5077185694Srrs				}
5078202526Stuexen				if (abort_now) {
5079202526Stuexen					/* ABORT signal from sack processing */
5080202526Stuexen					*offset = length;
5081202526Stuexen					return (NULL);
5082202526Stuexen				}
5083185694Srrs				if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5084185694Srrs				    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5085185694Srrs				    (stcb->asoc.stream_queue_cnt == 0)) {
5086185694Srrs					sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
5087185694Srrs				}
5088185694Srrs			}
5089185694Srrs			break;
5090185694Srrs
5091163953Srrs		case SCTP_HEARTBEAT_REQUEST:
5092169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT\n");
5093169420Srrs			if ((stcb) && netp && *netp) {
5094169420Srrs				SCTP_STAT_INCR(sctps_recvheartbeat);
5095169420Srrs				sctp_send_heartbeat_ack(stcb, m, *offset,
5096169420Srrs				    chk_length, *netp);
5097169420Srrs
5098169420Srrs				/* He's alive so give him credit */
5099179783Srrs				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5100171943Srrs					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5101171943Srrs					    stcb->asoc.overall_error_count,
5102171943Srrs					    0,
5103171943Srrs					    SCTP_FROM_SCTP_INPUT,
5104171943Srrs					    __LINE__);
5105171943Srrs				}
5106169420Srrs				stcb->asoc.overall_error_count = 0;
5107163953Srrs			}
5108163953Srrs			break;
5109163953Srrs		case SCTP_HEARTBEAT_ACK:
5110169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT-ACK\n");
5111169420Srrs			if ((stcb == NULL) || (chk_length != sizeof(struct sctp_heartbeat_chunk))) {
5112169208Srrs				/* Its not ours */
5113169352Srrs				*offset = length;
5114169378Srrs				if (locked_tcb) {
5115169295Srrs					SCTP_TCB_UNLOCK(locked_tcb);
5116169378Srrs				}
5117169208Srrs				return (NULL);
5118169208Srrs			}
5119163953Srrs			/* He's alive so give him credit */
5120179783Srrs			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5121171943Srrs				sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5122171943Srrs				    stcb->asoc.overall_error_count,
5123171943Srrs				    0,
5124171943Srrs				    SCTP_FROM_SCTP_INPUT,
5125171943Srrs				    __LINE__);
5126171943Srrs			}
5127163953Srrs			stcb->asoc.overall_error_count = 0;
5128163953Srrs			SCTP_STAT_INCR(sctps_recvheartbeatack);
5129169420Srrs			if (netp && *netp)
5130169420Srrs				sctp_handle_heartbeat_ack((struct sctp_heartbeat_chunk *)ch,
5131169420Srrs				    stcb, *netp);
5132163953Srrs			break;
5133163953Srrs		case SCTP_ABORT_ASSOCIATION:
5134170091Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT, stcb %p\n",
5135240148Stuexen			    (void *)stcb);
5136169420Srrs			if ((stcb) && netp && *netp)
5137169420Srrs				sctp_handle_abort((struct sctp_abort_chunk *)ch,
5138169420Srrs				    stcb, *netp);
5139163953Srrs			*offset = length;
5140163953Srrs			return (NULL);
5141163953Srrs			break;
5142163953Srrs		case SCTP_SHUTDOWN:
5143170091Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN, stcb %p\n",
5144240148Stuexen			    (void *)stcb);
5145169420Srrs			if ((stcb == NULL) || (chk_length != sizeof(struct sctp_shutdown_chunk))) {
5146169208Srrs				*offset = length;
5147169378Srrs				if (locked_tcb) {
5148169295Srrs					SCTP_TCB_UNLOCK(locked_tcb);
5149169378Srrs				}
5150169208Srrs				return (NULL);
5151169420Srrs			}
5152169420Srrs			if (netp && *netp) {
5153163953Srrs				int abort_flag = 0;
5154163953Srrs
5155163953Srrs				sctp_handle_shutdown((struct sctp_shutdown_chunk *)ch,
5156163953Srrs				    stcb, *netp, &abort_flag);
5157163953Srrs				if (abort_flag) {
5158163953Srrs					*offset = length;
5159163953Srrs					return (NULL);
5160163953Srrs				}
5161163953Srrs			}
5162163953Srrs			break;
5163163953Srrs		case SCTP_SHUTDOWN_ACK:
5164240148Stuexen			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", (void *)stcb);
5165169420Srrs			if ((stcb) && (netp) && (*netp))
5166169420Srrs				sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp);
5167163953Srrs			*offset = length;
5168163953Srrs			return (NULL);
5169163953Srrs			break;
5170169420Srrs
5171163953Srrs		case SCTP_OPERATION_ERROR:
5172169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_OP-ERR\n");
5173169420Srrs			if ((stcb) && netp && *netp && sctp_handle_error(ch, stcb, *netp) < 0) {
5174163953Srrs				*offset = length;
5175163953Srrs				return (NULL);
5176163953Srrs			}
5177163953Srrs			break;
5178163953Srrs		case SCTP_COOKIE_ECHO:
5179169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3,
5180240148Stuexen			    "SCTP_COOKIE-ECHO, stcb %p\n", (void *)stcb);
5181163953Srrs			if ((stcb) && (stcb->asoc.total_output_queue_size)) {
5182163953Srrs				;
5183163953Srrs			} else {
5184169420Srrs				if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
5185163953Srrs					/* We are not interested anymore */
5186208878Srrs			abend:
5187208853Srrs					if (stcb) {
5188208853Srrs						SCTP_TCB_UNLOCK(stcb);
5189208853Srrs					}
5190163953Srrs					*offset = length;
5191163953Srrs					return (NULL);
5192163953Srrs				}
5193163953Srrs			}
5194163953Srrs			/*
5195163953Srrs			 * First are we accepting? We do this again here
5196207924Srrs			 * since it is possible that a previous endpoint WAS
5197207924Srrs			 * listening responded to a INIT-ACK and then
5198163953Srrs			 * closed. We opened and bound.. and are now no
5199163953Srrs			 * longer listening.
5200163953Srrs			 */
5201172703Srrs
5202172703Srrs			if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) {
5203172703Srrs				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
5204179783Srrs				    (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) {
5205267723Stuexen					op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
5206237715Stuexen					sctp_abort_association(inp, stcb, m, iphlen,
5207237715Stuexen					    src, dst, sh, op_err,
5208281955Shiren					    mflowtype, mflowid,
5209237049Stuexen					    vrf_id, port);
5210163953Srrs				}
5211172703Srrs				*offset = length;
5212172703Srrs				return (NULL);
5213172703Srrs			} else {
5214163953Srrs				struct mbuf *ret_buf;
5215165220Srrs				struct sctp_inpcb *linp;
5216163953Srrs
5217169420Srrs				if (stcb) {
5218165220Srrs					linp = NULL;
5219169420Srrs				} else {
5220165220Srrs					linp = inp;
5221169420Srrs				}
5222165220Srrs
5223169420Srrs				if (linp) {
5224165220Srrs					SCTP_ASOC_CREATE_LOCK(linp);
5225208878Srrs					if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
5226208878Srrs					    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
5227208878Srrs						SCTP_ASOC_CREATE_UNLOCK(linp);
5228208878Srrs						goto abend;
5229208878Srrs					}
5230169420Srrs				}
5231169420Srrs				if (netp) {
5232169420Srrs					ret_buf =
5233169420Srrs					    sctp_handle_cookie_echo(m, iphlen,
5234237715Stuexen					    *offset,
5235237715Stuexen					    src, dst,
5236237715Stuexen					    sh,
5237169420Srrs					    (struct sctp_cookie_echo_chunk *)ch,
5238169420Srrs					    &inp, &stcb, netp,
5239169420Srrs					    auth_skipped,
5240169420Srrs					    auth_offset,
5241169420Srrs					    auth_len,
5242169420Srrs					    &locked_tcb,
5243281955Shiren					    mflowtype,
5244237049Stuexen					    mflowid,
5245179157Srrs					    vrf_id,
5246179157Srrs					    port);
5247169420Srrs				} else {
5248169420Srrs					ret_buf = NULL;
5249169420Srrs				}
5250169420Srrs				if (linp) {
5251165220Srrs					SCTP_ASOC_CREATE_UNLOCK(linp);
5252169420Srrs				}
5253163953Srrs				if (ret_buf == NULL) {
5254163953Srrs					if (locked_tcb) {
5255163953Srrs						SCTP_TCB_UNLOCK(locked_tcb);
5256163953Srrs					}
5257169420Srrs					SCTPDBG(SCTP_DEBUG_INPUT3,
5258169420Srrs					    "GAK, null buffer\n");
5259163953Srrs					*offset = length;
5260163953Srrs					return (NULL);
5261163953Srrs				}
5262163953Srrs				/* if AUTH skipped, see if it verified... */
5263163953Srrs				if (auth_skipped) {
5264163953Srrs					got_auth = 1;
5265163953Srrs					auth_skipped = 0;
5266163953Srrs				}
5267163953Srrs				if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
5268163953Srrs					/*
5269163953Srrs					 * Restart the timer if we have
5270163953Srrs					 * pending data
5271163953Srrs					 */
5272163953Srrs					struct sctp_tmit_chunk *chk;
5273163953Srrs
5274163953Srrs					chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
5275216822Stuexen					sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo);
5276163953Srrs				}
5277163953Srrs			}
5278163953Srrs			break;
5279163953Srrs		case SCTP_COOKIE_ACK:
5280240148Stuexen			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", (void *)stcb);
5281169420Srrs			if ((stcb == NULL) || chk_length != sizeof(struct sctp_cookie_ack_chunk)) {
5282169378Srrs				if (locked_tcb) {
5283169352Srrs					SCTP_TCB_UNLOCK(locked_tcb);
5284169378Srrs				}
5285169352Srrs				return (NULL);
5286169352Srrs			}
5287163953Srrs			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
5288163953Srrs				/* We are not interested anymore */
5289163953Srrs				if ((stcb) && (stcb->asoc.total_output_queue_size)) {
5290163953Srrs					;
5291169420Srrs				} else if (stcb) {
5292237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
5293172090Srrs					so = SCTP_INP_SO(inp);
5294172090Srrs					atomic_add_int(&stcb->asoc.refcnt, 1);
5295172090Srrs					SCTP_TCB_UNLOCK(stcb);
5296172090Srrs					SCTP_SOCKET_LOCK(so, 1);
5297172090Srrs					SCTP_TCB_LOCK(stcb);
5298172090Srrs					atomic_subtract_int(&stcb->asoc.refcnt, 1);
5299172090Srrs#endif
5300283822Stuexen					(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
5301283822Stuexen					    SCTP_FROM_SCTP_INPUT + SCTP_LOC_30);
5302237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
5303172090Srrs					SCTP_SOCKET_UNLOCK(so, 1);
5304172090Srrs#endif
5305163953Srrs					*offset = length;
5306163953Srrs					return (NULL);
5307163953Srrs				}
5308163953Srrs			}
5309163953Srrs			/* He's alive so give him credit */
5310169420Srrs			if ((stcb) && netp && *netp) {
5311179783Srrs				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5312171943Srrs					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5313171943Srrs					    stcb->asoc.overall_error_count,
5314171943Srrs					    0,
5315171943Srrs					    SCTP_FROM_SCTP_INPUT,
5316171943Srrs					    __LINE__);
5317171943Srrs				}
5318169378Srrs				stcb->asoc.overall_error_count = 0;
5319169378Srrs				sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, *netp);
5320169378Srrs			}
5321163953Srrs			break;
5322163953Srrs		case SCTP_ECN_ECHO:
5323169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-ECHO\n");
5324163953Srrs			/* He's alive so give him credit */
5325169420Srrs			if ((stcb == NULL) || (chk_length != sizeof(struct sctp_ecne_chunk))) {
5326169208Srrs				/* Its not ours */
5327169378Srrs				if (locked_tcb) {
5328169295Srrs					SCTP_TCB_UNLOCK(locked_tcb);
5329169378Srrs				}
5330169208Srrs				*offset = length;
5331169208Srrs				return (NULL);
5332169208Srrs			}
5333169378Srrs			if (stcb) {
5334270362Stuexen				if (stcb->asoc.ecn_supported == 0) {
5335270362Stuexen					goto unknown_chunk;
5336270362Stuexen				}
5337179783Srrs				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5338171943Srrs					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5339171943Srrs					    stcb->asoc.overall_error_count,
5340171943Srrs					    0,
5341171943Srrs					    SCTP_FROM_SCTP_INPUT,
5342171943Srrs					    __LINE__);
5343171943Srrs				}
5344169378Srrs				stcb->asoc.overall_error_count = 0;
5345169378Srrs				sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch,
5346169378Srrs				    stcb);
5347218186Srrs				ecne_seen = 1;
5348169378Srrs			}
5349163953Srrs			break;
5350163953Srrs		case SCTP_ECN_CWR:
5351169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-CWR\n");
5352163953Srrs			/* He's alive so give him credit */
5353169420Srrs			if ((stcb == NULL) || (chk_length != sizeof(struct sctp_cwr_chunk))) {
5354169208Srrs				/* Its not ours */
5355169378Srrs				if (locked_tcb) {
5356169295Srrs					SCTP_TCB_UNLOCK(locked_tcb);
5357169378Srrs				}
5358169208Srrs				*offset = length;
5359169208Srrs				return (NULL);
5360169208Srrs			}
5361169378Srrs			if (stcb) {
5362270362Stuexen				if (stcb->asoc.ecn_supported == 0) {
5363270362Stuexen					goto unknown_chunk;
5364270362Stuexen				}
5365179783Srrs				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5366171943Srrs					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5367171943Srrs					    stcb->asoc.overall_error_count,
5368171943Srrs					    0,
5369171943Srrs					    SCTP_FROM_SCTP_INPUT,
5370171943Srrs					    __LINE__);
5371171943Srrs				}
5372169378Srrs				stcb->asoc.overall_error_count = 0;
5373218072Srrs				sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb, *netp);
5374169378Srrs			}
5375163953Srrs			break;
5376163953Srrs		case SCTP_SHUTDOWN_COMPLETE:
5377240148Stuexen			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", (void *)stcb);
5378163953Srrs			/* must be first and only chunk */
5379163953Srrs			if ((num_chunks > 1) ||
5380170140Srrs			    (length - *offset > (int)SCTP_SIZE32(chk_length))) {
5381163953Srrs				*offset = length;
5382169378Srrs				if (locked_tcb) {
5383163953Srrs					SCTP_TCB_UNLOCK(locked_tcb);
5384169378Srrs				}
5385163953Srrs				return (NULL);
5386163953Srrs			}
5387169420Srrs			if ((stcb) && netp && *netp) {
5388169378Srrs				sctp_handle_shutdown_complete((struct sctp_shutdown_complete_chunk *)ch,
5389169378Srrs				    stcb, *netp);
5390169378Srrs			}
5391163953Srrs			*offset = length;
5392163953Srrs			return (NULL);
5393163953Srrs			break;
5394163953Srrs		case SCTP_ASCONF:
5395169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n");
5396163953Srrs			/* He's alive so give him credit */
5397169378Srrs			if (stcb) {
5398270362Stuexen				if (stcb->asoc.asconf_supported == 0) {
5399270362Stuexen					goto unknown_chunk;
5400270362Stuexen				}
5401179783Srrs				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5402171943Srrs					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5403171943Srrs					    stcb->asoc.overall_error_count,
5404171943Srrs					    0,
5405171943Srrs					    SCTP_FROM_SCTP_INPUT,
5406171943Srrs					    __LINE__);
5407171943Srrs				}
5408169378Srrs				stcb->asoc.overall_error_count = 0;
5409237715Stuexen				sctp_handle_asconf(m, *offset, src,
5410171990Srrs				    (struct sctp_asconf_chunk *)ch, stcb, asconf_cnt == 0);
5411171990Srrs				asconf_cnt++;
5412169378Srrs			}
5413163953Srrs			break;
5414163953Srrs		case SCTP_ASCONF_ACK:
5415169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF-ACK\n");
5416169208Srrs			if (chk_length < sizeof(struct sctp_asconf_ack_chunk)) {
5417169208Srrs				/* Its not ours */
5418169378Srrs				if (locked_tcb) {
5419169295Srrs					SCTP_TCB_UNLOCK(locked_tcb);
5420169378Srrs				}
5421169208Srrs				*offset = length;
5422169208Srrs				return (NULL);
5423169208Srrs			}
5424169420Srrs			if ((stcb) && netp && *netp) {
5425270362Stuexen				if (stcb->asoc.asconf_supported == 0) {
5426270362Stuexen					goto unknown_chunk;
5427270362Stuexen				}
5428169378Srrs				/* He's alive so give him credit */
5429179783Srrs				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5430171943Srrs					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5431171943Srrs					    stcb->asoc.overall_error_count,
5432171943Srrs					    0,
5433171943Srrs					    SCTP_FROM_SCTP_INPUT,
5434171943Srrs					    __LINE__);
5435171943Srrs				}
5436169378Srrs				stcb->asoc.overall_error_count = 0;
5437169378Srrs				sctp_handle_asconf_ack(m, *offset,
5438172190Srrs				    (struct sctp_asconf_ack_chunk *)ch, stcb, *netp, &abort_no_unlock);
5439172190Srrs				if (abort_no_unlock)
5440172190Srrs					return (NULL);
5441169378Srrs			}
5442163953Srrs			break;
5443163953Srrs		case SCTP_FORWARD_CUM_TSN:
5444169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_FWD-TSN\n");
5445169208Srrs			if (chk_length < sizeof(struct sctp_forward_tsn_chunk)) {
5446169208Srrs				/* Its not ours */
5447169378Srrs				if (locked_tcb) {
5448169295Srrs					SCTP_TCB_UNLOCK(locked_tcb);
5449169378Srrs				}
5450169208Srrs				*offset = length;
5451169208Srrs				return (NULL);
5452169208Srrs			}
5453163953Srrs			/* He's alive so give him credit */
5454169378Srrs			if (stcb) {
5455163953Srrs				int abort_flag = 0;
5456163953Srrs
5457270362Stuexen				if (stcb->asoc.prsctp_supported == 0) {
5458270362Stuexen					goto unknown_chunk;
5459270362Stuexen				}
5460163953Srrs				stcb->asoc.overall_error_count = 0;
5461179783Srrs				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5462171943Srrs					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5463171943Srrs					    stcb->asoc.overall_error_count,
5464171943Srrs					    0,
5465171943Srrs					    SCTP_FROM_SCTP_INPUT,
5466171943Srrs					    __LINE__);
5467171943Srrs				}
5468163953Srrs				*fwd_tsn_seen = 1;
5469163953Srrs				if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
5470163953Srrs					/* We are not interested anymore */
5471237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
5472172090Srrs					so = SCTP_INP_SO(inp);
5473172090Srrs					atomic_add_int(&stcb->asoc.refcnt, 1);
5474172090Srrs					SCTP_TCB_UNLOCK(stcb);
5475172090Srrs					SCTP_SOCKET_LOCK(so, 1);
5476172090Srrs					SCTP_TCB_LOCK(stcb);
5477172090Srrs					atomic_subtract_int(&stcb->asoc.refcnt, 1);
5478172090Srrs#endif
5479283822Stuexen					(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
5480283822Stuexen					    SCTP_FROM_SCTP_INPUT + SCTP_LOC_31);
5481237565Stuexen#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
5482172090Srrs					SCTP_SOCKET_UNLOCK(so, 1);
5483172090Srrs#endif
5484163953Srrs					*offset = length;
5485163953Srrs					return (NULL);
5486163953Srrs				}
5487163953Srrs				sctp_handle_forward_tsn(stcb,
5488170992Srrs				    (struct sctp_forward_tsn_chunk *)ch, &abort_flag, m, *offset);
5489163953Srrs				if (abort_flag) {
5490163953Srrs					*offset = length;
5491163953Srrs					return (NULL);
5492163953Srrs				} else {
5493179783Srrs					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5494171943Srrs						sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5495171943Srrs						    stcb->asoc.overall_error_count,
5496171943Srrs						    0,
5497171943Srrs						    SCTP_FROM_SCTP_INPUT,
5498171943Srrs						    __LINE__);
5499171943Srrs					}
5500163953Srrs					stcb->asoc.overall_error_count = 0;
5501163953Srrs				}
5502163953Srrs
5503163953Srrs			}
5504163953Srrs			break;
5505163953Srrs		case SCTP_STREAM_RESET:
5506169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_STREAM_RESET\n");
5507169420Srrs			if (((stcb == NULL) || (ch == NULL) || (chk_length < sizeof(struct sctp_stream_reset_tsn_req)))) {
5508169208Srrs				/* Its not ours */
5509169378Srrs				if (locked_tcb) {
5510169295Srrs					SCTP_TCB_UNLOCK(locked_tcb);
5511169378Srrs				}
5512169208Srrs				*offset = length;
5513169208Srrs				return (NULL);
5514169208Srrs			}
5515270361Stuexen			if (stcb->asoc.reconfig_supported == 0) {
5516270362Stuexen				goto unknown_chunk;
5517163953Srrs			}
5518240198Stuexen			if (sctp_handle_stream_reset(stcb, m, *offset, ch)) {
5519169420Srrs				/* stop processing */
5520169420Srrs				*offset = length;
5521169420Srrs				return (NULL);
5522169420Srrs			}
5523163953Srrs			break;
5524163953Srrs		case SCTP_PACKET_DROPPED:
5525169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_PACKET_DROPPED\n");
5526163953Srrs			/* re-get it all please */
5527169208Srrs			if (chk_length < sizeof(struct sctp_pktdrop_chunk)) {
5528169208Srrs				/* Its not ours */
5529169378Srrs				if (locked_tcb) {
5530169295Srrs					SCTP_TCB_UNLOCK(locked_tcb);
5531169378Srrs				}
5532169208Srrs				*offset = length;
5533169208Srrs				return (NULL);
5534169208Srrs			}
5535169420Srrs			if (ch && (stcb) && netp && (*netp)) {
5536270362Stuexen				if (stcb->asoc.pktdrop_supported == 0) {
5537270362Stuexen					goto unknown_chunk;
5538270362Stuexen				}
5539169378Srrs				sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch,
5540170781Srrs				    stcb, *netp,
5541170781Srrs				    min(chk_length, (sizeof(chunk_buf) - 4)));
5542170781Srrs
5543169378Srrs			}
5544163953Srrs			break;
5545163953Srrs		case SCTP_AUTHENTICATION:
5546169420Srrs			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n");
5547163953Srrs			if (stcb == NULL) {
5548163953Srrs				/* save the first AUTH for later processing */
5549163953Srrs				if (auth_skipped == 0) {
5550163953Srrs					auth_offset = *offset;
5551163953Srrs					auth_len = chk_length;
5552163953Srrs					auth_skipped = 1;
5553163953Srrs				}
5554163953Srrs				/* skip this chunk (temporarily) */
5555163953Srrs				goto next_chunk;
5556163953Srrs			}
5557270362Stuexen			if (stcb->asoc.auth_supported == 0) {
5558270362Stuexen				goto unknown_chunk;
5559270362Stuexen			}
5560169208Srrs			if ((chk_length < (sizeof(struct sctp_auth_chunk))) ||
5561169420Srrs			    (chk_length > (sizeof(struct sctp_auth_chunk) +
5562169420Srrs			    SCTP_AUTH_DIGEST_LEN_MAX))) {
5563169208Srrs				/* Its not ours */
5564169378Srrs				if (locked_tcb) {
5565169295Srrs					SCTP_TCB_UNLOCK(locked_tcb);
5566169378Srrs				}
5567169208Srrs				*offset = length;
5568169208Srrs				return (NULL);
5569169208Srrs			}
5570163953Srrs			if (got_auth == 1) {
5571163953Srrs				/* skip this chunk... it's already auth'd */
5572163953Srrs				goto next_chunk;
5573163953Srrs			}
5574163953Srrs			got_auth = 1;
5575169420Srrs			if ((ch == NULL) || sctp_handle_auth(stcb, (struct sctp_auth_chunk *)ch,
5576163953Srrs			    m, *offset)) {
5577163953Srrs				/* auth HMAC failed so dump the packet */
5578163953Srrs				*offset = length;
5579163953Srrs				return (stcb);
5580163953Srrs			} else {
5581163953Srrs				/* remaining chunks are HMAC checked */
5582163953Srrs				stcb->asoc.authenticated = 1;
5583163953Srrs			}
5584163953Srrs			break;
5585163953Srrs
5586163953Srrs		default:
5587163953Srrs	unknown_chunk:
5588163953Srrs			/* it's an unknown chunk! */
5589163953Srrs			if ((ch->chunk_type & 0x40) && (stcb != NULL)) {
5590294158Stuexen				struct sctp_gen_error_cause *cause;
5591283700Stuexen				int len;
5592163953Srrs
5593294158Stuexen				op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause),
5594243882Sglebius				    0, M_NOWAIT, 1, MT_DATA);
5595294158Stuexen				if (op_err != NULL) {
5596283700Stuexen					len = min(SCTP_SIZE32(chk_length), (uint32_t) (length - *offset));
5597294158Stuexen					cause = mtod(op_err, struct sctp_gen_error_cause *);
5598294158Stuexen					cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK);
5599294158Stuexen					cause->length = htons(len + sizeof(struct sctp_gen_error_cause));
5600294158Stuexen					SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause);
5601294158Stuexen					SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT);
5602294158Stuexen					if (SCTP_BUF_NEXT(op_err) != NULL) {
5603178202Srrs#ifdef SCTP_MBUF_LOGGING
5604294157Stuexen						if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
5605294172Stuexen							sctp_log_mbc(SCTP_BUF_NEXT(op_err), SCTP_MBUF_ICOPY);
5606294157Stuexen						}
5607234459Stuexen#endif
5608294158Stuexen						sctp_queue_op_err(stcb, op_err);
5609163953Srrs					} else {
5610294158Stuexen						sctp_m_freem(op_err);
5611163953Srrs					}
5612163953Srrs				}
5613163953Srrs			}
5614163953Srrs			if ((ch->chunk_type & 0x80) == 0) {
5615163953Srrs				/* discard this packet */
5616163953Srrs				*offset = length;
5617163953Srrs				return (stcb);
5618163953Srrs			}	/* else skip this bad chunk and continue... */
5619163953Srrs			break;
5620163953Srrs		}		/* switch (ch->chunk_type) */
5621163953Srrs
5622163953Srrs
5623163953Srrsnext_chunk:
5624163953Srrs		/* get the next chunk */
5625163953Srrs		*offset += SCTP_SIZE32(chk_length);
5626163953Srrs		if (*offset >= length) {
5627163953Srrs			/* no more data left in the mbuf chain */
5628163953Srrs			break;
5629163953Srrs		}
5630163953Srrs		ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
5631163953Srrs		    sizeof(struct sctp_chunkhdr), chunk_buf);
5632163953Srrs		if (ch == NULL) {
5633169378Srrs			if (locked_tcb) {
5634163953Srrs				SCTP_TCB_UNLOCK(locked_tcb);
5635169378Srrs			}
5636163953Srrs			*offset = length;
5637163953Srrs			return (NULL);
5638163953Srrs		}
5639163953Srrs	}			/* while */
5640171990Srrs
5641171990Srrs	if (asconf_cnt > 0 && stcb != NULL) {
5642171990Srrs		sctp_send_asconf_ack(stcb);
5643171990Srrs	}
5644163953Srrs	return (stcb);
5645163953Srrs}
5646163953Srrs
5647163953Srrs
5648163953Srrs/*
5649163953Srrs * common input chunk processing (v4 and v6)
5650163953Srrs */
5651169378Srrsvoid
5652237715Stuexensctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int length,
5653237715Stuexen    struct sockaddr *src, struct sockaddr *dst,
5654237715Stuexen    struct sctphdr *sh, struct sctp_chunkhdr *ch,
5655238003Stuexen#if !defined(SCTP_WITH_NO_CSUM)
5656238003Stuexen    uint8_t compute_crc,
5657238003Stuexen#endif
5658238003Stuexen    uint8_t ecn_bits,
5659284633Stuexen    uint8_t mflowtype, uint32_t mflowid, uint16_t fibnum,
5660237049Stuexen    uint32_t vrf_id, uint16_t port)
5661163953Srrs{
5662163953Srrs	uint32_t high_tsn;
5663163953Srrs	int fwd_tsn_seen = 0, data_processed = 0;
5664267723Stuexen	struct mbuf *m = *mm, *op_err;
5665267723Stuexen	char msg[SCTP_DIAG_INFO_LEN];
5666163953Srrs	int un_sent;
5667218129Srrs	int cnt_ctrl_ready = 0;
5668239091Stuexen	struct sctp_inpcb *inp = NULL, *inp_decr = NULL;
5669238003Stuexen	struct sctp_tcb *stcb = NULL;
5670238087Stuexen	struct sctp_nets *net = NULL;
5671163953Srrs
5672163953Srrs	SCTP_STAT_INCR(sctps_recvdatagrams);
5673163953Srrs#ifdef SCTP_AUDITING_ENABLED
5674163953Srrs	sctp_audit_log(0xE0, 1);
5675163953Srrs	sctp_auditing(0, inp, stcb, net);
5676163953Srrs#endif
5677238003Stuexen#if !defined(SCTP_WITH_NO_CSUM)
5678238003Stuexen	if (compute_crc != 0) {
5679238003Stuexen		uint32_t check, calc_check;
5680163953Srrs
5681238003Stuexen		check = sh->checksum;
5682238003Stuexen		sh->checksum = 0;
5683238003Stuexen		calc_check = sctp_calculate_cksum(m, iphlen);
5684238003Stuexen		sh->checksum = check;
5685238003Stuexen		if (calc_check != check) {
5686238003Stuexen			SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x  m:%p mlen:%d iphlen:%d\n",
5687240148Stuexen			    calc_check, check, (void *)m, length, iphlen);
5688238003Stuexen			stcb = sctp_findassociation_addr(m, offset, src, dst,
5689238003Stuexen			    sh, ch, &inp, &net, vrf_id);
5690270350Stuexen#if defined(INET) || defined(INET6)
5691295208Stuexen			if ((ch->chunk_type != SCTP_INITIATION) &&
5692295208Stuexen			    (net != NULL) && (net->port != port)) {
5693238003Stuexen				if (net->port == 0) {
5694295208Stuexen					/* UDP encapsulation turned on. */
5695295208Stuexen					net->mtu -= sizeof(struct udphdr);
5696295208Stuexen					if (stcb->asoc.smallest_mtu > net->mtu) {
5697295208Stuexen						sctp_pathmtu_adjustment(stcb, net->mtu);
5698295208Stuexen					}
5699295208Stuexen				} else if (port == 0) {
5700295208Stuexen					/* UDP encapsulation turned off. */
5701295208Stuexen					net->mtu += sizeof(struct udphdr);
5702295208Stuexen					/* XXX Update smallest_mtu */
5703238003Stuexen				}
5704238003Stuexen				net->port = port;
5705238003Stuexen			}
5706270350Stuexen#endif
5707284634Stuexen			if (net != NULL) {
5708281955Shiren				net->flowtype = mflowtype;
5709284634Stuexen				net->flowid = mflowid;
5710238003Stuexen			}
5711238003Stuexen			if ((inp != NULL) && (stcb != NULL)) {
5712238003Stuexen				sctp_send_packet_dropped(stcb, net, m, length, iphlen, 1);
5713238003Stuexen				sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
5714238003Stuexen			} else if ((inp != NULL) && (stcb == NULL)) {
5715238003Stuexen				inp_decr = inp;
5716238003Stuexen			}
5717238003Stuexen			SCTP_STAT_INCR(sctps_badsum);
5718238003Stuexen			SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
5719238003Stuexen			goto out;
5720238003Stuexen		}
5721238003Stuexen	}
5722238003Stuexen#endif
5723238003Stuexen	/* Destination port of 0 is illegal, based on RFC4960. */
5724238003Stuexen	if (sh->dest_port == 0) {
5725238003Stuexen		SCTP_STAT_INCR(sctps_hdrops);
5726238003Stuexen		goto out;
5727238003Stuexen	}
5728238003Stuexen	stcb = sctp_findassociation_addr(m, offset, src, dst,
5729238003Stuexen	    sh, ch, &inp, &net, vrf_id);
5730270350Stuexen#if defined(INET) || defined(INET6)
5731295208Stuexen	if ((ch->chunk_type != SCTP_INITIATION) &&
5732295208Stuexen	    (net != NULL) && (net->port != port)) {
5733238003Stuexen		if (net->port == 0) {
5734295208Stuexen			/* UDP encapsulation turned on. */
5735295208Stuexen			net->mtu -= sizeof(struct udphdr);
5736295208Stuexen			if (stcb->asoc.smallest_mtu > net->mtu) {
5737295208Stuexen				sctp_pathmtu_adjustment(stcb, net->mtu);
5738295208Stuexen			}
5739295208Stuexen		} else if (port == 0) {
5740295208Stuexen			/* UDP encapsulation turned off. */
5741295208Stuexen			net->mtu += sizeof(struct udphdr);
5742295208Stuexen			/* XXX Update smallest_mtu */
5743238003Stuexen		}
5744238003Stuexen		net->port = port;
5745238003Stuexen	}
5746270350Stuexen#endif
5747284634Stuexen	if (net != NULL) {
5748281955Shiren		net->flowtype = mflowtype;
5749284634Stuexen		net->flowid = mflowid;
5750238003Stuexen	}
5751238003Stuexen	if (inp == NULL) {
5752238003Stuexen		SCTP_STAT_INCR(sctps_noport);
5753238003Stuexen		if (badport_bandlim(BANDLIM_SCTP_OOTB) < 0) {
5754238003Stuexen			goto out;
5755238003Stuexen		}
5756238003Stuexen		if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
5757238003Stuexen			sctp_send_shutdown_complete2(src, dst, sh,
5758284633Stuexen			    mflowtype, mflowid, fibnum,
5759238003Stuexen			    vrf_id, port);
5760238003Stuexen			goto out;
5761238003Stuexen		}
5762238003Stuexen		if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
5763238003Stuexen			goto out;
5764238003Stuexen		}
5765238003Stuexen		if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) {
5766238003Stuexen			if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
5767238003Stuexen			    ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
5768238003Stuexen			    (ch->chunk_type != SCTP_INIT))) {
5769267723Stuexen				op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
5770267723Stuexen				    "Out of the blue");
5771238003Stuexen				sctp_send_abort(m, iphlen, src, dst,
5772267723Stuexen				    sh, 0, op_err,
5773284633Stuexen				    mflowtype, mflowid, fibnum,
5774238003Stuexen				    vrf_id, port);
5775238003Stuexen			}
5776238003Stuexen		}
5777238003Stuexen		goto out;
5778238003Stuexen	} else if (stcb == NULL) {
5779238003Stuexen		inp_decr = inp;
5780238003Stuexen	}
5781238003Stuexen#ifdef IPSEC
5782238003Stuexen	/*-
5783238003Stuexen	 * I very much doubt any of the IPSEC stuff will work but I have no
5784238003Stuexen	 * idea, so I will leave it in place.
5785238003Stuexen	 */
5786238003Stuexen	if (inp != NULL) {
5787238003Stuexen		switch (dst->sa_family) {
5788238003Stuexen#ifdef INET
5789238003Stuexen		case AF_INET:
5790238003Stuexen			if (ipsec4_in_reject(m, &inp->ip_inp.inp)) {
5791253571Sae				IPSECSTAT_INC(ips_in_polvio);
5792238003Stuexen				SCTP_STAT_INCR(sctps_hdrops);
5793238003Stuexen				goto out;
5794238003Stuexen			}
5795238003Stuexen			break;
5796238003Stuexen#endif
5797238003Stuexen#ifdef INET6
5798238003Stuexen		case AF_INET6:
5799238003Stuexen			if (ipsec6_in_reject(m, &inp->ip_inp.inp)) {
5800253571Sae				IPSEC6STAT_INC(ips_in_polvio);
5801238003Stuexen				SCTP_STAT_INCR(sctps_hdrops);
5802238003Stuexen				goto out;
5803238003Stuexen			}
5804238003Stuexen			break;
5805238003Stuexen#endif
5806238003Stuexen		default:
5807238003Stuexen			break;
5808238003Stuexen		}
5809238003Stuexen	}
5810238003Stuexen#endif
5811179783Srrs	SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n",
5812240148Stuexen	    (void *)m, iphlen, offset, length, (void *)stcb);
5813163953Srrs	if (stcb) {
5814163953Srrs		/* always clear this before beginning a packet */
5815163953Srrs		stcb->asoc.authenticated = 0;
5816163953Srrs		stcb->asoc.seen_a_sack_this_pkt = 0;
5817171990Srrs		SCTPDBG(SCTP_DEBUG_INPUT1, "stcb:%p state:%x\n",
5818240148Stuexen		    (void *)stcb, stcb->asoc.state);
5819171990Srrs
5820171943Srrs		if ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) ||
5821171943Srrs		    (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) {
5822171745Srrs			/*-
5823171745Srrs			 * If we hit here, we had a ref count
5824171745Srrs			 * up when the assoc was aborted and the
5825171745Srrs			 * timer is clearing out the assoc, we should
5826171745Srrs			 * NOT respond to any packet.. its OOTB.
5827171745Srrs			 */
5828171745Srrs			SCTP_TCB_UNLOCK(stcb);
5829238003Stuexen			stcb = NULL;
5830294174Stuexen			snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
5831267723Stuexen			op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
5832267723Stuexen			    msg);
5833267723Stuexen			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
5834284633Stuexen			    mflowtype, mflowid, inp->fibnum,
5835179157Srrs			    vrf_id, port);
5836238003Stuexen			goto out;
5837171745Srrs		}
5838163953Srrs	}
5839163953Srrs	if (IS_SCTP_CONTROL(ch)) {
5840163953Srrs		/* process the control portion of the SCTP packet */
5841169655Srrs		/* sa_ignore NO_NULL_CHK */
5842237715Stuexen		stcb = sctp_process_control(m, iphlen, &offset, length,
5843237715Stuexen		    src, dst, sh, ch,
5844237049Stuexen		    inp, stcb, &net, &fwd_tsn_seen,
5845284633Stuexen		    mflowtype, mflowid, fibnum,
5846237049Stuexen		    vrf_id, port);
5847163953Srrs		if (stcb) {
5848163953Srrs			/*
5849163953Srrs			 * This covers us if the cookie-echo was there and
5850163953Srrs			 * it changes our INP.
5851163953Srrs			 */
5852163953Srrs			inp = stcb->sctp_ep;
5853270350Stuexen#if defined(INET) || defined(INET6)
5854295208Stuexen			if ((ch->chunk_type != SCTP_INITIATION) &&
5855295208Stuexen			    (net != NULL) && (net->port != port)) {
5856179783Srrs				if (net->port == 0) {
5857295208Stuexen					/* UDP encapsulation turned on. */
5858295208Stuexen					net->mtu -= sizeof(struct udphdr);
5859295208Stuexen					if (stcb->asoc.smallest_mtu > net->mtu) {
5860295208Stuexen						sctp_pathmtu_adjustment(stcb, net->mtu);
5861295208Stuexen					}
5862295208Stuexen				} else if (port == 0) {
5863295208Stuexen					/* UDP encapsulation turned off. */
5864295208Stuexen					net->mtu += sizeof(struct udphdr);
5865295208Stuexen					/* XXX Update smallest_mtu */
5866179783Srrs				}
5867179783Srrs				net->port = port;
5868179783Srrs			}
5869270350Stuexen#endif
5870163953Srrs		}
5871163953Srrs	} else {
5872163953Srrs		/*
5873163953Srrs		 * no control chunks, so pre-process DATA chunks (these
5874163953Srrs		 * checks are taken care of by control processing)
5875163953Srrs		 */
5876163953Srrs
5877163953Srrs		/*
5878163953Srrs		 * if DATA only packet, and auth is required, then punt...
5879163953Srrs		 * can't have authenticated without any AUTH (control)
5880163953Srrs		 * chunks
5881163953Srrs		 */
5882179783Srrs		if ((stcb != NULL) &&
5883270362Stuexen		    (stcb->asoc.auth_supported == 1) &&
5884179783Srrs		    sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) {
5885163953Srrs			/* "silently" ignore */
5886163953Srrs			SCTP_STAT_INCR(sctps_recvauthmissing);
5887238003Stuexen			goto out;
5888163953Srrs		}
5889163953Srrs		if (stcb == NULL) {
5890163953Srrs			/* out of the blue DATA chunk */
5891294174Stuexen			snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
5892267723Stuexen			op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
5893267723Stuexen			    msg);
5894267723Stuexen			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
5895284633Stuexen			    mflowtype, mflowid, fibnum,
5896179157Srrs			    vrf_id, port);
5897238003Stuexen			goto out;
5898163953Srrs		}
5899163953Srrs		if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) {
5900163953Srrs			/* v_tag mismatch! */
5901163953Srrs			SCTP_STAT_INCR(sctps_badvtag);
5902238003Stuexen			goto out;
5903163953Srrs		}
5904163953Srrs	}
5905163953Srrs
5906163953Srrs	if (stcb == NULL) {
5907163953Srrs		/*
5908163953Srrs		 * no valid TCB for this packet, or we found it's a bad
5909163953Srrs		 * packet while processing control, or we're done with this
5910163953Srrs		 * packet (done or skip rest of data), so we drop it...
5911163953Srrs		 */
5912238003Stuexen		goto out;
5913163953Srrs	}
5914163953Srrs	/*
5915163953Srrs	 * DATA chunk processing
5916163953Srrs	 */
5917163953Srrs	/* plow through the data chunks while length > offset */
5918163953Srrs
5919163953Srrs	/*
5920163953Srrs	 * Rest should be DATA only.  Check authentication state if AUTH for
5921163953Srrs	 * DATA is required.
5922163953Srrs	 */
5923179783Srrs	if ((length > offset) &&
5924179783Srrs	    (stcb != NULL) &&
5925270362Stuexen	    (stcb->asoc.auth_supported == 1) &&
5926179783Srrs	    sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) &&
5927163953Srrs	    !stcb->asoc.authenticated) {
5928163953Srrs		/* "silently" ignore */
5929163953Srrs		SCTP_STAT_INCR(sctps_recvauthmissing);
5930169420Srrs		SCTPDBG(SCTP_DEBUG_AUTH1,
5931169420Srrs		    "Data chunk requires AUTH, skipped\n");
5932165220Srrs		goto trigger_send;
5933163953Srrs	}
5934163953Srrs	if (length > offset) {
5935163953Srrs		int retval;
5936163953Srrs
5937163953Srrs		/*
5938163953Srrs		 * First check to make sure our state is correct. We would
5939163953Srrs		 * not get here unless we really did have a tag, so we don't
5940163953Srrs		 * abort if this happens, just dump the chunk silently.
5941163953Srrs		 */
5942163953Srrs		switch (SCTP_GET_STATE(&stcb->asoc)) {
5943163953Srrs		case SCTP_STATE_COOKIE_ECHOED:
5944163953Srrs			/*
5945163953Srrs			 * we consider data with valid tags in this state
5946163953Srrs			 * shows us the cookie-ack was lost. Imply it was
5947163953Srrs			 * there.
5948163953Srrs			 */
5949179783Srrs			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5950171943Srrs				sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5951171943Srrs				    stcb->asoc.overall_error_count,
5952171943Srrs				    0,
5953171943Srrs				    SCTP_FROM_SCTP_INPUT,
5954171943Srrs				    __LINE__);
5955171943Srrs			}
5956163953Srrs			stcb->asoc.overall_error_count = 0;
5957163953Srrs			sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, net);
5958163953Srrs			break;
5959163953Srrs		case SCTP_STATE_COOKIE_WAIT:
5960163953Srrs			/*
5961163953Srrs			 * We consider OOTB any data sent during asoc setup.
5962163953Srrs			 */
5963294174Stuexen			snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s", __FILE__, __LINE__, __func__);
5964267723Stuexen			op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
5965267723Stuexen			    msg);
5966267723Stuexen			sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err,
5967284633Stuexen			    mflowtype, mflowid, inp->fibnum,
5968179157Srrs			    vrf_id, port);
5969238003Stuexen			goto out;
5970171531Srrs			/* sa_ignore NOTREACHED */
5971163953Srrs			break;
5972163953Srrs		case SCTP_STATE_EMPTY:	/* should not happen */
5973163953Srrs		case SCTP_STATE_INUSE:	/* should not happen */
5974163953Srrs		case SCTP_STATE_SHUTDOWN_RECEIVED:	/* This is a peer error */
5975163953Srrs		case SCTP_STATE_SHUTDOWN_ACK_SENT:
5976163953Srrs		default:
5977238003Stuexen			goto out;
5978171531Srrs			/* sa_ignore NOTREACHED */
5979163953Srrs			break;
5980163953Srrs		case SCTP_STATE_OPEN:
5981163953Srrs		case SCTP_STATE_SHUTDOWN_SENT:
5982163953Srrs			break;
5983163953Srrs		}
5984163953Srrs		/* plow through the data chunks while length > offset */
5985237715Stuexen		retval = sctp_process_data(mm, iphlen, &offset, length,
5986294147Stuexen		    inp, stcb, net, &high_tsn);
5987163953Srrs		if (retval == 2) {
5988163953Srrs			/*
5989163953Srrs			 * The association aborted, NO UNLOCK needed since
5990163953Srrs			 * the association is destroyed.
5991163953Srrs			 */
5992238003Stuexen			stcb = NULL;
5993238003Stuexen			goto out;
5994163953Srrs		}
5995163953Srrs		data_processed = 1;
5996163953Srrs		/*
5997163953Srrs		 * Anything important needs to have been m_copy'ed in
5998163953Srrs		 * process_data
5999163953Srrs		 */
6000163953Srrs	}
6001218129Srrs	/* take care of ecn */
6002228907Stuexen	if ((data_processed == 1) &&
6003270356Stuexen	    (stcb->asoc.ecn_supported == 1) &&
6004218235Stuexen	    ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) {
6005218129Srrs		/* Yep, we need to add a ECNE */
6006218129Srrs		sctp_send_ecn_echo(stcb, net, high_tsn);
6007218129Srrs	}
6008163953Srrs	if ((data_processed == 0) && (fwd_tsn_seen)) {
6009216495Stuexen		int was_a_gap;
6010216495Stuexen		uint32_t highest_tsn;
6011163953Srrs
6012216825Stuexen		if (SCTP_TSN_GT(stcb->asoc.highest_tsn_inside_nr_map, stcb->asoc.highest_tsn_inside_map)) {
6013216495Stuexen			highest_tsn = stcb->asoc.highest_tsn_inside_nr_map;
6014216495Stuexen		} else {
6015216495Stuexen			highest_tsn = stcb->asoc.highest_tsn_inside_map;
6016163953Srrs		}
6017216825Stuexen		was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn);
6018190689Srrs		stcb->asoc.send_sack = 1;
6019228653Stuexen		sctp_sack_check(stcb, was_a_gap);
6020190689Srrs	} else if (fwd_tsn_seen) {
6021190689Srrs		stcb->asoc.send_sack = 1;
6022163953Srrs	}
6023163953Srrs	/* trigger send of any chunks in queue... */
6024165220Srrstrigger_send:
6025163953Srrs#ifdef SCTP_AUDITING_ENABLED
6026163953Srrs	sctp_audit_log(0xE0, 2);
6027163953Srrs	sctp_auditing(1, inp, stcb, net);
6028163953Srrs#endif
6029169420Srrs	SCTPDBG(SCTP_DEBUG_INPUT1,
6030169420Srrs	    "Check for chunk output prw:%d tqe:%d tf=%d\n",
6031169420Srrs	    stcb->asoc.peers_rwnd,
6032169420Srrs	    TAILQ_EMPTY(&stcb->asoc.control_send_queue),
6033169420Srrs	    stcb->asoc.total_flight);
6034163953Srrs	un_sent = (stcb->asoc.total_output_queue_size - stcb->asoc.total_flight);
6035218129Srrs	if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) {
6036218129Srrs		cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq;
6037218129Srrs	}
6038294210Stuexen	if (cnt_ctrl_ready || stcb->asoc.trigger_reset ||
6039163953Srrs	    ((un_sent) &&
6040163953Srrs	    (stcb->asoc.peers_rwnd > 0 ||
6041163953Srrs	    (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) {
6042169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT3, "Calling chunk OUTPUT\n");
6043172090Srrs		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
6044169420Srrs		SCTPDBG(SCTP_DEBUG_INPUT3, "chunk OUTPUT returns\n");
6045163953Srrs	}
6046163953Srrs#ifdef SCTP_AUDITING_ENABLED
6047163953Srrs	sctp_audit_log(0xE0, 3);
6048163953Srrs	sctp_auditing(2, inp, stcb, net);
6049163953Srrs#endif
6050238003Stuexenout:
6051238003Stuexen	if (stcb != NULL) {
6052238003Stuexen		SCTP_TCB_UNLOCK(stcb);
6053238003Stuexen	}
6054238003Stuexen	if (inp_decr != NULL) {
6055238003Stuexen		/* reduce ref-count */
6056238003Stuexen		SCTP_INP_WLOCK(inp_decr);
6057238003Stuexen		SCTP_INP_DECR_REF(inp_decr);
6058238003Stuexen		SCTP_INP_WUNLOCK(inp_decr);
6059238003Stuexen	}
6060169378Srrs	return;
6061163953Srrs}
6062163953Srrs
6063185694Srrs#if 0
6064185694Srrsstatic void
6065185694Srrssctp_print_mbuf_chain(struct mbuf *m)
6066185694Srrs{
6067185694Srrs	for (; m; m = SCTP_BUF_NEXT(m)) {
6068240148Stuexen		SCTP_PRINTF("%p: m_len = %ld\n", (void *)m, SCTP_BUF_LEN(m));
6069185694Srrs		if (SCTP_BUF_IS_EXTENDED(m))
6070240148Stuexen			SCTP_PRINTF("%p: extend_size = %d\n", (void *)m, SCTP_BUF_EXTEND_SIZE(m));
6071185694Srrs	}
6072185694Srrs}
6073163953Srrs
6074185694Srrs#endif
6075185694Srrs
6076221249Stuexen#ifdef INET
6077163953Srrsvoid
6078189004Srdivackysctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
6079163953Srrs{
6080165647Srrs	struct mbuf *m;
6081163953Srrs	int iphlen;
6082170181Srrs	uint32_t vrf_id = 0;
6083163953Srrs	uint8_t ecn_bits;
6084237715Stuexen	struct sockaddr_in src, dst;
6085163953Srrs	struct ip *ip;
6086163953Srrs	struct sctphdr *sh;
6087237569Stuexen	struct sctp_chunkhdr *ch;
6088237569Stuexen	int length, offset;
6089163953Srrs
6090211969Stuexen#if !defined(SCTP_WITH_NO_CSUM)
6091238003Stuexen	uint8_t compute_crc;
6092211969Stuexen
6093211969Stuexen#endif
6094238003Stuexen	uint32_t mflowid;
6095281955Shiren	uint8_t mflowtype;
6096284633Stuexen	uint16_t fibnum;
6097211969Stuexen
6098237569Stuexen	iphlen = off;
6099169352Srrs	if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) {
6100169352Srrs		SCTP_RELEASE_PKT(i_pak);
6101169352Srrs		return;
6102169352Srrs	}
6103165647Srrs	m = SCTP_HEADER_TO_CHAIN(i_pak);
6104163953Srrs#ifdef SCTP_MBUF_LOGGING
6105163953Srrs	/* Log in any input mbufs */
6106179783Srrs	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
6107283708Stuexen		sctp_log_mbc(m, SCTP_MBUF_INPUT);
6108163953Srrs	}
6109163953Srrs#endif
6110237540Stuexen#ifdef SCTP_PACKET_LOGGING
6111237569Stuexen	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
6112237540Stuexen		sctp_packet_log(m);
6113237569Stuexen	}
6114170091Srrs#endif
6115238003Stuexen	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
6116254854Stuexen	    "sctp_input(): Packet of length %d received on %s with csum_flags 0x%b.\n",
6117238003Stuexen	    m->m_pkthdr.len,
6118238003Stuexen	    if_name(m->m_pkthdr.rcvif),
6119254854Stuexen	    (int)m->m_pkthdr.csum_flags, CSUM_BITS);
6120281955Shiren	mflowid = m->m_pkthdr.flowid;
6121281955Shiren	mflowtype = M_HASHTYPE_GET(m);
6122284633Stuexen	fibnum = M_GETFIB(m);
6123237569Stuexen	SCTP_STAT_INCR(sctps_recvpackets);
6124237569Stuexen	SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
6125237569Stuexen	/* Get IP, SCTP, and first chunk header together in the first mbuf. */
6126237569Stuexen	offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
6127165647Srrs	if (SCTP_BUF_LEN(m) < offset) {
6128237715Stuexen		if ((m = m_pullup(m, offset)) == NULL) {
6129163953Srrs			SCTP_STAT_INCR(sctps_hdrops);
6130163953Srrs			return;
6131163953Srrs		}
6132163953Srrs	}
6133237715Stuexen	ip = mtod(m, struct ip *);
6134237569Stuexen	sh = (struct sctphdr *)((caddr_t)ip + iphlen);
6135237569Stuexen	ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
6136237569Stuexen	offset -= sizeof(struct sctp_chunkhdr);
6137237715Stuexen	memset(&src, 0, sizeof(struct sockaddr_in));
6138237715Stuexen	src.sin_family = AF_INET;
6139237715Stuexen	src.sin_len = sizeof(struct sockaddr_in);
6140237715Stuexen	src.sin_port = sh->src_port;
6141237715Stuexen	src.sin_addr = ip->ip_src;
6142237715Stuexen	memset(&dst, 0, sizeof(struct sockaddr_in));
6143237715Stuexen	dst.sin_family = AF_INET;
6144237715Stuexen	dst.sin_len = sizeof(struct sockaddr_in);
6145237715Stuexen	dst.sin_port = sh->dest_port;
6146237715Stuexen	dst.sin_addr = ip->ip_dst;
6147241923Sglebius	length = ntohs(ip->ip_len);
6148237569Stuexen	/* Validate mbuf chain length with IP payload length. */
6149238003Stuexen	if (SCTP_HEADER_LEN(m) != length) {
6150237569Stuexen		SCTPDBG(SCTP_DEBUG_INPUT1,
6151238003Stuexen		    "sctp_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
6152188067Srrs		SCTP_STAT_INCR(sctps_hdrops);
6153238003Stuexen		goto out;
6154188067Srrs	}
6155163953Srrs	/* SCTP does not allow broadcasts or multicasts */
6156237715Stuexen	if (IN_MULTICAST(ntohl(dst.sin_addr.s_addr))) {
6157238003Stuexen		goto out;
6158163953Srrs	}
6159237715Stuexen	if (SCTP_IS_IT_BROADCAST(dst.sin_addr, m)) {
6160238003Stuexen		goto out;
6161163953Srrs	}
6162238003Stuexen	ecn_bits = ip->ip_tos;
6163211969Stuexen#if defined(SCTP_WITH_NO_CSUM)
6164211969Stuexen	SCTP_STAT_INCR(sctps_recvnocrc);
6165211969Stuexen#else
6166188067Srrs	if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
6167188067Srrs		SCTP_STAT_INCR(sctps_recvhwcrc);
6168238003Stuexen		compute_crc = 0;
6169238003Stuexen	} else {
6170238003Stuexen		SCTP_STAT_INCR(sctps_recvswcrc);
6171238003Stuexen		compute_crc = 1;
6172188067Srrs	}
6173218400Stuexen#endif
6174238003Stuexen	sctp_common_input_processing(&m, iphlen, offset, length,
6175237715Stuexen	    (struct sockaddr *)&src,
6176237715Stuexen	    (struct sockaddr *)&dst,
6177238003Stuexen	    sh, ch,
6178238003Stuexen#if !defined(SCTP_WITH_NO_CSUM)
6179238003Stuexen	    compute_crc,
6180218400Stuexen#endif
6181238003Stuexen	    ecn_bits,
6182284633Stuexen	    mflowtype, mflowid, fibnum,
6183237049Stuexen	    vrf_id, port);
6184238003Stuexenout:
6185163953Srrs	if (m) {
6186163953Srrs		sctp_m_freem(m);
6187163953Srrs	}
6188163953Srrs	return;
6189163953Srrs}
6190218211Srrs
6191218269Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
6192218269Srrsextern int *sctp_cpuarry;
6193218211Srrs
6194218269Srrs#endif
6195218269Srrs
6196179157Srrsvoid
6197218211Srrssctp_input(struct mbuf *m, int off)
6198179157Srrs{
6199218211Srrs#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
6200218211Srrs	struct ip *ip;
6201218211Srrs	struct sctphdr *sh;
6202218211Srrs	int offset;
6203218211Srrs	int cpu_to_use;
6204218371Srrs	uint32_t flowid, tag;
6205218211Srrs
6206218269Srrs	if (mp_ncpus > 1) {
6207281955Shiren		if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
6208218371Srrs			flowid = m->m_pkthdr.flowid;
6209218269Srrs		} else {
6210218269Srrs			/*
6211218371Srrs			 * No flow id built by lower layers fix it so we
6212218371Srrs			 * create one.
6213218269Srrs			 */
6214237715Stuexen			offset = off + sizeof(struct sctphdr);
6215218371Srrs			if (SCTP_BUF_LEN(m) < offset) {
6216237715Stuexen				if ((m = m_pullup(m, offset)) == NULL) {
6217218371Srrs					SCTP_STAT_INCR(sctps_hdrops);
6218218371Srrs					return;
6219218371Srrs				}
6220218371Srrs			}
6221237715Stuexen			ip = mtod(m, struct ip *);
6222218371Srrs			sh = (struct sctphdr *)((caddr_t)ip + off);
6223218371Srrs			tag = htonl(sh->v_tag);
6224218371Srrs			flowid = tag ^ ntohs(sh->dest_port) ^ ntohs(sh->src_port);
6225218371Srrs			m->m_pkthdr.flowid = flowid;
6226281955Shiren			M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE);
6227218269Srrs		}
6228218371Srrs		cpu_to_use = sctp_cpuarry[flowid % mp_ncpus];
6229218211Srrs		sctp_queue_to_mcore(m, off, cpu_to_use);
6230218211Srrs		return;
6231218211Srrs	}
6232218211Srrs#endif
6233218211Srrs	sctp_input_with_port(m, off, 0);
6234179157Srrs}
6235221249Stuexen
6236221249Stuexen#endif
6237