sctp_input.c revision 235414
10Sstevel@tonic-gate/*-
20Sstevel@tonic-gate * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
30Sstevel@tonic-gate * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved.
40Sstevel@tonic-gate * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved.
51623Stw21770 *
61623Stw21770 * Redistribution and use in source and binary forms, with or without
70Sstevel@tonic-gate * modification, are permitted provided that the following conditions are met:
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * a) Redistributions of source code must retain the above copyright notice,
100Sstevel@tonic-gate *    this list of conditions and the following disclaimer.
110Sstevel@tonic-gate *
120Sstevel@tonic-gate * b) Redistributions in binary form must reproduce the above copyright
130Sstevel@tonic-gate *    notice, this list of conditions and the following disclaimer in
140Sstevel@tonic-gate *    the documentation and/or other materials provided with the distribution.
150Sstevel@tonic-gate *
160Sstevel@tonic-gate * c) Neither the name of Cisco Systems, Inc. nor the names of its
170Sstevel@tonic-gate *    contributors may be used to endorse or promote products derived
180Sstevel@tonic-gate *    from this software without specific prior written permission.
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
217563SPrasad.Singamsetty@Sun.COM * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
220Sstevel@tonic-gate * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
239017SJohn.Wren.Kennedy@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
240Sstevel@tonic-gate * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
250Sstevel@tonic-gate * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
260Sstevel@tonic-gate * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
270Sstevel@tonic-gate * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
280Sstevel@tonic-gate * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
290Sstevel@tonic-gate * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
300Sstevel@tonic-gate * THE POSSIBILITY OF SUCH DAMAGE.
310Sstevel@tonic-gate */
320Sstevel@tonic-gate
330Sstevel@tonic-gate/* $KAME: sctp_input.c,v 1.27 2005/03/06 16:04:17 itojun Exp $	 */
340Sstevel@tonic-gate
350Sstevel@tonic-gate#include <sys/cdefs.h>
360Sstevel@tonic-gate__FBSDID("$FreeBSD: head/sys/netinet/sctp_input.c 235414 2012-05-13 17:36:04Z tuexen $");
370Sstevel@tonic-gate
380Sstevel@tonic-gate#include <netinet/sctp_os.h>
390Sstevel@tonic-gate#include <netinet/sctp_var.h>
400Sstevel@tonic-gate#include <netinet/sctp_sysctl.h>
410Sstevel@tonic-gate#include <netinet/sctp_pcb.h>
420Sstevel@tonic-gate#include <netinet/sctp_header.h>
430Sstevel@tonic-gate#include <netinet/sctputil.h>
440Sstevel@tonic-gate#include <netinet/sctp_output.h>
450Sstevel@tonic-gate#include <netinet/sctp_input.h>
460Sstevel@tonic-gate#include <netinet/sctp_auth.h>
470Sstevel@tonic-gate#include <netinet/sctp_indata.h>
480Sstevel@tonic-gate#include <netinet/sctp_asconf.h>
490Sstevel@tonic-gate#include <netinet/sctp_bsd_addr.h>
500Sstevel@tonic-gate#include <netinet/sctp_timer.h>
510Sstevel@tonic-gate#include <netinet/sctp_crc32.h>
520Sstevel@tonic-gate#include <netinet/udp.h>
530Sstevel@tonic-gate#include <sys/smp.h>
540Sstevel@tonic-gate
550Sstevel@tonic-gate
560Sstevel@tonic-gate
570Sstevel@tonic-gatestatic void
580Sstevel@tonic-gatesctp_stop_all_cookie_timers(struct sctp_tcb *stcb)
590Sstevel@tonic-gate{
600Sstevel@tonic-gate	struct sctp_nets *net;
610Sstevel@tonic-gate
620Sstevel@tonic-gate	/*
630Sstevel@tonic-gate	 * This now not only stops all cookie timers it also stops any INIT
640Sstevel@tonic-gate	 * timers as well. This will make sure that the timers are stopped
650Sstevel@tonic-gate	 * in all collision cases.
660Sstevel@tonic-gate	 */
670Sstevel@tonic-gate	SCTP_TCB_LOCK_ASSERT(stcb);
680Sstevel@tonic-gate	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
690Sstevel@tonic-gate		if (net->rxt_timer.type == SCTP_TIMER_TYPE_COOKIE) {
700Sstevel@tonic-gate			sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE,
710Sstevel@tonic-gate			    stcb->sctp_ep,
720Sstevel@tonic-gate			    stcb,
730Sstevel@tonic-gate			    net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_1);
740Sstevel@tonic-gate		} else if (net->rxt_timer.type == SCTP_TIMER_TYPE_INIT) {
751623Stw21770			sctp_timer_stop(SCTP_TIMER_TYPE_INIT,
760Sstevel@tonic-gate			    stcb->sctp_ep,
770Sstevel@tonic-gate			    stcb,
780Sstevel@tonic-gate			    net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_2);
790Sstevel@tonic-gate		}
800Sstevel@tonic-gate	}
810Sstevel@tonic-gate}
820Sstevel@tonic-gate
830Sstevel@tonic-gate/* INIT handler */
840Sstevel@tonic-gatestatic void
850Sstevel@tonic-gatesctp_handle_init(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
860Sstevel@tonic-gate    struct sctp_init_chunk *cp, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
870Sstevel@tonic-gate    int *abort_no_unlock, uint32_t vrf_id, uint16_t port)
880Sstevel@tonic-gate{
890Sstevel@tonic-gate	struct sctp_init *init;
900Sstevel@tonic-gate	struct mbuf *op_err;
910Sstevel@tonic-gate
920Sstevel@tonic-gate	SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_init: handling INIT tcb:%p\n",
930Sstevel@tonic-gate	    stcb);
940Sstevel@tonic-gate	if (stcb == NULL) {
950Sstevel@tonic-gate		SCTP_INP_RLOCK(inp);
960Sstevel@tonic-gate	}
970Sstevel@tonic-gate	/* validate length */
980Sstevel@tonic-gate	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) {
990Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1000Sstevel@tonic-gate		sctp_abort_association(inp, stcb, m, iphlen, sh, op_err,
1010Sstevel@tonic-gate		    vrf_id, port);
1020Sstevel@tonic-gate		if (stcb)
1030Sstevel@tonic-gate			*abort_no_unlock = 1;
1040Sstevel@tonic-gate		goto outnow;
1050Sstevel@tonic-gate	}
1060Sstevel@tonic-gate	/* validate parameters */
1070Sstevel@tonic-gate	init = &cp->init;
1080Sstevel@tonic-gate	if (init->initiate_tag == 0) {
1090Sstevel@tonic-gate		/* protocol error... send abort */
1100Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1110Sstevel@tonic-gate		sctp_abort_association(inp, stcb, m, iphlen, sh, op_err,
1120Sstevel@tonic-gate		    vrf_id, port);
1130Sstevel@tonic-gate		if (stcb)
1140Sstevel@tonic-gate			*abort_no_unlock = 1;
1150Sstevel@tonic-gate		goto outnow;
1160Sstevel@tonic-gate	}
1170Sstevel@tonic-gate	if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) {
1180Sstevel@tonic-gate		/* invalid parameter... send abort */
1190Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1200Sstevel@tonic-gate		sctp_abort_association(inp, stcb, m, iphlen, sh, op_err,
1210Sstevel@tonic-gate		    vrf_id, port);
1220Sstevel@tonic-gate		if (stcb)
1230Sstevel@tonic-gate			*abort_no_unlock = 1;
1240Sstevel@tonic-gate		goto outnow;
1250Sstevel@tonic-gate	}
1260Sstevel@tonic-gate	if (init->num_inbound_streams == 0) {
1270Sstevel@tonic-gate		/* protocol error... send abort */
1280Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1290Sstevel@tonic-gate		sctp_abort_association(inp, stcb, m, iphlen, sh, op_err,
1300Sstevel@tonic-gate		    vrf_id, port);
1310Sstevel@tonic-gate		if (stcb)
1320Sstevel@tonic-gate			*abort_no_unlock = 1;
1330Sstevel@tonic-gate		goto outnow;
1340Sstevel@tonic-gate	}
1350Sstevel@tonic-gate	if (init->num_outbound_streams == 0) {
1360Sstevel@tonic-gate		/* protocol error... send abort */
1370Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1380Sstevel@tonic-gate		sctp_abort_association(inp, stcb, m, iphlen, sh, op_err,
1390Sstevel@tonic-gate		    vrf_id, port);
1400Sstevel@tonic-gate		if (stcb)
1410Sstevel@tonic-gate			*abort_no_unlock = 1;
1420Sstevel@tonic-gate		goto outnow;
1430Sstevel@tonic-gate	}
1440Sstevel@tonic-gate	if (sctp_validate_init_auth_params(m, offset + sizeof(*cp),
1450Sstevel@tonic-gate	    offset + ntohs(cp->ch.chunk_length))) {
1460Sstevel@tonic-gate		/* auth parameter(s) error... send abort */
1470Sstevel@tonic-gate		sctp_abort_association(inp, stcb, m, iphlen, sh, NULL, vrf_id, port);
1480Sstevel@tonic-gate		if (stcb)
1490Sstevel@tonic-gate			*abort_no_unlock = 1;
1500Sstevel@tonic-gate		goto outnow;
1510Sstevel@tonic-gate	}
1520Sstevel@tonic-gate	/*
1530Sstevel@tonic-gate	 * We are only accepting if we have a socket with positive
1540Sstevel@tonic-gate	 * so_qlimit.
1550Sstevel@tonic-gate	 */
1560Sstevel@tonic-gate	if ((stcb == NULL) &&
1570Sstevel@tonic-gate	    ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
1580Sstevel@tonic-gate	    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
1590Sstevel@tonic-gate	    (inp->sctp_socket == NULL) ||
1600Sstevel@tonic-gate	    (inp->sctp_socket->so_qlimit == 0))) {
1610Sstevel@tonic-gate		/*
1620Sstevel@tonic-gate		 * FIX ME ?? What about TCP model and we have a
1630Sstevel@tonic-gate		 * match/restart case? Actually no fix is needed. the lookup
1640Sstevel@tonic-gate		 * will always find the existing assoc so stcb would not be
1650Sstevel@tonic-gate		 * NULL. It may be questionable to do this since we COULD
1660Sstevel@tonic-gate		 * just send back the INIT-ACK and hope that the app did
1670Sstevel@tonic-gate		 * accept()'s by the time the COOKIE was sent. But there is
1680Sstevel@tonic-gate		 * a price to pay for COOKIE generation and I don't want to
1690Sstevel@tonic-gate		 * pay it on the chance that the app will actually do some
1700Sstevel@tonic-gate		 * accepts(). The App just looses and should NOT be in this
1710Sstevel@tonic-gate		 * state :-)
1720Sstevel@tonic-gate		 */
1730Sstevel@tonic-gate		if (SCTP_BASE_SYSCTL(sctp_blackhole) == 0) {
1740Sstevel@tonic-gate			sctp_send_abort(m, iphlen, sh, 0, NULL, vrf_id, port);
1750Sstevel@tonic-gate		}
1760Sstevel@tonic-gate		goto outnow;
1770Sstevel@tonic-gate	}
1780Sstevel@tonic-gate	if ((stcb != NULL) &&
1790Sstevel@tonic-gate	    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT)) {
1800Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending SHUTDOWN-ACK\n");
1810Sstevel@tonic-gate		sctp_send_shutdown_ack(stcb, NULL);
1820Sstevel@tonic-gate		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
1830Sstevel@tonic-gate	} else {
1840Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT3, "sctp_handle_init: sending INIT-ACK\n");
1850Sstevel@tonic-gate		sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, sh, cp, vrf_id, port,
1860Sstevel@tonic-gate		    ((stcb == NULL) ? SCTP_HOLDS_LOCK : SCTP_NOT_LOCKED));
1870Sstevel@tonic-gate	}
1880Sstevel@tonic-gateoutnow:
1890Sstevel@tonic-gate	if (stcb == NULL) {
1900Sstevel@tonic-gate		SCTP_INP_RUNLOCK(inp);
1910Sstevel@tonic-gate	}
1920Sstevel@tonic-gate}
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate/*
1950Sstevel@tonic-gate * process peer "INIT/INIT-ACK" chunk returns value < 0 on error
1964954Sachimm */
1970Sstevel@tonic-gate
1980Sstevel@tonic-gateint
1990Sstevel@tonic-gatesctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked
2000Sstevel@tonic-gate#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
2010Sstevel@tonic-gate    SCTP_UNUSED
2020Sstevel@tonic-gate#endif
2030Sstevel@tonic-gate)
2044954Sachimm{
2050Sstevel@tonic-gate	int unsent_data = 0;
2060Sstevel@tonic-gate	unsigned int i;
2070Sstevel@tonic-gate	struct sctp_stream_queue_pending *sp;
2084954Sachimm	struct sctp_association *asoc;
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate	/*
2110Sstevel@tonic-gate	 * This function returns the number of streams that have true unsent
2120Sstevel@tonic-gate	 * data on them. Note that as it looks through it will clean up any
2130Sstevel@tonic-gate	 * places that have old data that has been sent but left at top of
2140Sstevel@tonic-gate	 * stream queue.
2150Sstevel@tonic-gate	 */
2160Sstevel@tonic-gate	asoc = &stcb->asoc;
2170Sstevel@tonic-gate	SCTP_TCB_SEND_LOCK(stcb);
2180Sstevel@tonic-gate	if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
2190Sstevel@tonic-gate		/* Check to see if some data queued */
2200Sstevel@tonic-gate		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
2210Sstevel@tonic-gate			/* sa_ignore FREED_MEMORY */
2220Sstevel@tonic-gate			sp = TAILQ_FIRST(&stcb->asoc.strmout[i].outqueue);
2230Sstevel@tonic-gate			if (sp == NULL) {
2240Sstevel@tonic-gate				continue;
2250Sstevel@tonic-gate			}
2260Sstevel@tonic-gate			if ((sp->msg_is_complete) &&
2270Sstevel@tonic-gate			    (sp->length == 0) &&
2280Sstevel@tonic-gate			    (sp->sender_all_done)) {
2290Sstevel@tonic-gate				/*
2300Sstevel@tonic-gate				 * We are doing differed cleanup. Last time
2311623Stw21770				 * through when we took all the data the
2320Sstevel@tonic-gate				 * sender_all_done was not set.
2330Sstevel@tonic-gate				 */
2340Sstevel@tonic-gate				if (sp->put_last_out == 0) {
2350Sstevel@tonic-gate					SCTP_PRINTF("Gak, put out entire msg with NO end!-1\n");
2360Sstevel@tonic-gate					SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d\n",
2370Sstevel@tonic-gate					    sp->sender_all_done,
2380Sstevel@tonic-gate					    sp->length,
2390Sstevel@tonic-gate					    sp->msg_is_complete,
2400Sstevel@tonic-gate					    sp->put_last_out);
2410Sstevel@tonic-gate				}
2420Sstevel@tonic-gate				atomic_subtract_int(&stcb->asoc.stream_queue_cnt, 1);
2430Sstevel@tonic-gate				TAILQ_REMOVE(&stcb->asoc.strmout[i].outqueue, sp, next);
2440Sstevel@tonic-gate				if (sp->net) {
2450Sstevel@tonic-gate					sctp_free_remote_addr(sp->net);
2460Sstevel@tonic-gate					sp->net = NULL;
2470Sstevel@tonic-gate				}
2480Sstevel@tonic-gate				if (sp->data) {
2490Sstevel@tonic-gate					sctp_m_freem(sp->data);
2500Sstevel@tonic-gate					sp->data = NULL;
2510Sstevel@tonic-gate				}
2527627SChris.Horne@Sun.COM				sctp_free_a_strmoq(stcb, sp, so_locked);
2530Sstevel@tonic-gate			} else {
2547627SChris.Horne@Sun.COM				unsent_data++;
2550Sstevel@tonic-gate				break;
2560Sstevel@tonic-gate			}
2574954Sachimm		}
2580Sstevel@tonic-gate	}
2590Sstevel@tonic-gate	SCTP_TCB_SEND_UNLOCK(stcb);
2600Sstevel@tonic-gate	return (unsent_data);
2617627SChris.Horne@Sun.COM}
2620Sstevel@tonic-gate
2637627SChris.Horne@Sun.COMstatic int
2640Sstevel@tonic-gatesctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
2650Sstevel@tonic-gate{
2660Sstevel@tonic-gate	struct sctp_init *init;
2670Sstevel@tonic-gate	struct sctp_association *asoc;
2681623Stw21770	struct sctp_nets *lnet;
2691623Stw21770	unsigned int i;
2701623Stw21770
2711623Stw21770	init = &cp->init;
2721623Stw21770	asoc = &stcb->asoc;
2730Sstevel@tonic-gate	/* save off parameters */
2740Sstevel@tonic-gate	asoc->peer_vtag = ntohl(init->initiate_tag);
2750Sstevel@tonic-gate	asoc->peers_rwnd = ntohl(init->a_rwnd);
2760Sstevel@tonic-gate	/* init tsn's */
2770Sstevel@tonic-gate	asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1;
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate	if (!TAILQ_EMPTY(&asoc->nets)) {
2800Sstevel@tonic-gate		/* update any ssthresh's that may have a default */
2810Sstevel@tonic-gate		TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) {
2820Sstevel@tonic-gate			lnet->ssthresh = asoc->peers_rwnd;
2830Sstevel@tonic-gate			if (SCTP_BASE_SYSCTL(sctp_logging_level) & (SCTP_CWND_MONITOR_ENABLE | SCTP_CWND_LOGGING_ENABLE)) {
2840Sstevel@tonic-gate				sctp_log_cwnd(stcb, lnet, 0, SCTP_CWND_INITIALIZATION);
2850Sstevel@tonic-gate			}
2860Sstevel@tonic-gate		}
2870Sstevel@tonic-gate	}
2880Sstevel@tonic-gate	SCTP_TCB_SEND_LOCK(stcb);
2890Sstevel@tonic-gate	if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) {
2900Sstevel@tonic-gate		unsigned int newcnt;
2910Sstevel@tonic-gate		struct sctp_stream_out *outs;
2920Sstevel@tonic-gate		struct sctp_stream_queue_pending *sp, *nsp;
2930Sstevel@tonic-gate		struct sctp_tmit_chunk *chk, *nchk;
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate		/* abandon the upper streams */
2960Sstevel@tonic-gate		newcnt = ntohs(init->num_inbound_streams);
2970Sstevel@tonic-gate		TAILQ_FOREACH_SAFE(chk, &asoc->send_queue, sctp_next, nchk) {
2980Sstevel@tonic-gate			if (chk->rec.data.stream_number >= newcnt) {
2990Sstevel@tonic-gate				TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
3000Sstevel@tonic-gate				asoc->send_queue_cnt--;
3010Sstevel@tonic-gate				if (chk->data != NULL) {
3020Sstevel@tonic-gate					sctp_free_bufspace(stcb, asoc, chk, 1);
3030Sstevel@tonic-gate					sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
3040Sstevel@tonic-gate					    SCTP_NOTIFY_DATAGRAM_UNSENT, chk, SCTP_SO_NOT_LOCKED);
3050Sstevel@tonic-gate					if (chk->data) {
3060Sstevel@tonic-gate						sctp_m_freem(chk->data);
3070Sstevel@tonic-gate						chk->data = NULL;
3080Sstevel@tonic-gate					}
3090Sstevel@tonic-gate				}
3100Sstevel@tonic-gate				sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
3110Sstevel@tonic-gate				/* sa_ignore FREED_MEMORY */
3120Sstevel@tonic-gate			}
3130Sstevel@tonic-gate		}
3140Sstevel@tonic-gate		if (asoc->strmout) {
3150Sstevel@tonic-gate			for (i = newcnt; i < asoc->pre_open_streams; i++) {
3160Sstevel@tonic-gate				outs = &asoc->strmout[i];
3170Sstevel@tonic-gate				TAILQ_FOREACH_SAFE(sp, &outs->outqueue, next, nsp) {
3180Sstevel@tonic-gate					TAILQ_REMOVE(&outs->outqueue, sp, next);
3190Sstevel@tonic-gate					asoc->stream_queue_cnt--;
3200Sstevel@tonic-gate					sctp_ulp_notify(SCTP_NOTIFY_SPECIAL_SP_FAIL,
3210Sstevel@tonic-gate					    stcb, SCTP_NOTIFY_DATAGRAM_UNSENT,
3220Sstevel@tonic-gate					    sp, SCTP_SO_NOT_LOCKED);
3230Sstevel@tonic-gate					if (sp->data) {
3240Sstevel@tonic-gate						sctp_m_freem(sp->data);
3250Sstevel@tonic-gate						sp->data = NULL;
3260Sstevel@tonic-gate					}
3270Sstevel@tonic-gate					if (sp->net) {
3280Sstevel@tonic-gate						sctp_free_remote_addr(sp->net);
3290Sstevel@tonic-gate						sp->net = NULL;
3304954Sachimm					}
3310Sstevel@tonic-gate					/* Free the chunk */
3320Sstevel@tonic-gate					sctp_free_a_strmoq(stcb, sp, SCTP_SO_NOT_LOCKED);
3330Sstevel@tonic-gate					/* sa_ignore FREED_MEMORY */
3340Sstevel@tonic-gate				}
3350Sstevel@tonic-gate			}
3360Sstevel@tonic-gate		}
3370Sstevel@tonic-gate		/* cut back the count */
3380Sstevel@tonic-gate		asoc->pre_open_streams = newcnt;
3390Sstevel@tonic-gate	}
3400Sstevel@tonic-gate	SCTP_TCB_SEND_UNLOCK(stcb);
3410Sstevel@tonic-gate	asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams;
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate	/* EY - nr_sack: initialize highest tsn in nr_mapping_array */
3440Sstevel@tonic-gate	asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map;
3450Sstevel@tonic-gate	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
3460Sstevel@tonic-gate		sctp_log_map(0, 5, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
3474954Sachimm	}
3480Sstevel@tonic-gate	/* This is the next one we expect */
3490Sstevel@tonic-gate	asoc->str_reset_seq_in = asoc->asconf_seq_in + 1;
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate	asoc->mapping_array_base_tsn = ntohl(init->initial_tsn);
3520Sstevel@tonic-gate	asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->asconf_seq_in;
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate	asoc->advanced_peer_ack_point = asoc->last_acked_seq;
3550Sstevel@tonic-gate	/* open the requested streams */
3560Sstevel@tonic-gate
3570Sstevel@tonic-gate	if (asoc->strmin != NULL) {
3580Sstevel@tonic-gate		/* Free the old ones */
3590Sstevel@tonic-gate		struct sctp_queued_to_read *ctl, *nctl;
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate		for (i = 0; i < asoc->streamincnt; i++) {
3620Sstevel@tonic-gate			TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) {
3630Sstevel@tonic-gate				TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next);
3640Sstevel@tonic-gate				sctp_free_remote_addr(ctl->whoFrom);
3650Sstevel@tonic-gate				ctl->whoFrom = NULL;
3661623Stw21770				sctp_m_freem(ctl->data);
3670Sstevel@tonic-gate				ctl->data = NULL;
3680Sstevel@tonic-gate				sctp_free_a_readq(stcb, ctl);
3690Sstevel@tonic-gate			}
3700Sstevel@tonic-gate		}
3710Sstevel@tonic-gate		SCTP_FREE(asoc->strmin, SCTP_M_STRMI);
3720Sstevel@tonic-gate	}
3730Sstevel@tonic-gate	asoc->streamincnt = ntohs(init->num_outbound_streams);
3740Sstevel@tonic-gate	if (asoc->streamincnt > MAX_SCTP_STREAMS) {
3750Sstevel@tonic-gate		asoc->streamincnt = MAX_SCTP_STREAMS;
3760Sstevel@tonic-gate	}
3770Sstevel@tonic-gate	SCTP_MALLOC(asoc->strmin, struct sctp_stream_in *, asoc->streamincnt *
3780Sstevel@tonic-gate	    sizeof(struct sctp_stream_in), SCTP_M_STRMI);
3790Sstevel@tonic-gate	if (asoc->strmin == NULL) {
3800Sstevel@tonic-gate		/* we didn't get memory for the streams! */
3810Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT2, "process_init: couldn't get memory for the streams!\n");
3820Sstevel@tonic-gate		return (-1);
3830Sstevel@tonic-gate	}
3840Sstevel@tonic-gate	for (i = 0; i < asoc->streamincnt; i++) {
3850Sstevel@tonic-gate		asoc->strmin[i].stream_no = i;
3860Sstevel@tonic-gate		asoc->strmin[i].last_sequence_delivered = 0xffff;
3870Sstevel@tonic-gate		/*
3880Sstevel@tonic-gate		 * U-stream ranges will be set when the cookie is unpacked.
3890Sstevel@tonic-gate		 * Or for the INIT sender they are un set (if pr-sctp not
3900Sstevel@tonic-gate		 * supported) when the INIT-ACK arrives.
3910Sstevel@tonic-gate		 */
3920Sstevel@tonic-gate		TAILQ_INIT(&asoc->strmin[i].inqueue);
3930Sstevel@tonic-gate		asoc->strmin[i].delivery_started = 0;
3940Sstevel@tonic-gate	}
3950Sstevel@tonic-gate	/*
3960Sstevel@tonic-gate	 * load_address_from_init will put the addresses into the
3970Sstevel@tonic-gate	 * association when the COOKIE is processed or the INIT-ACK is
3980Sstevel@tonic-gate	 * processed. Both types of COOKIE's existing and new call this
3990Sstevel@tonic-gate	 * routine. It will remove addresses that are no longer in the
4000Sstevel@tonic-gate	 * association (for the restarting case where addresses are
4010Sstevel@tonic-gate	 * removed). Up front when the INIT arrives we will discard it if it
4020Sstevel@tonic-gate	 * is a restart and new addresses have been added.
4030Sstevel@tonic-gate	 */
4040Sstevel@tonic-gate	/* sa_ignore MEMLEAK */
4050Sstevel@tonic-gate	return (0);
4061623Stw21770}
4071623Stw21770
4081623Stw21770/*
4091623Stw21770 * INIT-ACK message processing/consumption returns value < 0 on error
4101623Stw21770 */
4111623Stw21770static int
4121623Stw21770sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
4131623Stw21770    struct sctphdr *sh, struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
4141623Stw21770    struct sctp_nets *net, int *abort_no_unlock, uint32_t vrf_id)
4151623Stw21770{
4161623Stw21770	struct sctp_association *asoc;
4171623Stw21770	struct mbuf *op_err;
4181623Stw21770	int retval, abort_flag;
4191623Stw21770	uint32_t initack_limit;
4201623Stw21770	int nat_friendly = 0;
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate	/* First verify that we have no illegal param's */
4230Sstevel@tonic-gate	abort_flag = 0;
4240Sstevel@tonic-gate	op_err = NULL;
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate	op_err = sctp_arethere_unrecognized_parameters(m,
4270Sstevel@tonic-gate	    (offset + sizeof(struct sctp_init_chunk)),
4280Sstevel@tonic-gate	    &abort_flag, (struct sctp_chunkhdr *)cp, &nat_friendly);
4290Sstevel@tonic-gate	if (abort_flag) {
4300Sstevel@tonic-gate		/* Send an abort and notify peer */
4310Sstevel@tonic-gate		sctp_abort_an_association(stcb->sctp_ep, stcb, op_err, SCTP_SO_NOT_LOCKED);
4320Sstevel@tonic-gate		*abort_no_unlock = 1;
4330Sstevel@tonic-gate		return (-1);
4340Sstevel@tonic-gate	}
4350Sstevel@tonic-gate	asoc = &stcb->asoc;
4360Sstevel@tonic-gate	asoc->peer_supports_nat = (uint8_t) nat_friendly;
4370Sstevel@tonic-gate	/* process the peer's parameters in the INIT-ACK */
4380Sstevel@tonic-gate	retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb);
4390Sstevel@tonic-gate	if (retval < 0) {
4400Sstevel@tonic-gate		return (retval);
4410Sstevel@tonic-gate	}
4420Sstevel@tonic-gate	initack_limit = offset + ntohs(cp->ch.chunk_length);
4430Sstevel@tonic-gate	/* load all addresses */
4440Sstevel@tonic-gate	if ((retval = sctp_load_addresses_from_init(stcb, m,
4450Sstevel@tonic-gate	    (offset + sizeof(struct sctp_init_chunk)), initack_limit, sh,
4460Sstevel@tonic-gate	    NULL))) {
4470Sstevel@tonic-gate		/* Huh, we should abort */
4480Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT1,
4490Sstevel@tonic-gate		    "Load addresses from INIT causes an abort %d\n",
4500Sstevel@tonic-gate		    retval);
4510Sstevel@tonic-gate		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
4520Sstevel@tonic-gate		    NULL, 0, net->port);
4530Sstevel@tonic-gate		*abort_no_unlock = 1;
4540Sstevel@tonic-gate		return (-1);
4550Sstevel@tonic-gate	}
4560Sstevel@tonic-gate	/* if the peer doesn't support asconf, flush the asconf queue */
4577563SPrasad.Singamsetty@Sun.COM	if (asoc->peer_supports_asconf == 0) {
4587563SPrasad.Singamsetty@Sun.COM		struct sctp_asconf_addr *param, *nparam;
4597563SPrasad.Singamsetty@Sun.COM
4607563SPrasad.Singamsetty@Sun.COM		TAILQ_FOREACH_SAFE(param, &asoc->asconf_queue, next, nparam) {
4617563SPrasad.Singamsetty@Sun.COM			TAILQ_REMOVE(&asoc->asconf_queue, param, next);
4627563SPrasad.Singamsetty@Sun.COM			SCTP_FREE(param, SCTP_M_ASC_ADDR);
4637563SPrasad.Singamsetty@Sun.COM		}
4647563SPrasad.Singamsetty@Sun.COM	}
4657563SPrasad.Singamsetty@Sun.COM	stcb->asoc.peer_hmac_id = sctp_negotiate_hmacid(stcb->asoc.peer_hmacs,
4667563SPrasad.Singamsetty@Sun.COM	    stcb->asoc.local_hmacs);
4677563SPrasad.Singamsetty@Sun.COM	if (op_err) {
4687563SPrasad.Singamsetty@Sun.COM		sctp_queue_op_err(stcb, op_err);
4697563SPrasad.Singamsetty@Sun.COM		/* queuing will steal away the mbuf chain to the out queue */
4707563SPrasad.Singamsetty@Sun.COM		op_err = NULL;
4717563SPrasad.Singamsetty@Sun.COM	}
4727563SPrasad.Singamsetty@Sun.COM	/* extract the cookie and queue it to "echo" it back... */
4737563SPrasad.Singamsetty@Sun.COM	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
4747563SPrasad.Singamsetty@Sun.COM		sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
4757563SPrasad.Singamsetty@Sun.COM		    stcb->asoc.overall_error_count,
4767563SPrasad.Singamsetty@Sun.COM		    0,
4770Sstevel@tonic-gate		    SCTP_FROM_SCTP_INPUT,
4780Sstevel@tonic-gate		    __LINE__);
4790Sstevel@tonic-gate	}
4800Sstevel@tonic-gate	stcb->asoc.overall_error_count = 0;
4810Sstevel@tonic-gate	net->error_count = 0;
4820Sstevel@tonic-gate
4830Sstevel@tonic-gate	/*
4840Sstevel@tonic-gate	 * Cancel the INIT timer, We do this first before queueing the
4850Sstevel@tonic-gate	 * cookie. We always cancel at the primary to assue that we are
4860Sstevel@tonic-gate	 * canceling the timer started by the INIT which always goes to the
4870Sstevel@tonic-gate	 * primary.
4880Sstevel@tonic-gate	 */
4890Sstevel@tonic-gate	sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb,
4900Sstevel@tonic-gate	    asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4);
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate	/* calculate the RTO */
4930Sstevel@tonic-gate	net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy,
4940Sstevel@tonic-gate	    SCTP_RTT_FROM_NON_DATA);
4950Sstevel@tonic-gate
4960Sstevel@tonic-gate	retval = sctp_send_cookie_echo(m, offset, stcb, net);
4970Sstevel@tonic-gate	if (retval < 0) {
4980Sstevel@tonic-gate		/*
4990Sstevel@tonic-gate		 * No cookie, we probably should send a op error. But in any
5000Sstevel@tonic-gate		 * case if there is no cookie in the INIT-ACK, we can
5010Sstevel@tonic-gate		 * abandon the peer, its broke.
5020Sstevel@tonic-gate		 */
5030Sstevel@tonic-gate		if (retval == -3) {
5040Sstevel@tonic-gate			/* We abort with an error of missing mandatory param */
5050Sstevel@tonic-gate			op_err =
5060Sstevel@tonic-gate			    sctp_generate_invmanparam(SCTP_CAUSE_MISSING_PARAM);
5070Sstevel@tonic-gate			if (op_err) {
5080Sstevel@tonic-gate				/*
5090Sstevel@tonic-gate				 * Expand beyond to include the mandatory
5100Sstevel@tonic-gate				 * param cookie
5110Sstevel@tonic-gate				 */
5120Sstevel@tonic-gate				struct sctp_inv_mandatory_param *mp;
5130Sstevel@tonic-gate
5140Sstevel@tonic-gate				SCTP_BUF_LEN(op_err) =
5150Sstevel@tonic-gate				    sizeof(struct sctp_inv_mandatory_param);
5160Sstevel@tonic-gate				mp = mtod(op_err,
5170Sstevel@tonic-gate				    struct sctp_inv_mandatory_param *);
5180Sstevel@tonic-gate				/* Subtract the reserved param */
5190Sstevel@tonic-gate				mp->length =
5200Sstevel@tonic-gate				    htons(sizeof(struct sctp_inv_mandatory_param) - 2);
5210Sstevel@tonic-gate				mp->num_param = htonl(1);
5224954Sachimm				mp->param = htons(SCTP_STATE_COOKIE);
5230Sstevel@tonic-gate				mp->resv = 0;
5240Sstevel@tonic-gate			}
5250Sstevel@tonic-gate			sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
5260Sstevel@tonic-gate			    sh, op_err, vrf_id, net->port);
5270Sstevel@tonic-gate			*abort_no_unlock = 1;
5280Sstevel@tonic-gate		}
5290Sstevel@tonic-gate		return (retval);
5300Sstevel@tonic-gate	}
5310Sstevel@tonic-gate	return (0);
5320Sstevel@tonic-gate}
5330Sstevel@tonic-gate
5340Sstevel@tonic-gatestatic void
5350Sstevel@tonic-gatesctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
5360Sstevel@tonic-gate    struct sctp_tcb *stcb, struct sctp_nets *net)
5370Sstevel@tonic-gate{
5380Sstevel@tonic-gate	struct sockaddr_storage store;
5390Sstevel@tonic-gate	struct sctp_nets *r_net, *f_net;
5400Sstevel@tonic-gate	struct timeval tv;
5410Sstevel@tonic-gate	int req_prim = 0;
5420Sstevel@tonic-gate	uint16_t old_error_counter;
5430Sstevel@tonic-gate
5440Sstevel@tonic-gate#ifdef INET
5450Sstevel@tonic-gate	struct sockaddr_in *sin;
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate#endif
5480Sstevel@tonic-gate#ifdef INET6
5490Sstevel@tonic-gate	struct sockaddr_in6 *sin6;
5500Sstevel@tonic-gate
5510Sstevel@tonic-gate#endif
5520Sstevel@tonic-gate
5530Sstevel@tonic-gate	if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) {
5540Sstevel@tonic-gate		/* Invalid length */
5550Sstevel@tonic-gate		return;
5560Sstevel@tonic-gate	}
5570Sstevel@tonic-gate	memset(&store, 0, sizeof(store));
5580Sstevel@tonic-gate	switch (cp->heartbeat.hb_info.addr_family) {
5590Sstevel@tonic-gate#ifdef INET
5600Sstevel@tonic-gate	case AF_INET:
5610Sstevel@tonic-gate		if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) {
5620Sstevel@tonic-gate			sin = (struct sockaddr_in *)&store;
5630Sstevel@tonic-gate			sin->sin_family = cp->heartbeat.hb_info.addr_family;
5640Sstevel@tonic-gate			sin->sin_len = cp->heartbeat.hb_info.addr_len;
5650Sstevel@tonic-gate			sin->sin_port = stcb->rport;
5660Sstevel@tonic-gate			memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address,
5670Sstevel@tonic-gate			    sizeof(sin->sin_addr));
5680Sstevel@tonic-gate		} else {
5690Sstevel@tonic-gate			return;
5700Sstevel@tonic-gate		}
5710Sstevel@tonic-gate		break;
5720Sstevel@tonic-gate#endif
5730Sstevel@tonic-gate#ifdef INET6
5740Sstevel@tonic-gate	case AF_INET6:
5750Sstevel@tonic-gate		if (cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) {
5760Sstevel@tonic-gate			sin6 = (struct sockaddr_in6 *)&store;
5770Sstevel@tonic-gate			sin6->sin6_family = cp->heartbeat.hb_info.addr_family;
5780Sstevel@tonic-gate			sin6->sin6_len = cp->heartbeat.hb_info.addr_len;
5790Sstevel@tonic-gate			sin6->sin6_port = stcb->rport;
5800Sstevel@tonic-gate			memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address,
5810Sstevel@tonic-gate			    sizeof(sin6->sin6_addr));
5820Sstevel@tonic-gate		} else {
5830Sstevel@tonic-gate			return;
5840Sstevel@tonic-gate		}
5850Sstevel@tonic-gate		break;
5860Sstevel@tonic-gate#endif
5870Sstevel@tonic-gate	default:
5880Sstevel@tonic-gate		return;
5890Sstevel@tonic-gate	}
5900Sstevel@tonic-gate	r_net = sctp_findnet(stcb, (struct sockaddr *)&store);
5910Sstevel@tonic-gate	if (r_net == NULL) {
5920Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT1, "Huh? I can't find the address I sent it to, discard\n");
5930Sstevel@tonic-gate		return;
5940Sstevel@tonic-gate	}
5950Sstevel@tonic-gate	if ((r_net && (r_net->dest_state & SCTP_ADDR_UNCONFIRMED)) &&
5960Sstevel@tonic-gate	    (r_net->heartbeat_random1 == cp->heartbeat.hb_info.random_value1) &&
5970Sstevel@tonic-gate	    (r_net->heartbeat_random2 == cp->heartbeat.hb_info.random_value2)) {
5980Sstevel@tonic-gate		/*
5990Sstevel@tonic-gate		 * If the its a HB and it's random value is correct when can
6000Sstevel@tonic-gate		 * confirm the destination.
6010Sstevel@tonic-gate		 */
6020Sstevel@tonic-gate		r_net->dest_state &= ~SCTP_ADDR_UNCONFIRMED;
6030Sstevel@tonic-gate		if (r_net->dest_state & SCTP_ADDR_REQ_PRIMARY) {
6040Sstevel@tonic-gate			stcb->asoc.primary_destination = r_net;
6050Sstevel@tonic-gate			r_net->dest_state &= ~SCTP_ADDR_REQ_PRIMARY;
6060Sstevel@tonic-gate			f_net = TAILQ_FIRST(&stcb->asoc.nets);
6070Sstevel@tonic-gate			if (f_net != r_net) {
6080Sstevel@tonic-gate				/*
6090Sstevel@tonic-gate				 * first one on the list is NOT the primary
6100Sstevel@tonic-gate				 * sctp_cmpaddr() is much more efficent if
6110Sstevel@tonic-gate				 * the primary is the first on the list,
6120Sstevel@tonic-gate				 * make it so.
6130Sstevel@tonic-gate				 */
6140Sstevel@tonic-gate				TAILQ_REMOVE(&stcb->asoc.nets, r_net, sctp_next);
6150Sstevel@tonic-gate				TAILQ_INSERT_HEAD(&stcb->asoc.nets, r_net, sctp_next);
6160Sstevel@tonic-gate			}
6170Sstevel@tonic-gate			req_prim = 1;
6180Sstevel@tonic-gate		}
6190Sstevel@tonic-gate		sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
6200Sstevel@tonic-gate		    stcb, 0, (void *)r_net, SCTP_SO_NOT_LOCKED);
6210Sstevel@tonic-gate		sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
6220Sstevel@tonic-gate		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net);
6230Sstevel@tonic-gate	}
6240Sstevel@tonic-gate	old_error_counter = r_net->error_count;
6250Sstevel@tonic-gate	r_net->error_count = 0;
6260Sstevel@tonic-gate	r_net->hb_responded = 1;
6270Sstevel@tonic-gate	tv.tv_sec = cp->heartbeat.hb_info.time_value_1;
6280Sstevel@tonic-gate	tv.tv_usec = cp->heartbeat.hb_info.time_value_2;
6290Sstevel@tonic-gate	/* Now lets do a RTO with this */
6300Sstevel@tonic-gate	r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy,
6310Sstevel@tonic-gate	    SCTP_RTT_FROM_NON_DATA);
6320Sstevel@tonic-gate	if (!(r_net->dest_state & SCTP_ADDR_REACHABLE)) {
6330Sstevel@tonic-gate		r_net->dest_state |= SCTP_ADDR_REACHABLE;
6340Sstevel@tonic-gate		sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
6350Sstevel@tonic-gate		    0, (void *)r_net, SCTP_SO_NOT_LOCKED);
6360Sstevel@tonic-gate	}
6370Sstevel@tonic-gate	if (r_net->dest_state & SCTP_ADDR_PF) {
6380Sstevel@tonic-gate		r_net->dest_state &= ~SCTP_ADDR_PF;
6390Sstevel@tonic-gate		stcb->asoc.cc_functions.sctp_cwnd_update_exit_pf(stcb, net);
6400Sstevel@tonic-gate	}
6410Sstevel@tonic-gate	if (old_error_counter > 0) {
6420Sstevel@tonic-gate		sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_3);
6430Sstevel@tonic-gate		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, r_net);
6440Sstevel@tonic-gate	}
6450Sstevel@tonic-gate	if (r_net == stcb->asoc.primary_destination) {
6460Sstevel@tonic-gate		if (stcb->asoc.alternate) {
6470Sstevel@tonic-gate			/* release the alternate, primary is good */
6480Sstevel@tonic-gate			sctp_free_remote_addr(stcb->asoc.alternate);
6490Sstevel@tonic-gate			stcb->asoc.alternate = NULL;
6500Sstevel@tonic-gate		}
6510Sstevel@tonic-gate	}
6520Sstevel@tonic-gate	/* Mobility adaptation */
6530Sstevel@tonic-gate	if (req_prim) {
6540Sstevel@tonic-gate		if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
6550Sstevel@tonic-gate		    SCTP_MOBILITY_BASE) ||
6560Sstevel@tonic-gate		    sctp_is_mobility_feature_on(stcb->sctp_ep,
6574954Sachimm		    SCTP_MOBILITY_FASTHANDOFF)) &&
6580Sstevel@tonic-gate		    sctp_is_mobility_feature_on(stcb->sctp_ep,
6590Sstevel@tonic-gate		    SCTP_MOBILITY_PRIM_DELETED)) {
6600Sstevel@tonic-gate
6614954Sachimm			sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7);
6620Sstevel@tonic-gate			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
6630Sstevel@tonic-gate			    SCTP_MOBILITY_FASTHANDOFF)) {
6640Sstevel@tonic-gate				sctp_assoc_immediate_retrans(stcb,
6650Sstevel@tonic-gate				    stcb->asoc.primary_destination);
6660Sstevel@tonic-gate			}
6670Sstevel@tonic-gate			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
6680Sstevel@tonic-gate			    SCTP_MOBILITY_BASE)) {
6690Sstevel@tonic-gate				sctp_move_chunks_from_net(stcb,
6700Sstevel@tonic-gate				    stcb->asoc.deleted_primary);
6710Sstevel@tonic-gate			}
6724954Sachimm			sctp_delete_prim_timer(stcb->sctp_ep, stcb,
6730Sstevel@tonic-gate			    stcb->asoc.deleted_primary);
6740Sstevel@tonic-gate		}
6750Sstevel@tonic-gate	}
6760Sstevel@tonic-gate}
6770Sstevel@tonic-gate
6780Sstevel@tonic-gatestatic int
6790Sstevel@tonic-gatesctp_handle_nat_colliding_state(struct sctp_tcb *stcb)
6800Sstevel@tonic-gate{
6810Sstevel@tonic-gate	/*
6820Sstevel@tonic-gate	 * return 0 means we want you to proceed with the abort non-zero
6830Sstevel@tonic-gate	 * means no abort processing
6840Sstevel@tonic-gate	 */
6850Sstevel@tonic-gate	struct sctpasochead *head;
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate	if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) {
6880Sstevel@tonic-gate		/* generate a new vtag and send init */
6890Sstevel@tonic-gate		LIST_REMOVE(stcb, sctp_asocs);
6900Sstevel@tonic-gate		stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1);
6910Sstevel@tonic-gate		head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))];
6920Sstevel@tonic-gate		/*
6930Sstevel@tonic-gate		 * put it in the bucket in the vtag hash of assoc's for the
6940Sstevel@tonic-gate		 * system
6950Sstevel@tonic-gate		 */
6960Sstevel@tonic-gate		LIST_INSERT_HEAD(head, stcb, sctp_asocs);
6970Sstevel@tonic-gate		sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
6980Sstevel@tonic-gate		return (1);
6990Sstevel@tonic-gate	}
7000Sstevel@tonic-gate	if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED) {
7010Sstevel@tonic-gate		/*
7020Sstevel@tonic-gate		 * treat like a case where the cookie expired i.e.: - dump
7030Sstevel@tonic-gate		 * current cookie. - generate a new vtag. - resend init.
7040Sstevel@tonic-gate		 */
7050Sstevel@tonic-gate		/* generate a new vtag and send init */
7060Sstevel@tonic-gate		LIST_REMOVE(stcb, sctp_asocs);
7070Sstevel@tonic-gate		stcb->asoc.state &= ~SCTP_STATE_COOKIE_ECHOED;
7080Sstevel@tonic-gate		stcb->asoc.state |= SCTP_STATE_COOKIE_WAIT;
7090Sstevel@tonic-gate		sctp_stop_all_cookie_timers(stcb);
7100Sstevel@tonic-gate		sctp_toss_old_cookies(stcb, &stcb->asoc);
7110Sstevel@tonic-gate		stcb->asoc.my_vtag = sctp_select_a_tag(stcb->sctp_ep, stcb->sctp_ep->sctp_lport, stcb->rport, 1);
7120Sstevel@tonic-gate		head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag, SCTP_BASE_INFO(hashasocmark))];
7130Sstevel@tonic-gate		/*
7140Sstevel@tonic-gate		 * put it in the bucket in the vtag hash of assoc's for the
7150Sstevel@tonic-gate		 * system
7160Sstevel@tonic-gate		 */
7170Sstevel@tonic-gate		LIST_INSERT_HEAD(head, stcb, sctp_asocs);
7180Sstevel@tonic-gate		sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
7190Sstevel@tonic-gate		return (1);
7200Sstevel@tonic-gate	}
7210Sstevel@tonic-gate	return (0);
7220Sstevel@tonic-gate}
7230Sstevel@tonic-gate
7240Sstevel@tonic-gatestatic int
7250Sstevel@tonic-gatesctp_handle_nat_missing_state(struct sctp_tcb *stcb,
7260Sstevel@tonic-gate    struct sctp_nets *net)
7274954Sachimm{
7280Sstevel@tonic-gate	/*
7290Sstevel@tonic-gate	 * return 0 means we want you to proceed with the abort non-zero
7300Sstevel@tonic-gate	 * means no abort processing
7310Sstevel@tonic-gate	 */
7320Sstevel@tonic-gate	if (stcb->asoc.peer_supports_auth == 0) {
7330Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_nat_missing_state: Peer does not support AUTH, cannot send an asconf\n");
7340Sstevel@tonic-gate		return (0);
7350Sstevel@tonic-gate	}
7360Sstevel@tonic-gate	sctp_asconf_send_nat_state_update(stcb, net);
7370Sstevel@tonic-gate	return (1);
7380Sstevel@tonic-gate}
7390Sstevel@tonic-gate
7400Sstevel@tonic-gate
7410Sstevel@tonic-gatestatic void
7420Sstevel@tonic-gatesctp_handle_abort(struct sctp_abort_chunk *abort,
7430Sstevel@tonic-gate    struct sctp_tcb *stcb, struct sctp_nets *net)
7440Sstevel@tonic-gate{
7450Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
7460Sstevel@tonic-gate	struct socket *so;
7470Sstevel@tonic-gate
7480Sstevel@tonic-gate#endif
7490Sstevel@tonic-gate	uint16_t len;
7500Sstevel@tonic-gate	uint16_t error;
7510Sstevel@tonic-gate
7520Sstevel@tonic-gate	SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: handling ABORT\n");
7530Sstevel@tonic-gate	if (stcb == NULL)
7540Sstevel@tonic-gate		return;
7550Sstevel@tonic-gate
7564954Sachimm	len = ntohs(abort->ch.chunk_length);
7570Sstevel@tonic-gate	if (len > sizeof(struct sctp_chunkhdr)) {
7580Sstevel@tonic-gate		/*
7590Sstevel@tonic-gate		 * Need to check the cause codes for our two magic nat
7600Sstevel@tonic-gate		 * aborts which don't kill the assoc necessarily.
7610Sstevel@tonic-gate		 */
7620Sstevel@tonic-gate		struct sctp_missing_nat_state *natc;
7630Sstevel@tonic-gate
7640Sstevel@tonic-gate		natc = (struct sctp_missing_nat_state *)(abort + 1);
7650Sstevel@tonic-gate		error = ntohs(natc->cause);
7660Sstevel@tonic-gate		if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) {
7670Sstevel@tonic-gate			SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n",
7680Sstevel@tonic-gate			    abort->ch.chunk_flags);
7690Sstevel@tonic-gate			if (sctp_handle_nat_colliding_state(stcb)) {
7700Sstevel@tonic-gate				return;
7710Sstevel@tonic-gate			}
7720Sstevel@tonic-gate		} else if (error == SCTP_CAUSE_NAT_MISSING_STATE) {
7730Sstevel@tonic-gate			SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n",
7740Sstevel@tonic-gate			    abort->ch.chunk_flags);
7750Sstevel@tonic-gate			if (sctp_handle_nat_missing_state(stcb, net)) {
7760Sstevel@tonic-gate				return;
7770Sstevel@tonic-gate			}
7780Sstevel@tonic-gate		}
7790Sstevel@tonic-gate	} else {
7800Sstevel@tonic-gate		error = 0;
7810Sstevel@tonic-gate	}
7820Sstevel@tonic-gate	/* stop any receive timers */
7830Sstevel@tonic-gate	sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_6);
7840Sstevel@tonic-gate	/* notify user of the abort and clean up... */
7850Sstevel@tonic-gate	sctp_abort_notification(stcb, 1, error, abort, SCTP_SO_NOT_LOCKED);
7860Sstevel@tonic-gate	/* free the tcb */
7870Sstevel@tonic-gate	SCTP_STAT_INCR_COUNTER32(sctps_aborted);
7880Sstevel@tonic-gate	if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
7890Sstevel@tonic-gate	    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
7900Sstevel@tonic-gate		SCTP_STAT_DECR_GAUGE32(sctps_currestab);
7910Sstevel@tonic-gate	}
7920Sstevel@tonic-gate#ifdef SCTP_ASOCLOG_OF_TSNS
7930Sstevel@tonic-gate	sctp_print_out_track_log(stcb);
7940Sstevel@tonic-gate#endif
7950Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
7960Sstevel@tonic-gate	so = SCTP_INP_SO(stcb->sctp_ep);
7970Sstevel@tonic-gate	atomic_add_int(&stcb->asoc.refcnt, 1);
7980Sstevel@tonic-gate	SCTP_TCB_UNLOCK(stcb);
7990Sstevel@tonic-gate	SCTP_SOCKET_LOCK(so, 1);
8000Sstevel@tonic-gate	SCTP_TCB_LOCK(stcb);
8010Sstevel@tonic-gate	atomic_subtract_int(&stcb->asoc.refcnt, 1);
8020Sstevel@tonic-gate#endif
8030Sstevel@tonic-gate	stcb->asoc.state |= SCTP_STATE_WAS_ABORTED;
8040Sstevel@tonic-gate	(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
8050Sstevel@tonic-gate	    SCTP_FROM_SCTP_INPUT + SCTP_LOC_6);
8060Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
8070Sstevel@tonic-gate	SCTP_SOCKET_UNLOCK(so, 1);
8080Sstevel@tonic-gate#endif
8090Sstevel@tonic-gate	SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_abort: finished\n");
8100Sstevel@tonic-gate}
8110Sstevel@tonic-gate
8120Sstevel@tonic-gatestatic void
8130Sstevel@tonic-gatesctp_start_net_timers(struct sctp_tcb *stcb)
8140Sstevel@tonic-gate{
8150Sstevel@tonic-gate	uint32_t cnt_hb_sent;
8160Sstevel@tonic-gate	struct sctp_nets *net;
8170Sstevel@tonic-gate
8180Sstevel@tonic-gate	cnt_hb_sent = 0;
8190Sstevel@tonic-gate	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
8200Sstevel@tonic-gate		/*
8210Sstevel@tonic-gate		 * For each network start: 1) A pmtu timer. 2) A HB timer 3)
8220Sstevel@tonic-gate		 * If the dest in unconfirmed send a hb as well if under
8230Sstevel@tonic-gate		 * max_hb_burst have been sent.
8240Sstevel@tonic-gate		 */
8250Sstevel@tonic-gate		sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net);
8260Sstevel@tonic-gate		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
8270Sstevel@tonic-gate		if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
8280Sstevel@tonic-gate		    (cnt_hb_sent < SCTP_BASE_SYSCTL(sctp_hb_maxburst))) {
8290Sstevel@tonic-gate			sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
8300Sstevel@tonic-gate			cnt_hb_sent++;
8310Sstevel@tonic-gate		}
8320Sstevel@tonic-gate	}
8330Sstevel@tonic-gate	if (cnt_hb_sent) {
8340Sstevel@tonic-gate		sctp_chunk_output(stcb->sctp_ep, stcb,
8350Sstevel@tonic-gate		    SCTP_OUTPUT_FROM_COOKIE_ACK,
8360Sstevel@tonic-gate		    SCTP_SO_NOT_LOCKED);
8370Sstevel@tonic-gate	}
8380Sstevel@tonic-gate}
8390Sstevel@tonic-gate
8400Sstevel@tonic-gate
8410Sstevel@tonic-gatestatic void
8420Sstevel@tonic-gatesctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
8430Sstevel@tonic-gate    struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag)
8440Sstevel@tonic-gate{
8450Sstevel@tonic-gate	struct sctp_association *asoc;
8460Sstevel@tonic-gate	int some_on_streamwheel;
8470Sstevel@tonic-gate
8480Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
8490Sstevel@tonic-gate	struct socket *so;
8500Sstevel@tonic-gate
8510Sstevel@tonic-gate#endif
8520Sstevel@tonic-gate
8530Sstevel@tonic-gate	SCTPDBG(SCTP_DEBUG_INPUT2,
8540Sstevel@tonic-gate	    "sctp_handle_shutdown: handling SHUTDOWN\n");
8550Sstevel@tonic-gate	if (stcb == NULL)
8560Sstevel@tonic-gate		return;
8570Sstevel@tonic-gate	asoc = &stcb->asoc;
8580Sstevel@tonic-gate	if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
8590Sstevel@tonic-gate	    (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
8600Sstevel@tonic-gate		return;
8610Sstevel@tonic-gate	}
8620Sstevel@tonic-gate	if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) {
8630Sstevel@tonic-gate		/* Shutdown NOT the expected size */
8640Sstevel@tonic-gate		return;
8650Sstevel@tonic-gate	} else {
8660Sstevel@tonic-gate		sctp_update_acked(stcb, cp, abort_flag);
8670Sstevel@tonic-gate		if (*abort_flag) {
8680Sstevel@tonic-gate			return;
8690Sstevel@tonic-gate		}
8700Sstevel@tonic-gate	}
8710Sstevel@tonic-gate	if (asoc->control_pdapi) {
8720Sstevel@tonic-gate		/*
8730Sstevel@tonic-gate		 * With a normal shutdown we assume the end of last record.
8740Sstevel@tonic-gate		 */
8750Sstevel@tonic-gate		SCTP_INP_READ_LOCK(stcb->sctp_ep);
8760Sstevel@tonic-gate		asoc->control_pdapi->end_added = 1;
8770Sstevel@tonic-gate		asoc->control_pdapi->pdapi_aborted = 1;
8780Sstevel@tonic-gate		asoc->control_pdapi = NULL;
8790Sstevel@tonic-gate		SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
8800Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
8810Sstevel@tonic-gate		so = SCTP_INP_SO(stcb->sctp_ep);
8820Sstevel@tonic-gate		atomic_add_int(&stcb->asoc.refcnt, 1);
8830Sstevel@tonic-gate		SCTP_TCB_UNLOCK(stcb);
8840Sstevel@tonic-gate		SCTP_SOCKET_LOCK(so, 1);
8850Sstevel@tonic-gate		SCTP_TCB_LOCK(stcb);
8860Sstevel@tonic-gate		atomic_subtract_int(&stcb->asoc.refcnt, 1);
8870Sstevel@tonic-gate		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
8880Sstevel@tonic-gate			/* assoc was freed while we were unlocked */
8890Sstevel@tonic-gate			SCTP_SOCKET_UNLOCK(so, 1);
8900Sstevel@tonic-gate			return;
8910Sstevel@tonic-gate		}
8920Sstevel@tonic-gate#endif
8930Sstevel@tonic-gate		sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
8940Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
8950Sstevel@tonic-gate		SCTP_SOCKET_UNLOCK(so, 1);
8960Sstevel@tonic-gate#endif
8970Sstevel@tonic-gate	}
8980Sstevel@tonic-gate	/* goto SHUTDOWN_RECEIVED state to block new requests */
8990Sstevel@tonic-gate	if (stcb->sctp_socket) {
9000Sstevel@tonic-gate		if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
9010Sstevel@tonic-gate		    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) &&
9020Sstevel@tonic-gate		    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) {
9030Sstevel@tonic-gate			SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_RECEIVED);
9040Sstevel@tonic-gate			SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
9050Sstevel@tonic-gate			/*
9060Sstevel@tonic-gate			 * notify upper layer that peer has initiated a
9070Sstevel@tonic-gate			 * shutdown
9080Sstevel@tonic-gate			 */
9090Sstevel@tonic-gate			sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
9100Sstevel@tonic-gate
9110Sstevel@tonic-gate			/* reset time */
9120Sstevel@tonic-gate			(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
9130Sstevel@tonic-gate		}
9140Sstevel@tonic-gate	}
9150Sstevel@tonic-gate	if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) {
9160Sstevel@tonic-gate		/*
9174954Sachimm		 * stop the shutdown timer, since we WILL move to
9180Sstevel@tonic-gate		 * SHUTDOWN-ACK-SENT.
9190Sstevel@tonic-gate		 */
9200Sstevel@tonic-gate		sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_8);
9210Sstevel@tonic-gate	}
9220Sstevel@tonic-gate	/* Now is there unsent data on a stream somewhere? */
9230Sstevel@tonic-gate	some_on_streamwheel = sctp_is_there_unsent_data(stcb, SCTP_SO_NOT_LOCKED);
9244954Sachimm
9250Sstevel@tonic-gate	if (!TAILQ_EMPTY(&asoc->send_queue) ||
9260Sstevel@tonic-gate	    !TAILQ_EMPTY(&asoc->sent_queue) ||
9270Sstevel@tonic-gate	    some_on_streamwheel) {
9280Sstevel@tonic-gate		/* By returning we will push more data out */
9290Sstevel@tonic-gate		return;
9300Sstevel@tonic-gate	} else {
9310Sstevel@tonic-gate		/* no outstanding data to send, so move on... */
9320Sstevel@tonic-gate		/* send SHUTDOWN-ACK */
9330Sstevel@tonic-gate		sctp_send_shutdown_ack(stcb, net);
9340Sstevel@tonic-gate		/* move to SHUTDOWN-ACK-SENT state */
9350Sstevel@tonic-gate		if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
9360Sstevel@tonic-gate		    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
9370Sstevel@tonic-gate			SCTP_STAT_DECR_GAUGE32(sctps_currestab);
9380Sstevel@tonic-gate		}
9390Sstevel@tonic-gate		SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_ACK_SENT);
9400Sstevel@tonic-gate		SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
9410Sstevel@tonic-gate		sctp_stop_timers_for_shutdown(stcb);
9420Sstevel@tonic-gate		sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep,
9430Sstevel@tonic-gate		    stcb, net);
9440Sstevel@tonic-gate	}
9450Sstevel@tonic-gate}
9460Sstevel@tonic-gate
9470Sstevel@tonic-gatestatic void
9480Sstevel@tonic-gatesctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED,
9490Sstevel@tonic-gate    struct sctp_tcb *stcb,
9500Sstevel@tonic-gate    struct sctp_nets *net)
9510Sstevel@tonic-gate{
9520Sstevel@tonic-gate	struct sctp_association *asoc;
9530Sstevel@tonic-gate
9540Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
9550Sstevel@tonic-gate	struct socket *so;
9560Sstevel@tonic-gate
9570Sstevel@tonic-gate	so = SCTP_INP_SO(stcb->sctp_ep);
9580Sstevel@tonic-gate#endif
9590Sstevel@tonic-gate	SCTPDBG(SCTP_DEBUG_INPUT2,
9600Sstevel@tonic-gate	    "sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n");
9610Sstevel@tonic-gate	if (stcb == NULL)
9620Sstevel@tonic-gate		return;
9630Sstevel@tonic-gate
9640Sstevel@tonic-gate	asoc = &stcb->asoc;
9650Sstevel@tonic-gate	/* process according to association state */
9660Sstevel@tonic-gate	if ((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
9670Sstevel@tonic-gate	    (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)) {
9680Sstevel@tonic-gate		/* unexpected SHUTDOWN-ACK... do OOTB handling... */
9690Sstevel@tonic-gate		sctp_send_shutdown_complete(stcb, net, 1);
9700Sstevel@tonic-gate		SCTP_TCB_UNLOCK(stcb);
9710Sstevel@tonic-gate		return;
9720Sstevel@tonic-gate	}
9730Sstevel@tonic-gate	if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
9740Sstevel@tonic-gate	    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
9750Sstevel@tonic-gate		/* unexpected SHUTDOWN-ACK... so ignore... */
9760Sstevel@tonic-gate		SCTP_TCB_UNLOCK(stcb);
9770Sstevel@tonic-gate		return;
9780Sstevel@tonic-gate	}
9794954Sachimm	if (asoc->control_pdapi) {
9800Sstevel@tonic-gate		/*
9810Sstevel@tonic-gate		 * With a normal shutdown we assume the end of last record.
9820Sstevel@tonic-gate		 */
9830Sstevel@tonic-gate		SCTP_INP_READ_LOCK(stcb->sctp_ep);
9840Sstevel@tonic-gate		asoc->control_pdapi->end_added = 1;
9850Sstevel@tonic-gate		asoc->control_pdapi->pdapi_aborted = 1;
9860Sstevel@tonic-gate		asoc->control_pdapi = NULL;
9870Sstevel@tonic-gate		SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
9880Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
9890Sstevel@tonic-gate		atomic_add_int(&stcb->asoc.refcnt, 1);
9900Sstevel@tonic-gate		SCTP_TCB_UNLOCK(stcb);
9910Sstevel@tonic-gate		SCTP_SOCKET_LOCK(so, 1);
9920Sstevel@tonic-gate		SCTP_TCB_LOCK(stcb);
9930Sstevel@tonic-gate		atomic_subtract_int(&stcb->asoc.refcnt, 1);
9940Sstevel@tonic-gate		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
9950Sstevel@tonic-gate			/* assoc was freed while we were unlocked */
9960Sstevel@tonic-gate			SCTP_SOCKET_UNLOCK(so, 1);
9970Sstevel@tonic-gate			return;
9980Sstevel@tonic-gate		}
9990Sstevel@tonic-gate#endif
10000Sstevel@tonic-gate		sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
10010Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
10020Sstevel@tonic-gate		SCTP_SOCKET_UNLOCK(so, 1);
10030Sstevel@tonic-gate#endif
10040Sstevel@tonic-gate	}
10050Sstevel@tonic-gate	/* are the queues empty? */
10060Sstevel@tonic-gate	if (!TAILQ_EMPTY(&asoc->send_queue) ||
10070Sstevel@tonic-gate	    !TAILQ_EMPTY(&asoc->sent_queue) ||
10080Sstevel@tonic-gate	    !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
10090Sstevel@tonic-gate		sctp_report_all_outbound(stcb, 0, SCTP_SO_NOT_LOCKED);
10100Sstevel@tonic-gate	}
10110Sstevel@tonic-gate	/* stop the timer */
10124954Sachimm	sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_9);
10134954Sachimm	/* send SHUTDOWN-COMPLETE */
10140Sstevel@tonic-gate	sctp_send_shutdown_complete(stcb, net, 0);
10150Sstevel@tonic-gate	/* notify upper layer protocol */
10160Sstevel@tonic-gate	if (stcb->sctp_socket) {
10170Sstevel@tonic-gate		if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
10180Sstevel@tonic-gate		    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
10190Sstevel@tonic-gate			stcb->sctp_socket->so_snd.sb_cc = 0;
10200Sstevel@tonic-gate		}
10214954Sachimm		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
102210948SJames.Hall@Sun.COM	}
102310948SJames.Hall@Sun.COM	SCTP_STAT_INCR_COUNTER32(sctps_shutdown);
10240Sstevel@tonic-gate	/* free the TCB but first save off the ep */
10250Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
10260Sstevel@tonic-gate	atomic_add_int(&stcb->asoc.refcnt, 1);
10270Sstevel@tonic-gate	SCTP_TCB_UNLOCK(stcb);
10280Sstevel@tonic-gate	SCTP_SOCKET_LOCK(so, 1);
10290Sstevel@tonic-gate	SCTP_TCB_LOCK(stcb);
10300Sstevel@tonic-gate	atomic_subtract_int(&stcb->asoc.refcnt, 1);
10310Sstevel@tonic-gate#endif
10320Sstevel@tonic-gate	(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
10330Sstevel@tonic-gate	    SCTP_FROM_SCTP_INPUT + SCTP_LOC_10);
10340Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
10350Sstevel@tonic-gate	SCTP_SOCKET_UNLOCK(so, 1);
10360Sstevel@tonic-gate#endif
10370Sstevel@tonic-gate}
10380Sstevel@tonic-gate
10390Sstevel@tonic-gate/*
10400Sstevel@tonic-gate * Skip past the param header and then we will find the chunk that caused the
10410Sstevel@tonic-gate * problem. There are two possiblities ASCONF or FWD-TSN other than that and
10420Sstevel@tonic-gate * our peer must be broken.
10430Sstevel@tonic-gate */
10440Sstevel@tonic-gatestatic void
10450Sstevel@tonic-gatesctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr,
10464954Sachimm    struct sctp_nets *net)
10470Sstevel@tonic-gate{
10484954Sachimm	struct sctp_chunkhdr *chk;
10494954Sachimm
10504954Sachimm	chk = (struct sctp_chunkhdr *)((caddr_t)phdr + sizeof(*phdr));
10510Sstevel@tonic-gate	switch (chk->chunk_type) {
10524954Sachimm	case SCTP_ASCONF_ACK:
10530Sstevel@tonic-gate	case SCTP_ASCONF:
10540Sstevel@tonic-gate		sctp_asconf_cleanup(stcb, net);
10550Sstevel@tonic-gate		break;
10560Sstevel@tonic-gate	case SCTP_FORWARD_CUM_TSN:
10570Sstevel@tonic-gate		stcb->asoc.peer_supports_prsctp = 0;
10580Sstevel@tonic-gate		break;
10590Sstevel@tonic-gate	default:
10600Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT2,
10610Sstevel@tonic-gate		    "Peer does not support chunk type %d(%x)??\n",
10620Sstevel@tonic-gate		    chk->chunk_type, (uint32_t) chk->chunk_type);
10630Sstevel@tonic-gate		break;
10640Sstevel@tonic-gate	}
10650Sstevel@tonic-gate}
10660Sstevel@tonic-gate
10670Sstevel@tonic-gate/*
10680Sstevel@tonic-gate * Skip past the param header and then we will find the param that caused the
10690Sstevel@tonic-gate * problem.  There are a number of param's in a ASCONF OR the prsctp param
10700Sstevel@tonic-gate * these will turn of specific features.
10710Sstevel@tonic-gate */
10720Sstevel@tonic-gatestatic void
10730Sstevel@tonic-gatesctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr)
10740Sstevel@tonic-gate{
10750Sstevel@tonic-gate	struct sctp_paramhdr *pbad;
10760Sstevel@tonic-gate
10770Sstevel@tonic-gate	pbad = phdr + 1;
10780Sstevel@tonic-gate	switch (ntohs(pbad->param_type)) {
10790Sstevel@tonic-gate		/* pr-sctp draft */
10800Sstevel@tonic-gate	case SCTP_PRSCTP_SUPPORTED:
10810Sstevel@tonic-gate		stcb->asoc.peer_supports_prsctp = 0;
10820Sstevel@tonic-gate		break;
10830Sstevel@tonic-gate	case SCTP_SUPPORTED_CHUNK_EXT:
10840Sstevel@tonic-gate		break;
10850Sstevel@tonic-gate		/* draft-ietf-tsvwg-addip-sctp */
10860Sstevel@tonic-gate	case SCTP_HAS_NAT_SUPPORT:
10870Sstevel@tonic-gate		stcb->asoc.peer_supports_nat = 0;
10880Sstevel@tonic-gate		break;
10890Sstevel@tonic-gate	case SCTP_ADD_IP_ADDRESS:
10900Sstevel@tonic-gate	case SCTP_DEL_IP_ADDRESS:
10910Sstevel@tonic-gate	case SCTP_SET_PRIM_ADDR:
10920Sstevel@tonic-gate		stcb->asoc.peer_supports_asconf = 0;
10930Sstevel@tonic-gate		break;
10940Sstevel@tonic-gate	case SCTP_SUCCESS_REPORT:
10950Sstevel@tonic-gate	case SCTP_ERROR_CAUSE_IND:
10960Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT2, "Huh, the peer does not support success? or error cause?\n");
10970Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT2,
10980Sstevel@tonic-gate		    "Turning off ASCONF to this strange peer\n");
10990Sstevel@tonic-gate		stcb->asoc.peer_supports_asconf = 0;
11000Sstevel@tonic-gate		break;
11010Sstevel@tonic-gate	default:
11020Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT2,
11030Sstevel@tonic-gate		    "Peer does not support param type %d(%x)??\n",
11040Sstevel@tonic-gate		    pbad->param_type, (uint32_t) pbad->param_type);
11050Sstevel@tonic-gate		break;
11060Sstevel@tonic-gate	}
11070Sstevel@tonic-gate}
11080Sstevel@tonic-gate
11090Sstevel@tonic-gatestatic int
11100Sstevel@tonic-gatesctp_handle_error(struct sctp_chunkhdr *ch,
11110Sstevel@tonic-gate    struct sctp_tcb *stcb, struct sctp_nets *net)
11120Sstevel@tonic-gate{
11130Sstevel@tonic-gate	int chklen;
11140Sstevel@tonic-gate	struct sctp_paramhdr *phdr;
11150Sstevel@tonic-gate	uint16_t error_type;
11160Sstevel@tonic-gate	uint16_t error_len;
11170Sstevel@tonic-gate	struct sctp_association *asoc;
11180Sstevel@tonic-gate	int adjust;
11190Sstevel@tonic-gate
11204954Sachimm#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
11214954Sachimm	struct socket *so;
11224954Sachimm
11234954Sachimm#endif
11244954Sachimm
11254954Sachimm	/* parse through all of the errors and process */
11264954Sachimm	asoc = &stcb->asoc;
11274954Sachimm	phdr = (struct sctp_paramhdr *)((caddr_t)ch +
11284954Sachimm	    sizeof(struct sctp_chunkhdr));
11294954Sachimm	chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr);
11304954Sachimm	while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) {
11314954Sachimm		/* Process an Error Cause */
11324954Sachimm		error_type = ntohs(phdr->param_type);
11334954Sachimm		error_len = ntohs(phdr->param_length);
11344954Sachimm		if ((error_len > chklen) || (error_len == 0)) {
11354954Sachimm			/* invalid param length for this param */
11364954Sachimm			SCTPDBG(SCTP_DEBUG_INPUT1, "Bogus length in error param- chunk left:%d errorlen:%d\n",
11374954Sachimm			    chklen, error_len);
11384954Sachimm			return (0);
11397400SViswanathan.Kannappan@Sun.COM		}
114010948SJames.Hall@Sun.COM		switch (error_type) {
114110948SJames.Hall@Sun.COM		case SCTP_CAUSE_INVALID_STREAM:
114210948SJames.Hall@Sun.COM		case SCTP_CAUSE_MISSING_PARAM:
114310948SJames.Hall@Sun.COM		case SCTP_CAUSE_INVALID_PARAM:
11444954Sachimm		case SCTP_CAUSE_NO_USER_DATA:
11454954Sachimm			SCTPDBG(SCTP_DEBUG_INPUT1, "Software error we got a %d back? We have a bug :/ (or do they?)\n",
11464954Sachimm			    error_type);
11470Sstevel@tonic-gate			break;
11480Sstevel@tonic-gate		case SCTP_CAUSE_NAT_COLLIDING_STATE:
11490Sstevel@tonic-gate			SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n",
11500Sstevel@tonic-gate			    ch->chunk_flags);
11510Sstevel@tonic-gate			if (sctp_handle_nat_colliding_state(stcb)) {
11520Sstevel@tonic-gate				return (0);
11530Sstevel@tonic-gate			}
11540Sstevel@tonic-gate			break;
11550Sstevel@tonic-gate		case SCTP_CAUSE_NAT_MISSING_STATE:
11560Sstevel@tonic-gate			SCTPDBG(SCTP_DEBUG_INPUT2, "Received missing state abort flags:%x\n",
11570Sstevel@tonic-gate			    ch->chunk_flags);
11580Sstevel@tonic-gate			if (sctp_handle_nat_missing_state(stcb, net)) {
11590Sstevel@tonic-gate				return (0);
11600Sstevel@tonic-gate			}
11610Sstevel@tonic-gate			break;
11620Sstevel@tonic-gate		case SCTP_CAUSE_STALE_COOKIE:
11630Sstevel@tonic-gate			/*
11640Sstevel@tonic-gate			 * We only act if we have echoed a cookie and are
11650Sstevel@tonic-gate			 * waiting.
11660Sstevel@tonic-gate			 */
11670Sstevel@tonic-gate			if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) {
11680Sstevel@tonic-gate				int *p;
11690Sstevel@tonic-gate
11700Sstevel@tonic-gate				p = (int *)((caddr_t)phdr + sizeof(*phdr));
11710Sstevel@tonic-gate				/* Save the time doubled */
11720Sstevel@tonic-gate				asoc->cookie_preserve_req = ntohl(*p) << 1;
11730Sstevel@tonic-gate				asoc->stale_cookie_count++;
11740Sstevel@tonic-gate				if (asoc->stale_cookie_count >
11750Sstevel@tonic-gate				    asoc->max_init_times) {
11760Sstevel@tonic-gate					sctp_abort_notification(stcb, 0, 0, NULL, SCTP_SO_NOT_LOCKED);
11770Sstevel@tonic-gate					/* now free the asoc */
11780Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
11790Sstevel@tonic-gate					so = SCTP_INP_SO(stcb->sctp_ep);
11800Sstevel@tonic-gate					atomic_add_int(&stcb->asoc.refcnt, 1);
11810Sstevel@tonic-gate					SCTP_TCB_UNLOCK(stcb);
11820Sstevel@tonic-gate					SCTP_SOCKET_LOCK(so, 1);
11830Sstevel@tonic-gate					SCTP_TCB_LOCK(stcb);
11840Sstevel@tonic-gate					atomic_subtract_int(&stcb->asoc.refcnt, 1);
11850Sstevel@tonic-gate#endif
11860Sstevel@tonic-gate					(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC,
11870Sstevel@tonic-gate					    SCTP_FROM_SCTP_INPUT + SCTP_LOC_11);
11880Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
11890Sstevel@tonic-gate					SCTP_SOCKET_UNLOCK(so, 1);
11900Sstevel@tonic-gate#endif
11910Sstevel@tonic-gate					return (-1);
11920Sstevel@tonic-gate				}
11930Sstevel@tonic-gate				/* blast back to INIT state */
11940Sstevel@tonic-gate				sctp_toss_old_cookies(stcb, &stcb->asoc);
11950Sstevel@tonic-gate				asoc->state &= ~SCTP_STATE_COOKIE_ECHOED;
11960Sstevel@tonic-gate				asoc->state |= SCTP_STATE_COOKIE_WAIT;
11970Sstevel@tonic-gate				sctp_stop_all_cookie_timers(stcb);
11980Sstevel@tonic-gate				sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
11990Sstevel@tonic-gate			}
12000Sstevel@tonic-gate			break;
12010Sstevel@tonic-gate		case SCTP_CAUSE_UNRESOLVABLE_ADDR:
12020Sstevel@tonic-gate			/*
12030Sstevel@tonic-gate			 * Nothing we can do here, we don't do hostname
12040Sstevel@tonic-gate			 * addresses so if the peer does not like my IPv6
12050Sstevel@tonic-gate			 * (or IPv4 for that matter) it does not matter. If
12060Sstevel@tonic-gate			 * they don't support that type of address, they can
12070Sstevel@tonic-gate			 * NOT possibly get that packet type... i.e. with no
12080Sstevel@tonic-gate			 * IPv6 you can't recieve a IPv6 packet. so we can
12090Sstevel@tonic-gate			 * safely ignore this one. If we ever added support
12100Sstevel@tonic-gate			 * for HOSTNAME Addresses, then we would need to do
12110Sstevel@tonic-gate			 * something here.
12120Sstevel@tonic-gate			 */
12130Sstevel@tonic-gate			break;
12140Sstevel@tonic-gate		case SCTP_CAUSE_UNRECOG_CHUNK:
12150Sstevel@tonic-gate			sctp_process_unrecog_chunk(stcb, phdr, net);
12160Sstevel@tonic-gate			break;
12170Sstevel@tonic-gate		case SCTP_CAUSE_UNRECOG_PARAM:
12180Sstevel@tonic-gate			sctp_process_unrecog_param(stcb, phdr);
12190Sstevel@tonic-gate			break;
12200Sstevel@tonic-gate		case SCTP_CAUSE_COOKIE_IN_SHUTDOWN:
12210Sstevel@tonic-gate			/*
12220Sstevel@tonic-gate			 * We ignore this since the timer will drive out a
12230Sstevel@tonic-gate			 * new cookie anyway and there timer will drive us
12240Sstevel@tonic-gate			 * to send a SHUTDOWN_COMPLETE. We can't send one
12250Sstevel@tonic-gate			 * here since we don't have their tag.
12260Sstevel@tonic-gate			 */
12270Sstevel@tonic-gate			break;
12280Sstevel@tonic-gate		case SCTP_CAUSE_DELETING_LAST_ADDR:
12290Sstevel@tonic-gate		case SCTP_CAUSE_RESOURCE_SHORTAGE:
12300Sstevel@tonic-gate		case SCTP_CAUSE_DELETING_SRC_ADDR:
12310Sstevel@tonic-gate			/*
12320Sstevel@tonic-gate			 * We should NOT get these here, but in a
12330Sstevel@tonic-gate			 * ASCONF-ACK.
12340Sstevel@tonic-gate			 */
12350Sstevel@tonic-gate			SCTPDBG(SCTP_DEBUG_INPUT2, "Peer sends ASCONF errors in a Operational Error?<%d>?\n",
12360Sstevel@tonic-gate			    error_type);
12370Sstevel@tonic-gate			break;
12380Sstevel@tonic-gate		case SCTP_CAUSE_OUT_OF_RESC:
12390Sstevel@tonic-gate			/*
12400Sstevel@tonic-gate			 * And what, pray tell do we do with the fact that
12410Sstevel@tonic-gate			 * the peer is out of resources? Not really sure we
12420Sstevel@tonic-gate			 * could do anything but abort. I suspect this
12430Sstevel@tonic-gate			 * should have came WITH an abort instead of in a
12440Sstevel@tonic-gate			 * OP-ERROR.
12450Sstevel@tonic-gate			 */
12460Sstevel@tonic-gate			break;
12470Sstevel@tonic-gate		default:
12480Sstevel@tonic-gate			SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_handle_error: unknown error type = 0x%xh\n",
12490Sstevel@tonic-gate			    error_type);
12500Sstevel@tonic-gate			break;
12510Sstevel@tonic-gate		}
12520Sstevel@tonic-gate		adjust = SCTP_SIZE32(error_len);
12530Sstevel@tonic-gate		chklen -= adjust;
12540Sstevel@tonic-gate		phdr = (struct sctp_paramhdr *)((caddr_t)phdr + adjust);
12550Sstevel@tonic-gate	}
12560Sstevel@tonic-gate	return (0);
12570Sstevel@tonic-gate}
12580Sstevel@tonic-gate
12590Sstevel@tonic-gatestatic int
12600Sstevel@tonic-gatesctp_handle_init_ack(struct mbuf *m, int iphlen, int offset,
12610Sstevel@tonic-gate    struct sctphdr *sh, struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
12620Sstevel@tonic-gate    struct sctp_nets *net, int *abort_no_unlock, uint32_t vrf_id)
12630Sstevel@tonic-gate{
12640Sstevel@tonic-gate	struct sctp_init_ack *init_ack;
12650Sstevel@tonic-gate	struct mbuf *op_err;
12660Sstevel@tonic-gate
12670Sstevel@tonic-gate	SCTPDBG(SCTP_DEBUG_INPUT2,
12680Sstevel@tonic-gate	    "sctp_handle_init_ack: handling INIT-ACK\n");
12690Sstevel@tonic-gate
12700Sstevel@tonic-gate	if (stcb == NULL) {
12710Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT2,
12720Sstevel@tonic-gate		    "sctp_handle_init_ack: TCB is null\n");
12730Sstevel@tonic-gate		return (-1);
12740Sstevel@tonic-gate	}
12750Sstevel@tonic-gate	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) {
12760Sstevel@tonic-gate		/* Invalid length */
12770Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
12780Sstevel@tonic-gate		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
12790Sstevel@tonic-gate		    op_err, 0, net->port);
12800Sstevel@tonic-gate		*abort_no_unlock = 1;
12810Sstevel@tonic-gate		return (-1);
12820Sstevel@tonic-gate	}
12830Sstevel@tonic-gate	init_ack = &cp->init;
12840Sstevel@tonic-gate	/* validate parameters */
12850Sstevel@tonic-gate	if (init_ack->initiate_tag == 0) {
12860Sstevel@tonic-gate		/* protocol error... send an abort */
12870Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
12880Sstevel@tonic-gate		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
12890Sstevel@tonic-gate		    op_err, 0, net->port);
12900Sstevel@tonic-gate		*abort_no_unlock = 1;
12910Sstevel@tonic-gate		return (-1);
12920Sstevel@tonic-gate	}
12930Sstevel@tonic-gate	if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) {
12940Sstevel@tonic-gate		/* protocol error... send an abort */
12950Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
12960Sstevel@tonic-gate		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
12970Sstevel@tonic-gate		    op_err, 0, net->port);
12980Sstevel@tonic-gate		*abort_no_unlock = 1;
12990Sstevel@tonic-gate		return (-1);
13000Sstevel@tonic-gate	}
13010Sstevel@tonic-gate	if (init_ack->num_inbound_streams == 0) {
13020Sstevel@tonic-gate		/* protocol error... send an abort */
13030Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
13040Sstevel@tonic-gate		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
13050Sstevel@tonic-gate		    op_err, 0, net->port);
13060Sstevel@tonic-gate		*abort_no_unlock = 1;
13070Sstevel@tonic-gate		return (-1);
13080Sstevel@tonic-gate	}
13090Sstevel@tonic-gate	if (init_ack->num_outbound_streams == 0) {
13100Sstevel@tonic-gate		/* protocol error... send an abort */
13110Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
13120Sstevel@tonic-gate		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
13130Sstevel@tonic-gate		    op_err, 0, net->port);
13140Sstevel@tonic-gate		*abort_no_unlock = 1;
13150Sstevel@tonic-gate		return (-1);
13160Sstevel@tonic-gate	}
13170Sstevel@tonic-gate	/* process according to association state... */
13180Sstevel@tonic-gate	switch (stcb->asoc.state & SCTP_STATE_MASK) {
13190Sstevel@tonic-gate	case SCTP_STATE_COOKIE_WAIT:
13200Sstevel@tonic-gate		/* this is the expected state for this chunk */
13210Sstevel@tonic-gate		/* process the INIT-ACK parameters */
13220Sstevel@tonic-gate		if (stcb->asoc.primary_destination->dest_state &
13230Sstevel@tonic-gate		    SCTP_ADDR_UNCONFIRMED) {
13240Sstevel@tonic-gate			/*
13250Sstevel@tonic-gate			 * The primary is where we sent the INIT, we can
13260Sstevel@tonic-gate			 * always consider it confirmed when the INIT-ACK is
13270Sstevel@tonic-gate			 * returned. Do this before we load addresses
13280Sstevel@tonic-gate			 * though.
13290Sstevel@tonic-gate			 */
13300Sstevel@tonic-gate			stcb->asoc.primary_destination->dest_state &=
13310Sstevel@tonic-gate			    ~SCTP_ADDR_UNCONFIRMED;
13320Sstevel@tonic-gate			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
13330Sstevel@tonic-gate			    stcb, 0, (void *)stcb->asoc.primary_destination, SCTP_SO_NOT_LOCKED);
13340Sstevel@tonic-gate		}
13350Sstevel@tonic-gate		if (sctp_process_init_ack(m, iphlen, offset, sh, cp, stcb,
13360Sstevel@tonic-gate		    net, abort_no_unlock, vrf_id) < 0) {
13370Sstevel@tonic-gate			/* error in parsing parameters */
13380Sstevel@tonic-gate			return (-1);
13390Sstevel@tonic-gate		}
13400Sstevel@tonic-gate		/* update our state */
13410Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT2, "moving to COOKIE-ECHOED state\n");
13420Sstevel@tonic-gate		SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_ECHOED);
13430Sstevel@tonic-gate
13440Sstevel@tonic-gate		/* reset the RTO calc */
13450Sstevel@tonic-gate		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
13460Sstevel@tonic-gate			sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
13470Sstevel@tonic-gate			    stcb->asoc.overall_error_count,
13480Sstevel@tonic-gate			    0,
13490Sstevel@tonic-gate			    SCTP_FROM_SCTP_INPUT,
13500Sstevel@tonic-gate			    __LINE__);
13510Sstevel@tonic-gate		}
13520Sstevel@tonic-gate		stcb->asoc.overall_error_count = 0;
13530Sstevel@tonic-gate		(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
13540Sstevel@tonic-gate		/*
13550Sstevel@tonic-gate		 * collapse the init timer back in case of a exponential
13560Sstevel@tonic-gate		 * backoff
13570Sstevel@tonic-gate		 */
13580Sstevel@tonic-gate		sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep,
13590Sstevel@tonic-gate		    stcb, net);
13600Sstevel@tonic-gate		/*
13610Sstevel@tonic-gate		 * the send at the end of the inbound data processing will
13620Sstevel@tonic-gate		 * cause the cookie to be sent
13630Sstevel@tonic-gate		 */
13640Sstevel@tonic-gate		break;
13650Sstevel@tonic-gate	case SCTP_STATE_SHUTDOWN_SENT:
13660Sstevel@tonic-gate		/* incorrect state... discard */
13670Sstevel@tonic-gate		break;
13680Sstevel@tonic-gate	case SCTP_STATE_COOKIE_ECHOED:
13690Sstevel@tonic-gate		/* incorrect state... discard */
13700Sstevel@tonic-gate		break;
13710Sstevel@tonic-gate	case SCTP_STATE_OPEN:
13720Sstevel@tonic-gate		/* incorrect state... discard */
13730Sstevel@tonic-gate		break;
13740Sstevel@tonic-gate	case SCTP_STATE_EMPTY:
13750Sstevel@tonic-gate	case SCTP_STATE_INUSE:
13760Sstevel@tonic-gate	default:
13770Sstevel@tonic-gate		/* incorrect state... discard */
13780Sstevel@tonic-gate		return (-1);
13797627SChris.Horne@Sun.COM		break;
13800Sstevel@tonic-gate	}
13810Sstevel@tonic-gate	SCTPDBG(SCTP_DEBUG_INPUT1, "Leaving handle-init-ack end\n");
13820Sstevel@tonic-gate	return (0);
13831623Stw21770}
13840Sstevel@tonic-gate
13850Sstevel@tonic-gatestatic struct sctp_tcb *
13860Sstevel@tonic-gatesctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
13870Sstevel@tonic-gate    struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
13880Sstevel@tonic-gate    struct sctp_inpcb *inp, struct sctp_nets **netp,
13890Sstevel@tonic-gate    struct sockaddr *init_src, int *notification,
13900Sstevel@tonic-gate    int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
13910Sstevel@tonic-gate    uint32_t vrf_id, uint16_t port);
13920Sstevel@tonic-gate
13930Sstevel@tonic-gate
13941623Stw21770/*
13950Sstevel@tonic-gate * handle a state cookie for an existing association m: input packet mbuf
13960Sstevel@tonic-gate * chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a
13970Sstevel@tonic-gate * "split" mbuf and the cookie signature does not exist offset: offset into
13980Sstevel@tonic-gate * mbuf to the cookie-echo chunk
13990Sstevel@tonic-gate */
14001623Stw21770static struct sctp_tcb *
14011623Stw21770sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
14021623Stw21770    struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
14031623Stw21770    struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets **netp,
14041623Stw21770    struct sockaddr *init_src, int *notification,
14050Sstevel@tonic-gate    uint32_t vrf_id, int auth_skipped, uint32_t auth_offset, uint32_t auth_len, uint16_t port)
14061623Stw21770{
14070Sstevel@tonic-gate	struct sctp_association *asoc;
14081623Stw21770	struct sctp_init_chunk *init_cp, init_buf;
14090Sstevel@tonic-gate	struct sctp_init_ack_chunk *initack_cp, initack_buf;
14100Sstevel@tonic-gate	struct sctp_nets *net;
14110Sstevel@tonic-gate	struct mbuf *op_err;
14120Sstevel@tonic-gate	struct sctp_paramhdr *ph;
14130Sstevel@tonic-gate	int init_offset, initack_offset, i;
14140Sstevel@tonic-gate	int retval;
14150Sstevel@tonic-gate	int spec_flag = 0;
14160Sstevel@tonic-gate	uint32_t how_indx;
14170Sstevel@tonic-gate
14184954Sachimm	net = *netp;
14190Sstevel@tonic-gate	/* I know that the TCB is non-NULL from the caller */
14200Sstevel@tonic-gate	asoc = &stcb->asoc;
14210Sstevel@tonic-gate	for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); how_indx++) {
14220Sstevel@tonic-gate		if (asoc->cookie_how[how_indx] == 0)
14230Sstevel@tonic-gate			break;
14240Sstevel@tonic-gate	}
14250Sstevel@tonic-gate	if (how_indx < sizeof(asoc->cookie_how)) {
14260Sstevel@tonic-gate		asoc->cookie_how[how_indx] = 1;
14270Sstevel@tonic-gate	}
14280Sstevel@tonic-gate	if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
14290Sstevel@tonic-gate		/* SHUTDOWN came in after sending INIT-ACK */
14300Sstevel@tonic-gate		sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
14310Sstevel@tonic-gate		op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
14320Sstevel@tonic-gate		    0, M_DONTWAIT, 1, MT_DATA);
14330Sstevel@tonic-gate		if (op_err == NULL) {
14340Sstevel@tonic-gate			/* FOOBAR */
14350Sstevel@tonic-gate			return (NULL);
14360Sstevel@tonic-gate		}
14370Sstevel@tonic-gate		/* Set the len */
14380Sstevel@tonic-gate		SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
14390Sstevel@tonic-gate		ph = mtod(op_err, struct sctp_paramhdr *);
14400Sstevel@tonic-gate		ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN);
14410Sstevel@tonic-gate		ph->param_length = htons(sizeof(struct sctp_paramhdr));
14420Sstevel@tonic-gate		sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag,
14430Sstevel@tonic-gate		    vrf_id, net->port);
14440Sstevel@tonic-gate		if (how_indx < sizeof(asoc->cookie_how))
14450Sstevel@tonic-gate			asoc->cookie_how[how_indx] = 2;
14460Sstevel@tonic-gate		return (NULL);
14470Sstevel@tonic-gate	}
14480Sstevel@tonic-gate	/*
14490Sstevel@tonic-gate	 * find and validate the INIT chunk in the cookie (peer's info) the
14500Sstevel@tonic-gate	 * INIT should start after the cookie-echo header struct (chunk
14510Sstevel@tonic-gate	 * header, state cookie header struct)
14520Sstevel@tonic-gate	 */
14530Sstevel@tonic-gate	init_offset = offset += sizeof(struct sctp_cookie_echo_chunk);
14540Sstevel@tonic-gate
14550Sstevel@tonic-gate	init_cp = (struct sctp_init_chunk *)
14560Sstevel@tonic-gate	    sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk),
14570Sstevel@tonic-gate	    (uint8_t *) & init_buf);
14580Sstevel@tonic-gate	if (init_cp == NULL) {
14590Sstevel@tonic-gate		/* could not pull a INIT chunk in cookie */
14600Sstevel@tonic-gate		return (NULL);
14610Sstevel@tonic-gate	}
14620Sstevel@tonic-gate	if (init_cp->ch.chunk_type != SCTP_INITIATION) {
14630Sstevel@tonic-gate		return (NULL);
14640Sstevel@tonic-gate	}
14650Sstevel@tonic-gate	/*
14660Sstevel@tonic-gate	 * find and validate the INIT-ACK chunk in the cookie (my info) the
14670Sstevel@tonic-gate	 * INIT-ACK follows the INIT chunk
14680Sstevel@tonic-gate	 */
14690Sstevel@tonic-gate	initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length));
14700Sstevel@tonic-gate	initack_cp = (struct sctp_init_ack_chunk *)
14710Sstevel@tonic-gate	    sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk),
14720Sstevel@tonic-gate	    (uint8_t *) & initack_buf);
14730Sstevel@tonic-gate	if (initack_cp == NULL) {
14740Sstevel@tonic-gate		/* could not pull INIT-ACK chunk in cookie */
14754954Sachimm		return (NULL);
14760Sstevel@tonic-gate	}
14770Sstevel@tonic-gate	if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) {
14780Sstevel@tonic-gate		return (NULL);
14790Sstevel@tonic-gate	}
14800Sstevel@tonic-gate	if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) &&
14810Sstevel@tonic-gate	    (ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag)) {
14820Sstevel@tonic-gate		/*
14830Sstevel@tonic-gate		 * case D in Section 5.2.4 Table 2: MMAA process accordingly
14840Sstevel@tonic-gate		 * to get into the OPEN state
14850Sstevel@tonic-gate		 */
14860Sstevel@tonic-gate		if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) {
14870Sstevel@tonic-gate			/*-
14880Sstevel@tonic-gate			 * Opps, this means that we somehow generated two vtag's
14890Sstevel@tonic-gate			 * the same. I.e. we did:
14900Sstevel@tonic-gate			 *  Us               Peer
14910Sstevel@tonic-gate			 *   <---INIT(tag=a)------
14920Sstevel@tonic-gate			 *   ----INIT-ACK(tag=t)-->
14930Sstevel@tonic-gate			 *   ----INIT(tag=t)------> *1
14940Sstevel@tonic-gate			 *   <---INIT-ACK(tag=a)---
14950Sstevel@tonic-gate                         *   <----CE(tag=t)------------- *2
14960Sstevel@tonic-gate			 *
14970Sstevel@tonic-gate			 * At point *1 we should be generating a different
14980Sstevel@tonic-gate			 * tag t'. Which means we would throw away the CE and send
14990Sstevel@tonic-gate			 * ours instead. Basically this is case C (throw away side).
15000Sstevel@tonic-gate			 */
15010Sstevel@tonic-gate			if (how_indx < sizeof(asoc->cookie_how))
15020Sstevel@tonic-gate				asoc->cookie_how[how_indx] = 17;
15030Sstevel@tonic-gate			return (NULL);
15040Sstevel@tonic-gate
15050Sstevel@tonic-gate		}
15060Sstevel@tonic-gate		switch SCTP_GET_STATE
15070Sstevel@tonic-gate			(asoc) {
15080Sstevel@tonic-gate		case SCTP_STATE_COOKIE_WAIT:
15090Sstevel@tonic-gate		case SCTP_STATE_COOKIE_ECHOED:
15100Sstevel@tonic-gate			/*
15110Sstevel@tonic-gate			 * INIT was sent but got a COOKIE_ECHO with the
15120Sstevel@tonic-gate			 * correct tags... just accept it...but we must
15130Sstevel@tonic-gate			 * process the init so that we can make sure we have
15140Sstevel@tonic-gate			 * the right seq no's.
15150Sstevel@tonic-gate			 */
15160Sstevel@tonic-gate			/* First we must process the INIT !! */
15170Sstevel@tonic-gate			retval = sctp_process_init(init_cp, stcb);
15180Sstevel@tonic-gate			if (retval < 0) {
15190Sstevel@tonic-gate				if (how_indx < sizeof(asoc->cookie_how))
15200Sstevel@tonic-gate					asoc->cookie_how[how_indx] = 3;
15210Sstevel@tonic-gate				return (NULL);
15220Sstevel@tonic-gate			}
15230Sstevel@tonic-gate			/* we have already processed the INIT so no problem */
15240Sstevel@tonic-gate			sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb,
15250Sstevel@tonic-gate			    net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_12);
15260Sstevel@tonic-gate			sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_13);
15270Sstevel@tonic-gate			/* update current state */
15280Sstevel@tonic-gate			if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)
15290Sstevel@tonic-gate				SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
15300Sstevel@tonic-gate			else
15310Sstevel@tonic-gate				SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
15320Sstevel@tonic-gate
15330Sstevel@tonic-gate			SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
15340Sstevel@tonic-gate			if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
15350Sstevel@tonic-gate				sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
15360Sstevel@tonic-gate				    stcb->sctp_ep, stcb, asoc->primary_destination);
15370Sstevel@tonic-gate			}
15380Sstevel@tonic-gate			SCTP_STAT_INCR_GAUGE32(sctps_currestab);
15390Sstevel@tonic-gate			sctp_stop_all_cookie_timers(stcb);
15400Sstevel@tonic-gate			if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
15410Sstevel@tonic-gate			    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
15420Sstevel@tonic-gate			    (inp->sctp_socket->so_qlimit == 0)
15430Sstevel@tonic-gate			    ) {
15440Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
15450Sstevel@tonic-gate				struct socket *so;
15460Sstevel@tonic-gate
15470Sstevel@tonic-gate#endif
15480Sstevel@tonic-gate				/*
15490Sstevel@tonic-gate				 * Here is where collision would go if we
15500Sstevel@tonic-gate				 * did a connect() and instead got a
15510Sstevel@tonic-gate				 * init/init-ack/cookie done before the
15520Sstevel@tonic-gate				 * init-ack came back..
15530Sstevel@tonic-gate				 */
15540Sstevel@tonic-gate				stcb->sctp_ep->sctp_flags |=
15550Sstevel@tonic-gate				    SCTP_PCB_FLAGS_CONNECTED;
15560Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
15570Sstevel@tonic-gate				so = SCTP_INP_SO(stcb->sctp_ep);
15580Sstevel@tonic-gate				atomic_add_int(&stcb->asoc.refcnt, 1);
15590Sstevel@tonic-gate				SCTP_TCB_UNLOCK(stcb);
15600Sstevel@tonic-gate				SCTP_SOCKET_LOCK(so, 1);
15610Sstevel@tonic-gate				SCTP_TCB_LOCK(stcb);
15620Sstevel@tonic-gate				atomic_add_int(&stcb->asoc.refcnt, -1);
15630Sstevel@tonic-gate				if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
15640Sstevel@tonic-gate					SCTP_SOCKET_UNLOCK(so, 1);
15650Sstevel@tonic-gate					return (NULL);
15660Sstevel@tonic-gate				}
15670Sstevel@tonic-gate#endif
15680Sstevel@tonic-gate				soisconnected(stcb->sctp_socket);
15690Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
15700Sstevel@tonic-gate				SCTP_SOCKET_UNLOCK(so, 1);
15710Sstevel@tonic-gate#endif
15720Sstevel@tonic-gate			}
15730Sstevel@tonic-gate			/* notify upper layer */
15740Sstevel@tonic-gate			*notification = SCTP_NOTIFY_ASSOC_UP;
15750Sstevel@tonic-gate			/*
15760Sstevel@tonic-gate			 * since we did not send a HB make sure we don't
15770Sstevel@tonic-gate			 * double things
15780Sstevel@tonic-gate			 */
15790Sstevel@tonic-gate			net->hb_responded = 1;
15800Sstevel@tonic-gate			net->RTO = sctp_calculate_rto(stcb, asoc, net,
15810Sstevel@tonic-gate			    &cookie->time_entered,
15820Sstevel@tonic-gate			    sctp_align_unsafe_makecopy,
15830Sstevel@tonic-gate			    SCTP_RTT_FROM_NON_DATA);
15840Sstevel@tonic-gate
15850Sstevel@tonic-gate			if (stcb->asoc.sctp_autoclose_ticks &&
15860Sstevel@tonic-gate			    (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) {
15870Sstevel@tonic-gate				sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE,
15880Sstevel@tonic-gate				    inp, stcb, NULL);
15890Sstevel@tonic-gate			}
15900Sstevel@tonic-gate			break;
15910Sstevel@tonic-gate		default:
15920Sstevel@tonic-gate			/*
15930Sstevel@tonic-gate			 * we're in the OPEN state (or beyond), so peer must
15940Sstevel@tonic-gate			 * have simply lost the COOKIE-ACK
15950Sstevel@tonic-gate			 */
15960Sstevel@tonic-gate			break;
15970Sstevel@tonic-gate			}	/* end switch */
15980Sstevel@tonic-gate		sctp_stop_all_cookie_timers(stcb);
15990Sstevel@tonic-gate		/*
16000Sstevel@tonic-gate		 * We ignore the return code here.. not sure if we should
16010Sstevel@tonic-gate		 * somehow abort.. but we do have an existing asoc. This
16020Sstevel@tonic-gate		 * really should not fail.
16030Sstevel@tonic-gate		 */
16040Sstevel@tonic-gate		if (sctp_load_addresses_from_init(stcb, m,
16050Sstevel@tonic-gate		    init_offset + sizeof(struct sctp_init_chunk),
16060Sstevel@tonic-gate		    initack_offset, sh, init_src)) {
16070Sstevel@tonic-gate			if (how_indx < sizeof(asoc->cookie_how))
16080Sstevel@tonic-gate				asoc->cookie_how[how_indx] = 4;
16090Sstevel@tonic-gate			return (NULL);
16100Sstevel@tonic-gate		}
16110Sstevel@tonic-gate		/* respond with a COOKIE-ACK */
16120Sstevel@tonic-gate		sctp_toss_old_cookies(stcb, asoc);
16130Sstevel@tonic-gate		sctp_send_cookie_ack(stcb);
16140Sstevel@tonic-gate		if (how_indx < sizeof(asoc->cookie_how))
16150Sstevel@tonic-gate			asoc->cookie_how[how_indx] = 5;
16160Sstevel@tonic-gate		return (stcb);
16170Sstevel@tonic-gate	}
16180Sstevel@tonic-gate	if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag &&
16190Sstevel@tonic-gate	    ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag &&
16200Sstevel@tonic-gate	    cookie->tie_tag_my_vtag == 0 &&
16210Sstevel@tonic-gate	    cookie->tie_tag_peer_vtag == 0) {
16220Sstevel@tonic-gate		/*
16230Sstevel@tonic-gate		 * case C in Section 5.2.4 Table 2: XMOO silently discard
16240Sstevel@tonic-gate		 */
16250Sstevel@tonic-gate		if (how_indx < sizeof(asoc->cookie_how))
16260Sstevel@tonic-gate			asoc->cookie_how[how_indx] = 6;
16270Sstevel@tonic-gate		return (NULL);
16280Sstevel@tonic-gate	}
16290Sstevel@tonic-gate	/*
16300Sstevel@tonic-gate	 * If nat support, and the below and stcb is established, send back
16310Sstevel@tonic-gate	 * a ABORT(colliding state) if we are established.
16320Sstevel@tonic-gate	 */
16338452SJohn.Wren.Kennedy@Sun.COM	if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) &&
16340Sstevel@tonic-gate	    (asoc->peer_supports_nat) &&
16350Sstevel@tonic-gate	    ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) &&
16360Sstevel@tonic-gate	    ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) ||
16370Sstevel@tonic-gate	    (asoc->peer_vtag == 0)))) {
16380Sstevel@tonic-gate		/*
16390Sstevel@tonic-gate		 * Special case - Peer's support nat. We may have two init's
16400Sstevel@tonic-gate		 * that we gave out the same tag on since one was not
16410Sstevel@tonic-gate		 * established.. i.e. we get INIT from host-1 behind the nat
16420Sstevel@tonic-gate		 * and we respond tag-a, we get a INIT from host-2 behind
16430Sstevel@tonic-gate		 * the nat and we get tag-a again. Then we bring up host-1
16440Sstevel@tonic-gate		 * (or 2's) assoc, Then comes the cookie from hsot-2 (or 1).
16450Sstevel@tonic-gate		 * Now we have colliding state. We must send an abort here
16460Sstevel@tonic-gate		 * with colliding state indication.
16470Sstevel@tonic-gate		 */
16480Sstevel@tonic-gate		op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
16490Sstevel@tonic-gate		    0, M_DONTWAIT, 1, MT_DATA);
16500Sstevel@tonic-gate		if (op_err == NULL) {
16510Sstevel@tonic-gate			/* FOOBAR */
16520Sstevel@tonic-gate			return (NULL);
16530Sstevel@tonic-gate		}
16540Sstevel@tonic-gate		/* pre-reserve some space */
16550Sstevel@tonic-gate#ifdef INET6
16560Sstevel@tonic-gate		SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
16570Sstevel@tonic-gate#else
16580Sstevel@tonic-gate		SCTP_BUF_RESV_UF(op_err, sizeof(struct ip));
16590Sstevel@tonic-gate#endif
16600Sstevel@tonic-gate		SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
16610Sstevel@tonic-gate		SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
16620Sstevel@tonic-gate		/* Set the len */
16630Sstevel@tonic-gate		SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
16640Sstevel@tonic-gate		ph = mtod(op_err, struct sctp_paramhdr *);
16650Sstevel@tonic-gate		ph->param_type = htons(SCTP_CAUSE_NAT_COLLIDING_STATE);
16660Sstevel@tonic-gate		ph->param_length = htons(sizeof(struct sctp_paramhdr));
16670Sstevel@tonic-gate		sctp_send_abort(m, iphlen, sh, 0, op_err, vrf_id, port);
16680Sstevel@tonic-gate		return (NULL);
16690Sstevel@tonic-gate	}
16700Sstevel@tonic-gate	if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) &&
16710Sstevel@tonic-gate	    ((ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) ||
16720Sstevel@tonic-gate	    (asoc->peer_vtag == 0))) {
16738452SJohn.Wren.Kennedy@Sun.COM		/*
16748452SJohn.Wren.Kennedy@Sun.COM		 * case B in Section 5.2.4 Table 2: MXAA or MOAA my info
16750Sstevel@tonic-gate		 * should be ok, re-accept peer info
16760Sstevel@tonic-gate		 */
16770Sstevel@tonic-gate		if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) {
16780Sstevel@tonic-gate			/*
16790Sstevel@tonic-gate			 * Extension of case C. If we hit this, then the
16800Sstevel@tonic-gate			 * random number generator returned the same vtag
16810Sstevel@tonic-gate			 * when we first sent our INIT-ACK and when we later
16820Sstevel@tonic-gate			 * sent our INIT. The side with the seq numbers that
16830Sstevel@tonic-gate			 * are different will be the one that normnally
16840Sstevel@tonic-gate			 * would have hit case C. This in effect "extends"
16850Sstevel@tonic-gate			 * our vtags in this collision case to be 64 bits.
16860Sstevel@tonic-gate			 * The same collision could occur aka you get both
16870Sstevel@tonic-gate			 * vtag and seq number the same twice in a row.. but
16880Sstevel@tonic-gate			 * is much less likely. If it did happen then we
16890Sstevel@tonic-gate			 * would proceed through and bring up the assoc.. we
16900Sstevel@tonic-gate			 * may end up with the wrong stream setup however..
16910Sstevel@tonic-gate			 * which would be bad.. but there is no way to
16920Sstevel@tonic-gate			 * tell.. until we send on a stream that does not
16930Sstevel@tonic-gate			 * exist :-)
16940Sstevel@tonic-gate			 */
16950Sstevel@tonic-gate			if (how_indx < sizeof(asoc->cookie_how))
16960Sstevel@tonic-gate				asoc->cookie_how[how_indx] = 7;
16970Sstevel@tonic-gate
16984954Sachimm			return (NULL);
16990Sstevel@tonic-gate		}
17000Sstevel@tonic-gate		if (how_indx < sizeof(asoc->cookie_how))
17010Sstevel@tonic-gate			asoc->cookie_how[how_indx] = 8;
17020Sstevel@tonic-gate		sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_14);
17036901Sjkennedy		sctp_stop_all_cookie_timers(stcb);
17040Sstevel@tonic-gate		/*
17050Sstevel@tonic-gate		 * since we did not send a HB make sure we don't double
17066901Sjkennedy		 * things
17070Sstevel@tonic-gate		 */
17080Sstevel@tonic-gate		net->hb_responded = 1;
17090Sstevel@tonic-gate		if (stcb->asoc.sctp_autoclose_ticks &&
17100Sstevel@tonic-gate		    sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) {
17110Sstevel@tonic-gate			sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb,
17120Sstevel@tonic-gate			    NULL);
17130Sstevel@tonic-gate		}
17140Sstevel@tonic-gate		asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
17150Sstevel@tonic-gate		asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams);
17160Sstevel@tonic-gate
17170Sstevel@tonic-gate		if (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) {
17180Sstevel@tonic-gate			/*
17190Sstevel@tonic-gate			 * Ok the peer probably discarded our data (if we
17200Sstevel@tonic-gate			 * echoed a cookie+data). So anything on the
17210Sstevel@tonic-gate			 * sent_queue should be marked for retransmit, we
17220Sstevel@tonic-gate			 * may not get something to kick us so it COULD
17230Sstevel@tonic-gate			 * still take a timeout to move these.. but it can't
17240Sstevel@tonic-gate			 * hurt to mark them.
17250Sstevel@tonic-gate			 */
17260Sstevel@tonic-gate			struct sctp_tmit_chunk *chk;
17270Sstevel@tonic-gate
17280Sstevel@tonic-gate			TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
17290Sstevel@tonic-gate				if (chk->sent < SCTP_DATAGRAM_RESEND) {
17300Sstevel@tonic-gate					chk->sent = SCTP_DATAGRAM_RESEND;
17310Sstevel@tonic-gate					sctp_flight_size_decrease(chk);
17320Sstevel@tonic-gate					sctp_total_flight_decrease(stcb, chk);
17330Sstevel@tonic-gate					sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
17340Sstevel@tonic-gate					spec_flag++;
17350Sstevel@tonic-gate				}
17360Sstevel@tonic-gate			}
17370Sstevel@tonic-gate
17380Sstevel@tonic-gate		}
17390Sstevel@tonic-gate		/* process the INIT info (peer's info) */
17400Sstevel@tonic-gate		retval = sctp_process_init(init_cp, stcb);
17410Sstevel@tonic-gate		if (retval < 0) {
17420Sstevel@tonic-gate			if (how_indx < sizeof(asoc->cookie_how))
17430Sstevel@tonic-gate				asoc->cookie_how[how_indx] = 9;
17440Sstevel@tonic-gate			return (NULL);
17450Sstevel@tonic-gate		}
17460Sstevel@tonic-gate		if (sctp_load_addresses_from_init(stcb, m,
17470Sstevel@tonic-gate		    init_offset + sizeof(struct sctp_init_chunk),
17480Sstevel@tonic-gate		    initack_offset, sh, init_src)) {
17490Sstevel@tonic-gate			if (how_indx < sizeof(asoc->cookie_how))
17500Sstevel@tonic-gate				asoc->cookie_how[how_indx] = 10;
17510Sstevel@tonic-gate			return (NULL);
17520Sstevel@tonic-gate		}
17530Sstevel@tonic-gate		if ((asoc->state & SCTP_STATE_COOKIE_WAIT) ||
17540Sstevel@tonic-gate		    (asoc->state & SCTP_STATE_COOKIE_ECHOED)) {
17550Sstevel@tonic-gate			*notification = SCTP_NOTIFY_ASSOC_UP;
17560Sstevel@tonic-gate
17570Sstevel@tonic-gate			if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
17580Sstevel@tonic-gate			    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
17590Sstevel@tonic-gate			    (inp->sctp_socket->so_qlimit == 0)) {
17600Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
17610Sstevel@tonic-gate				struct socket *so;
17620Sstevel@tonic-gate
17630Sstevel@tonic-gate#endif
17640Sstevel@tonic-gate				stcb->sctp_ep->sctp_flags |=
17650Sstevel@tonic-gate				    SCTP_PCB_FLAGS_CONNECTED;
17660Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
17670Sstevel@tonic-gate				so = SCTP_INP_SO(stcb->sctp_ep);
17680Sstevel@tonic-gate				atomic_add_int(&stcb->asoc.refcnt, 1);
17690Sstevel@tonic-gate				SCTP_TCB_UNLOCK(stcb);
17700Sstevel@tonic-gate				SCTP_SOCKET_LOCK(so, 1);
17710Sstevel@tonic-gate				SCTP_TCB_LOCK(stcb);
17720Sstevel@tonic-gate				atomic_add_int(&stcb->asoc.refcnt, -1);
17730Sstevel@tonic-gate				if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
17740Sstevel@tonic-gate					SCTP_SOCKET_UNLOCK(so, 1);
17750Sstevel@tonic-gate					return (NULL);
17760Sstevel@tonic-gate				}
17770Sstevel@tonic-gate#endif
17780Sstevel@tonic-gate				soisconnected(stcb->sctp_socket);
17790Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
17800Sstevel@tonic-gate				SCTP_SOCKET_UNLOCK(so, 1);
17810Sstevel@tonic-gate#endif
17820Sstevel@tonic-gate			}
17830Sstevel@tonic-gate			if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED)
17840Sstevel@tonic-gate				SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
17850Sstevel@tonic-gate			else
17860Sstevel@tonic-gate				SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
17870Sstevel@tonic-gate			SCTP_STAT_INCR_GAUGE32(sctps_currestab);
17880Sstevel@tonic-gate		} else if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
17890Sstevel@tonic-gate			SCTP_STAT_INCR_COUNTER32(sctps_restartestab);
17900Sstevel@tonic-gate		} else {
17910Sstevel@tonic-gate			SCTP_STAT_INCR_COUNTER32(sctps_collisionestab);
17920Sstevel@tonic-gate		}
17930Sstevel@tonic-gate		SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
17940Sstevel@tonic-gate		if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
17950Sstevel@tonic-gate			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
17960Sstevel@tonic-gate			    stcb->sctp_ep, stcb, asoc->primary_destination);
17970Sstevel@tonic-gate		}
17980Sstevel@tonic-gate		sctp_stop_all_cookie_timers(stcb);
17990Sstevel@tonic-gate		sctp_toss_old_cookies(stcb, asoc);
18000Sstevel@tonic-gate		sctp_send_cookie_ack(stcb);
18010Sstevel@tonic-gate		if (spec_flag) {
18020Sstevel@tonic-gate			/*
18030Sstevel@tonic-gate			 * only if we have retrans set do we do this. What
18040Sstevel@tonic-gate			 * this call does is get only the COOKIE-ACK out and
18050Sstevel@tonic-gate			 * then when we return the normal call to
18060Sstevel@tonic-gate			 * sctp_chunk_output will get the retrans out behind
18070Sstevel@tonic-gate			 * this.
18080Sstevel@tonic-gate			 */
18090Sstevel@tonic-gate			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_COOKIE_ACK, SCTP_SO_NOT_LOCKED);
18100Sstevel@tonic-gate		}
18110Sstevel@tonic-gate		if (how_indx < sizeof(asoc->cookie_how))
18120Sstevel@tonic-gate			asoc->cookie_how[how_indx] = 11;
18130Sstevel@tonic-gate
18140Sstevel@tonic-gate		return (stcb);
18150Sstevel@tonic-gate	}
18160Sstevel@tonic-gate	if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag &&
18170Sstevel@tonic-gate	    ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) &&
18180Sstevel@tonic-gate	    cookie->tie_tag_my_vtag == asoc->my_vtag_nonce &&
18190Sstevel@tonic-gate	    cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce &&
18200Sstevel@tonic-gate	    cookie->tie_tag_peer_vtag != 0) {
18210Sstevel@tonic-gate		struct sctpasochead *head;
18220Sstevel@tonic-gate
18230Sstevel@tonic-gate		if (asoc->peer_supports_nat) {
18240Sstevel@tonic-gate			/*
18250Sstevel@tonic-gate			 * This is a gross gross hack. just call the
18260Sstevel@tonic-gate			 * cookie_new code since we are allowing a duplicate
18270Sstevel@tonic-gate			 * association. I hope this works...
18280Sstevel@tonic-gate			 */
18290Sstevel@tonic-gate			return (sctp_process_cookie_new(m, iphlen, offset, sh, cookie, cookie_len,
18300Sstevel@tonic-gate			    inp, netp, init_src, notification,
18310Sstevel@tonic-gate			    auth_skipped, auth_offset, auth_len,
18320Sstevel@tonic-gate			    vrf_id, port));
18330Sstevel@tonic-gate		}
18340Sstevel@tonic-gate		/*
18350Sstevel@tonic-gate		 * case A in Section 5.2.4 Table 2: XXMM (peer restarted)
18360Sstevel@tonic-gate		 */
18370Sstevel@tonic-gate		/* temp code */
18380Sstevel@tonic-gate		if (how_indx < sizeof(asoc->cookie_how))
18390Sstevel@tonic-gate			asoc->cookie_how[how_indx] = 12;
18400Sstevel@tonic-gate		sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_15);
18410Sstevel@tonic-gate		sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
18426901Sjkennedy
18430Sstevel@tonic-gate		/* notify upper layer */
18440Sstevel@tonic-gate		*notification = SCTP_NOTIFY_ASSOC_RESTART;
18450Sstevel@tonic-gate		atomic_add_int(&stcb->asoc.refcnt, 1);
18460Sstevel@tonic-gate		if ((SCTP_GET_STATE(asoc) != SCTP_STATE_OPEN) &&
18470Sstevel@tonic-gate		    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
18480Sstevel@tonic-gate		    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) {
18490Sstevel@tonic-gate			SCTP_STAT_INCR_GAUGE32(sctps_currestab);
18500Sstevel@tonic-gate		}
18510Sstevel@tonic-gate		if (SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) {
18520Sstevel@tonic-gate			SCTP_STAT_INCR_GAUGE32(sctps_restartestab);
18530Sstevel@tonic-gate		} else if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
18540Sstevel@tonic-gate			SCTP_STAT_INCR_GAUGE32(sctps_collisionestab);
18550Sstevel@tonic-gate		}
18560Sstevel@tonic-gate		if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
18570Sstevel@tonic-gate			SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
18580Sstevel@tonic-gate			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
18590Sstevel@tonic-gate			    stcb->sctp_ep, stcb, asoc->primary_destination);
18600Sstevel@tonic-gate
18610Sstevel@tonic-gate		} else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) {
18620Sstevel@tonic-gate			/* move to OPEN state, if not in SHUTDOWN_SENT */
18630Sstevel@tonic-gate			SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
18640Sstevel@tonic-gate		}
18650Sstevel@tonic-gate		asoc->pre_open_streams =
18660Sstevel@tonic-gate		    ntohs(initack_cp->init.num_outbound_streams);
18670Sstevel@tonic-gate		asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn);
18680Sstevel@tonic-gate		asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number;
18690Sstevel@tonic-gate		asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
18700Sstevel@tonic-gate
18710Sstevel@tonic-gate		asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
18720Sstevel@tonic-gate
18730Sstevel@tonic-gate		asoc->str_reset_seq_in = asoc->init_seq_number;
18746901Sjkennedy
18750Sstevel@tonic-gate		asoc->advanced_peer_ack_point = asoc->last_acked_seq;
18766901Sjkennedy		if (asoc->mapping_array) {
18770Sstevel@tonic-gate			memset(asoc->mapping_array, 0,
18780Sstevel@tonic-gate			    asoc->mapping_array_size);
18790Sstevel@tonic-gate		}
18800Sstevel@tonic-gate		if (asoc->nr_mapping_array) {
18810Sstevel@tonic-gate			memset(asoc->nr_mapping_array, 0,
18820Sstevel@tonic-gate			    asoc->mapping_array_size);
18830Sstevel@tonic-gate		}
18840Sstevel@tonic-gate		SCTP_TCB_UNLOCK(stcb);
18850Sstevel@tonic-gate		SCTP_INP_INFO_WLOCK();
18860Sstevel@tonic-gate		SCTP_INP_WLOCK(stcb->sctp_ep);
18870Sstevel@tonic-gate		SCTP_TCB_LOCK(stcb);
18880Sstevel@tonic-gate		atomic_add_int(&stcb->asoc.refcnt, -1);
18890Sstevel@tonic-gate		/* send up all the data */
18900Sstevel@tonic-gate		SCTP_TCB_SEND_LOCK(stcb);
18910Sstevel@tonic-gate
18920Sstevel@tonic-gate		sctp_report_all_outbound(stcb, 1, SCTP_SO_NOT_LOCKED);
18930Sstevel@tonic-gate		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
18940Sstevel@tonic-gate			stcb->asoc.strmout[i].stream_no = i;
18950Sstevel@tonic-gate			stcb->asoc.strmout[i].next_sequence_sent = 0;
18960Sstevel@tonic-gate			stcb->asoc.strmout[i].last_msg_incomplete = 0;
18970Sstevel@tonic-gate		}
18980Sstevel@tonic-gate		/* process the INIT-ACK info (my info) */
18990Sstevel@tonic-gate		asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
19000Sstevel@tonic-gate		asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
19010Sstevel@tonic-gate
19020Sstevel@tonic-gate		/* pull from vtag hash */
19030Sstevel@tonic-gate		LIST_REMOVE(stcb, sctp_asocs);
19040Sstevel@tonic-gate		/* re-insert to new vtag position */
19050Sstevel@tonic-gate		head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(stcb->asoc.my_vtag,
19060Sstevel@tonic-gate		    SCTP_BASE_INFO(hashasocmark))];
19070Sstevel@tonic-gate		/*
19080Sstevel@tonic-gate		 * put it in the bucket in the vtag hash of assoc's for the
19090Sstevel@tonic-gate		 * system
19100Sstevel@tonic-gate		 */
19110Sstevel@tonic-gate		LIST_INSERT_HEAD(head, stcb, sctp_asocs);
19120Sstevel@tonic-gate
19130Sstevel@tonic-gate		/* process the INIT info (peer's info) */
19140Sstevel@tonic-gate		SCTP_TCB_SEND_UNLOCK(stcb);
19150Sstevel@tonic-gate		SCTP_INP_WUNLOCK(stcb->sctp_ep);
19160Sstevel@tonic-gate		SCTP_INP_INFO_WUNLOCK();
19170Sstevel@tonic-gate
19180Sstevel@tonic-gate		retval = sctp_process_init(init_cp, stcb);
19190Sstevel@tonic-gate		if (retval < 0) {
19200Sstevel@tonic-gate			if (how_indx < sizeof(asoc->cookie_how))
19210Sstevel@tonic-gate				asoc->cookie_how[how_indx] = 13;
19220Sstevel@tonic-gate
19230Sstevel@tonic-gate			return (NULL);
19240Sstevel@tonic-gate		}
19250Sstevel@tonic-gate		/*
19260Sstevel@tonic-gate		 * since we did not send a HB make sure we don't double
19270Sstevel@tonic-gate		 * things
19280Sstevel@tonic-gate		 */
19290Sstevel@tonic-gate		net->hb_responded = 1;
19300Sstevel@tonic-gate
19310Sstevel@tonic-gate		if (sctp_load_addresses_from_init(stcb, m,
19320Sstevel@tonic-gate		    init_offset + sizeof(struct sctp_init_chunk),
19330Sstevel@tonic-gate		    initack_offset, sh, init_src)) {
19340Sstevel@tonic-gate			if (how_indx < sizeof(asoc->cookie_how))
19354954Sachimm				asoc->cookie_how[how_indx] = 14;
19360Sstevel@tonic-gate
19370Sstevel@tonic-gate			return (NULL);
19380Sstevel@tonic-gate		}
19390Sstevel@tonic-gate		/* respond with a COOKIE-ACK */
19400Sstevel@tonic-gate		sctp_stop_all_cookie_timers(stcb);
19410Sstevel@tonic-gate		sctp_toss_old_cookies(stcb, asoc);
19420Sstevel@tonic-gate		sctp_send_cookie_ack(stcb);
19430Sstevel@tonic-gate		if (how_indx < sizeof(asoc->cookie_how))
19440Sstevel@tonic-gate			asoc->cookie_how[how_indx] = 15;
19450Sstevel@tonic-gate
19460Sstevel@tonic-gate		return (stcb);
19470Sstevel@tonic-gate	}
19480Sstevel@tonic-gate	if (how_indx < sizeof(asoc->cookie_how))
19490Sstevel@tonic-gate		asoc->cookie_how[how_indx] = 16;
19500Sstevel@tonic-gate	/* all other cases... */
19510Sstevel@tonic-gate	return (NULL);
19520Sstevel@tonic-gate}
19530Sstevel@tonic-gate
19540Sstevel@tonic-gate
19550Sstevel@tonic-gate/*
19560Sstevel@tonic-gate * handle a state cookie for a new association m: input packet mbuf chain--
19570Sstevel@tonic-gate * assumes a pullup on IP/SCTP/COOKIE-ECHO chunk note: this is a "split" mbuf
19580Sstevel@tonic-gate * and the cookie signature does not exist offset: offset into mbuf to the
19590Sstevel@tonic-gate * cookie-echo chunk length: length of the cookie chunk to: where the init
19600Sstevel@tonic-gate * was from returns a new TCB
19610Sstevel@tonic-gate */
19620Sstevel@tonic-gatestruct sctp_tcb *
19630Sstevel@tonic-gatesctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
19640Sstevel@tonic-gate    struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
19650Sstevel@tonic-gate    struct sctp_inpcb *inp, struct sctp_nets **netp,
19660Sstevel@tonic-gate    struct sockaddr *init_src, int *notification,
19670Sstevel@tonic-gate    int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
19680Sstevel@tonic-gate    uint32_t vrf_id, uint16_t port)
19690Sstevel@tonic-gate{
19700Sstevel@tonic-gate	struct sctp_tcb *stcb;
19710Sstevel@tonic-gate	struct sctp_init_chunk *init_cp, init_buf;
19720Sstevel@tonic-gate	struct sctp_init_ack_chunk *initack_cp, initack_buf;
19730Sstevel@tonic-gate	struct sockaddr_storage sa_store;
19740Sstevel@tonic-gate	struct sockaddr *initack_src = (struct sockaddr *)&sa_store;
19750Sstevel@tonic-gate	struct sctp_association *asoc;
19760Sstevel@tonic-gate	int init_offset, initack_offset, initack_limit;
19770Sstevel@tonic-gate	int retval;
19780Sstevel@tonic-gate	int error = 0;
19790Sstevel@tonic-gate	uint8_t auth_chunk_buf[SCTP_PARAM_BUFFER_SIZE];
19800Sstevel@tonic-gate
19810Sstevel@tonic-gate#ifdef INET
19820Sstevel@tonic-gate	struct sockaddr_in *sin;
19830Sstevel@tonic-gate
19840Sstevel@tonic-gate#endif
19850Sstevel@tonic-gate#ifdef INET6
19860Sstevel@tonic-gate	struct sockaddr_in6 *sin6;
19870Sstevel@tonic-gate
19880Sstevel@tonic-gate#endif
19890Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
19900Sstevel@tonic-gate	struct socket *so;
19910Sstevel@tonic-gate
19920Sstevel@tonic-gate	so = SCTP_INP_SO(inp);
19930Sstevel@tonic-gate#endif
19940Sstevel@tonic-gate
19950Sstevel@tonic-gate	/*
19960Sstevel@tonic-gate	 * find and validate the INIT chunk in the cookie (peer's info) the
19970Sstevel@tonic-gate	 * INIT should start after the cookie-echo header struct (chunk
19980Sstevel@tonic-gate	 * header, state cookie header struct)
19990Sstevel@tonic-gate	 */
20000Sstevel@tonic-gate	init_offset = offset + sizeof(struct sctp_cookie_echo_chunk);
20010Sstevel@tonic-gate	init_cp = (struct sctp_init_chunk *)
20020Sstevel@tonic-gate	    sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk),
20030Sstevel@tonic-gate	    (uint8_t *) & init_buf);
20040Sstevel@tonic-gate	if (init_cp == NULL) {
20050Sstevel@tonic-gate		/* could not pull a INIT chunk in cookie */
20060Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT1,
20070Sstevel@tonic-gate		    "process_cookie_new: could not pull INIT chunk hdr\n");
20080Sstevel@tonic-gate		return (NULL);
20090Sstevel@tonic-gate	}
20100Sstevel@tonic-gate	if (init_cp->ch.chunk_type != SCTP_INITIATION) {
20110Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT1, "HUH? process_cookie_new: could not find INIT chunk!\n");
20120Sstevel@tonic-gate		return (NULL);
20130Sstevel@tonic-gate	}
20140Sstevel@tonic-gate	initack_offset = init_offset + SCTP_SIZE32(ntohs(init_cp->ch.chunk_length));
20150Sstevel@tonic-gate	/*
20160Sstevel@tonic-gate	 * find and validate the INIT-ACK chunk in the cookie (my info) the
20170Sstevel@tonic-gate	 * INIT-ACK follows the INIT chunk
20180Sstevel@tonic-gate	 */
20190Sstevel@tonic-gate	initack_cp = (struct sctp_init_ack_chunk *)
20200Sstevel@tonic-gate	    sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk),
20210Sstevel@tonic-gate	    (uint8_t *) & initack_buf);
20220Sstevel@tonic-gate	if (initack_cp == NULL) {
20230Sstevel@tonic-gate		/* could not pull INIT-ACK chunk in cookie */
20240Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: could not pull INIT-ACK chunk hdr\n");
20250Sstevel@tonic-gate		return (NULL);
20260Sstevel@tonic-gate	}
20270Sstevel@tonic-gate	if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) {
20280Sstevel@tonic-gate		return (NULL);
20290Sstevel@tonic-gate	}
20300Sstevel@tonic-gate	/*
20310Sstevel@tonic-gate	 * NOTE: We can't use the INIT_ACK's chk_length to determine the
20320Sstevel@tonic-gate	 * "initack_limit" value.  This is because the chk_length field
20330Sstevel@tonic-gate	 * includes the length of the cookie, but the cookie is omitted when
20340Sstevel@tonic-gate	 * the INIT and INIT_ACK are tacked onto the cookie...
20350Sstevel@tonic-gate	 */
20360Sstevel@tonic-gate	initack_limit = offset + cookie_len;
20370Sstevel@tonic-gate
20380Sstevel@tonic-gate	/*
20390Sstevel@tonic-gate	 * now that we know the INIT/INIT-ACK are in place, create a new TCB
20400Sstevel@tonic-gate	 * and popluate
20410Sstevel@tonic-gate	 */
20420Sstevel@tonic-gate
20430Sstevel@tonic-gate	/*
20440Sstevel@tonic-gate	 * Here we do a trick, we set in NULL for the proc/thread argument.
20450Sstevel@tonic-gate	 * We do this since in effect we only use the p argument when the
20460Sstevel@tonic-gate	 * socket is unbound and we must do an implicit bind. Since we are
20470Sstevel@tonic-gate	 * getting a cookie, we cannot be unbound.
20480Sstevel@tonic-gate	 */
20490Sstevel@tonic-gate	stcb = sctp_aloc_assoc(inp, init_src, &error,
20500Sstevel@tonic-gate	    ntohl(initack_cp->init.initiate_tag), vrf_id,
20510Sstevel@tonic-gate	    (struct thread *)NULL
20520Sstevel@tonic-gate	    );
20530Sstevel@tonic-gate	if (stcb == NULL) {
20540Sstevel@tonic-gate		struct mbuf *op_err;
20550Sstevel@tonic-gate
20560Sstevel@tonic-gate		/* memory problem? */
20570Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT1,
20580Sstevel@tonic-gate		    "process_cookie_new: no room for another TCB!\n");
20590Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
20600Sstevel@tonic-gate
20610Sstevel@tonic-gate		sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
20620Sstevel@tonic-gate		    sh, op_err, vrf_id, port);
20630Sstevel@tonic-gate		return (NULL);
20640Sstevel@tonic-gate	}
20650Sstevel@tonic-gate	/* get the correct sctp_nets */
20660Sstevel@tonic-gate	if (netp)
20670Sstevel@tonic-gate		*netp = sctp_findnet(stcb, init_src);
20680Sstevel@tonic-gate
20690Sstevel@tonic-gate	asoc = &stcb->asoc;
20700Sstevel@tonic-gate	/* get scope variables out of cookie */
20710Sstevel@tonic-gate	asoc->ipv4_local_scope = cookie->ipv4_scope;
20720Sstevel@tonic-gate	asoc->site_scope = cookie->site_scope;
20730Sstevel@tonic-gate	asoc->local_scope = cookie->local_scope;
20740Sstevel@tonic-gate	asoc->loopback_scope = cookie->loopback_scope;
20750Sstevel@tonic-gate
20760Sstevel@tonic-gate	if ((asoc->ipv4_addr_legal != cookie->ipv4_addr_legal) ||
20770Sstevel@tonic-gate	    (asoc->ipv6_addr_legal != cookie->ipv6_addr_legal)) {
20780Sstevel@tonic-gate		struct mbuf *op_err;
20790Sstevel@tonic-gate
20800Sstevel@tonic-gate		/*
20810Sstevel@tonic-gate		 * Houston we have a problem. The EP changed while the
20820Sstevel@tonic-gate		 * cookie was in flight. Only recourse is to abort the
20830Sstevel@tonic-gate		 * association.
20840Sstevel@tonic-gate		 */
20850Sstevel@tonic-gate		atomic_add_int(&stcb->asoc.refcnt, 1);
20860Sstevel@tonic-gate		op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
20870Sstevel@tonic-gate		sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
20880Sstevel@tonic-gate		    sh, op_err, vrf_id, port);
20890Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
20900Sstevel@tonic-gate		SCTP_TCB_UNLOCK(stcb);
20910Sstevel@tonic-gate		SCTP_SOCKET_LOCK(so, 1);
20924954Sachimm		SCTP_TCB_LOCK(stcb);
20934954Sachimm#endif
20940Sstevel@tonic-gate		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
20950Sstevel@tonic-gate		    SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
20960Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
20970Sstevel@tonic-gate		SCTP_SOCKET_UNLOCK(so, 1);
20980Sstevel@tonic-gate#endif
20990Sstevel@tonic-gate		atomic_subtract_int(&stcb->asoc.refcnt, 1);
21000Sstevel@tonic-gate		return (NULL);
21010Sstevel@tonic-gate	}
21020Sstevel@tonic-gate	/* process the INIT-ACK info (my info) */
21030Sstevel@tonic-gate	asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
21040Sstevel@tonic-gate	asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
21050Sstevel@tonic-gate	asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams);
21060Sstevel@tonic-gate	asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn);
21070Sstevel@tonic-gate	asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number;
21080Sstevel@tonic-gate	asoc->asconf_seq_out_acked = asoc->asconf_seq_out - 1;
21090Sstevel@tonic-gate	asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
21100Sstevel@tonic-gate	asoc->str_reset_seq_in = asoc->init_seq_number;
21110Sstevel@tonic-gate
21120Sstevel@tonic-gate	asoc->advanced_peer_ack_point = asoc->last_acked_seq;
21130Sstevel@tonic-gate
21140Sstevel@tonic-gate	/* process the INIT info (peer's info) */
21150Sstevel@tonic-gate	if (netp)
21160Sstevel@tonic-gate		retval = sctp_process_init(init_cp, stcb);
21170Sstevel@tonic-gate	else
21180Sstevel@tonic-gate		retval = 0;
21190Sstevel@tonic-gate	if (retval < 0) {
21200Sstevel@tonic-gate		atomic_add_int(&stcb->asoc.refcnt, 1);
21210Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
21220Sstevel@tonic-gate		SCTP_TCB_UNLOCK(stcb);
21230Sstevel@tonic-gate		SCTP_SOCKET_LOCK(so, 1);
21240Sstevel@tonic-gate		SCTP_TCB_LOCK(stcb);
21250Sstevel@tonic-gate#endif
21260Sstevel@tonic-gate		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_16);
21270Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
21280Sstevel@tonic-gate		SCTP_SOCKET_UNLOCK(so, 1);
21290Sstevel@tonic-gate#endif
21300Sstevel@tonic-gate		atomic_subtract_int(&stcb->asoc.refcnt, 1);
21310Sstevel@tonic-gate		return (NULL);
21320Sstevel@tonic-gate	}
21330Sstevel@tonic-gate	/* load all addresses */
21340Sstevel@tonic-gate	if (sctp_load_addresses_from_init(stcb, m,
21350Sstevel@tonic-gate	    init_offset + sizeof(struct sctp_init_chunk), initack_offset, sh,
21360Sstevel@tonic-gate	    init_src)) {
21370Sstevel@tonic-gate		atomic_add_int(&stcb->asoc.refcnt, 1);
21380Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
21390Sstevel@tonic-gate		SCTP_TCB_UNLOCK(stcb);
21400Sstevel@tonic-gate		SCTP_SOCKET_LOCK(so, 1);
21410Sstevel@tonic-gate		SCTP_TCB_LOCK(stcb);
21420Sstevel@tonic-gate#endif
21430Sstevel@tonic-gate		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_17);
21440Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
21450Sstevel@tonic-gate		SCTP_SOCKET_UNLOCK(so, 1);
21460Sstevel@tonic-gate#endif
21470Sstevel@tonic-gate		atomic_subtract_int(&stcb->asoc.refcnt, 1);
21480Sstevel@tonic-gate		return (NULL);
21490Sstevel@tonic-gate	}
21500Sstevel@tonic-gate	/*
21510Sstevel@tonic-gate	 * verify any preceding AUTH chunk that was skipped
21520Sstevel@tonic-gate	 */
21530Sstevel@tonic-gate	/* pull the local authentication parameters from the cookie/init-ack */
21540Sstevel@tonic-gate	sctp_auth_get_cookie_params(stcb, m,
21550Sstevel@tonic-gate	    initack_offset + sizeof(struct sctp_init_ack_chunk),
21560Sstevel@tonic-gate	    initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)));
21570Sstevel@tonic-gate	if (auth_skipped) {
21580Sstevel@tonic-gate		struct sctp_auth_chunk *auth;
21590Sstevel@tonic-gate
21600Sstevel@tonic-gate		auth = (struct sctp_auth_chunk *)
21610Sstevel@tonic-gate		    sctp_m_getptr(m, auth_offset, auth_len, auth_chunk_buf);
21620Sstevel@tonic-gate		if ((auth == NULL) || sctp_handle_auth(stcb, auth, m, auth_offset)) {
21630Sstevel@tonic-gate			/* auth HMAC failed, dump the assoc and packet */
21640Sstevel@tonic-gate			SCTPDBG(SCTP_DEBUG_AUTH1,
21650Sstevel@tonic-gate			    "COOKIE-ECHO: AUTH failed\n");
21660Sstevel@tonic-gate			atomic_add_int(&stcb->asoc.refcnt, 1);
21670Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
21680Sstevel@tonic-gate			SCTP_TCB_UNLOCK(stcb);
21690Sstevel@tonic-gate			SCTP_SOCKET_LOCK(so, 1);
21700Sstevel@tonic-gate			SCTP_TCB_LOCK(stcb);
21710Sstevel@tonic-gate#endif
21720Sstevel@tonic-gate			(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_18);
21730Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
21740Sstevel@tonic-gate			SCTP_SOCKET_UNLOCK(so, 1);
21750Sstevel@tonic-gate#endif
21760Sstevel@tonic-gate			atomic_subtract_int(&stcb->asoc.refcnt, 1);
21770Sstevel@tonic-gate			return (NULL);
21780Sstevel@tonic-gate		} else {
21790Sstevel@tonic-gate			/* remaining chunks checked... good to go */
21800Sstevel@tonic-gate			stcb->asoc.authenticated = 1;
21810Sstevel@tonic-gate		}
21820Sstevel@tonic-gate	}
21830Sstevel@tonic-gate	/* update current state */
21840Sstevel@tonic-gate	SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
21850Sstevel@tonic-gate	SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
21860Sstevel@tonic-gate	if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
21870Sstevel@tonic-gate		sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
21880Sstevel@tonic-gate		    stcb->sctp_ep, stcb, asoc->primary_destination);
21890Sstevel@tonic-gate	}
21900Sstevel@tonic-gate	sctp_stop_all_cookie_timers(stcb);
21910Sstevel@tonic-gate	SCTP_STAT_INCR_COUNTER32(sctps_passiveestab);
21920Sstevel@tonic-gate	SCTP_STAT_INCR_GAUGE32(sctps_currestab);
21930Sstevel@tonic-gate
21940Sstevel@tonic-gate	/*
21950Sstevel@tonic-gate	 * if we're doing ASCONFs, check to see if we have any new local
21960Sstevel@tonic-gate	 * addresses that need to get added to the peer (eg. addresses
21970Sstevel@tonic-gate	 * changed while cookie echo in flight).  This needs to be done
21980Sstevel@tonic-gate	 * after we go to the OPEN state to do the correct asconf
21990Sstevel@tonic-gate	 * processing. else, make sure we have the correct addresses in our
22000Sstevel@tonic-gate	 * lists
22010Sstevel@tonic-gate	 */
22020Sstevel@tonic-gate
22030Sstevel@tonic-gate	/* warning, we re-use sin, sin6, sa_store here! */
22040Sstevel@tonic-gate	/* pull in local_address (our "from" address) */
22050Sstevel@tonic-gate	switch (cookie->laddr_type) {
22060Sstevel@tonic-gate#ifdef INET
22070Sstevel@tonic-gate	case SCTP_IPV4_ADDRESS:
22080Sstevel@tonic-gate		/* source addr is IPv4 */
22090Sstevel@tonic-gate		sin = (struct sockaddr_in *)initack_src;
22100Sstevel@tonic-gate		memset(sin, 0, sizeof(*sin));
22110Sstevel@tonic-gate		sin->sin_family = AF_INET;
22120Sstevel@tonic-gate		sin->sin_len = sizeof(struct sockaddr_in);
22130Sstevel@tonic-gate		sin->sin_addr.s_addr = cookie->laddress[0];
22140Sstevel@tonic-gate		break;
22150Sstevel@tonic-gate#endif
22160Sstevel@tonic-gate#ifdef INET6
22170Sstevel@tonic-gate	case SCTP_IPV6_ADDRESS:
22180Sstevel@tonic-gate		/* source addr is IPv6 */
22190Sstevel@tonic-gate		sin6 = (struct sockaddr_in6 *)initack_src;
22200Sstevel@tonic-gate		memset(sin6, 0, sizeof(*sin6));
22210Sstevel@tonic-gate		sin6->sin6_family = AF_INET6;
22220Sstevel@tonic-gate		sin6->sin6_len = sizeof(struct sockaddr_in6);
22230Sstevel@tonic-gate		sin6->sin6_scope_id = cookie->scope_id;
22240Sstevel@tonic-gate		memcpy(&sin6->sin6_addr, cookie->laddress,
22250Sstevel@tonic-gate		    sizeof(sin6->sin6_addr));
22260Sstevel@tonic-gate		break;
22270Sstevel@tonic-gate#endif
22280Sstevel@tonic-gate	default:
22290Sstevel@tonic-gate		atomic_add_int(&stcb->asoc.refcnt, 1);
22300Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
22310Sstevel@tonic-gate		SCTP_TCB_UNLOCK(stcb);
22320Sstevel@tonic-gate		SCTP_SOCKET_LOCK(so, 1);
22330Sstevel@tonic-gate		SCTP_TCB_LOCK(stcb);
22340Sstevel@tonic-gate#endif
22350Sstevel@tonic-gate		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_19);
22360Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
22370Sstevel@tonic-gate		SCTP_SOCKET_UNLOCK(so, 1);
22380Sstevel@tonic-gate#endif
22390Sstevel@tonic-gate		atomic_subtract_int(&stcb->asoc.refcnt, 1);
22400Sstevel@tonic-gate		return (NULL);
22410Sstevel@tonic-gate	}
22420Sstevel@tonic-gate
22430Sstevel@tonic-gate	/* set up to notify upper layer */
22440Sstevel@tonic-gate	*notification = SCTP_NOTIFY_ASSOC_UP;
22450Sstevel@tonic-gate	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
22460Sstevel@tonic-gate	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
22470Sstevel@tonic-gate	    (inp->sctp_socket->so_qlimit == 0)) {
22480Sstevel@tonic-gate		/*
22490Sstevel@tonic-gate		 * This is an endpoint that called connect() how it got a
22500Sstevel@tonic-gate		 * cookie that is NEW is a bit of a mystery. It must be that
22510Sstevel@tonic-gate		 * the INIT was sent, but before it got there.. a complete
22520Sstevel@tonic-gate		 * INIT/INIT-ACK/COOKIE arrived. But of course then it
22530Sstevel@tonic-gate		 * should have went to the other code.. not here.. oh well..
22540Sstevel@tonic-gate		 * a bit of protection is worth having..
22550Sstevel@tonic-gate		 */
22560Sstevel@tonic-gate		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
22570Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
22580Sstevel@tonic-gate		atomic_add_int(&stcb->asoc.refcnt, 1);
22590Sstevel@tonic-gate		SCTP_TCB_UNLOCK(stcb);
22600Sstevel@tonic-gate		SCTP_SOCKET_LOCK(so, 1);
22610Sstevel@tonic-gate		SCTP_TCB_LOCK(stcb);
22620Sstevel@tonic-gate		atomic_subtract_int(&stcb->asoc.refcnt, 1);
22630Sstevel@tonic-gate		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
22640Sstevel@tonic-gate			SCTP_SOCKET_UNLOCK(so, 1);
22650Sstevel@tonic-gate			return (NULL);
22660Sstevel@tonic-gate		}
22670Sstevel@tonic-gate#endif
22680Sstevel@tonic-gate		soisconnected(stcb->sctp_socket);
22690Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
22700Sstevel@tonic-gate		SCTP_SOCKET_UNLOCK(so, 1);
22710Sstevel@tonic-gate#endif
22720Sstevel@tonic-gate	} else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
22730Sstevel@tonic-gate	    (inp->sctp_socket->so_qlimit)) {
22740Sstevel@tonic-gate		/*
22750Sstevel@tonic-gate		 * We don't want to do anything with this one. Since it is
22760Sstevel@tonic-gate		 * the listening guy. The timer will get started for
22770Sstevel@tonic-gate		 * accepted connections in the caller.
22780Sstevel@tonic-gate		 */
22790Sstevel@tonic-gate		;
22800Sstevel@tonic-gate	}
22810Sstevel@tonic-gate	/* since we did not send a HB make sure we don't double things */
22820Sstevel@tonic-gate	if ((netp) && (*netp))
22830Sstevel@tonic-gate		(*netp)->hb_responded = 1;
22840Sstevel@tonic-gate
22850Sstevel@tonic-gate	if (stcb->asoc.sctp_autoclose_ticks &&
22860Sstevel@tonic-gate	    sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE)) {
22870Sstevel@tonic-gate		sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL);
22880Sstevel@tonic-gate	}
22890Sstevel@tonic-gate	/* calculate the RTT */
22900Sstevel@tonic-gate	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
22910Sstevel@tonic-gate	if ((netp) && (*netp)) {
22920Sstevel@tonic-gate		(*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp,
22930Sstevel@tonic-gate		    &cookie->time_entered, sctp_align_unsafe_makecopy,
22940Sstevel@tonic-gate		    SCTP_RTT_FROM_NON_DATA);
22950Sstevel@tonic-gate	}
22960Sstevel@tonic-gate	/* respond with a COOKIE-ACK */
22970Sstevel@tonic-gate	sctp_send_cookie_ack(stcb);
22980Sstevel@tonic-gate
22990Sstevel@tonic-gate	/*
23000Sstevel@tonic-gate	 * check the address lists for any ASCONFs that need to be sent
23010Sstevel@tonic-gate	 * AFTER the cookie-ack is sent
23020Sstevel@tonic-gate	 */
23030Sstevel@tonic-gate	sctp_check_address_list(stcb, m,
23040Sstevel@tonic-gate	    initack_offset + sizeof(struct sctp_init_ack_chunk),
23050Sstevel@tonic-gate	    initack_limit - (initack_offset + sizeof(struct sctp_init_ack_chunk)),
23060Sstevel@tonic-gate	    initack_src, cookie->local_scope, cookie->site_scope,
23070Sstevel@tonic-gate	    cookie->ipv4_scope, cookie->loopback_scope);
23080Sstevel@tonic-gate
23090Sstevel@tonic-gate
23100Sstevel@tonic-gate	return (stcb);
23110Sstevel@tonic-gate}
23120Sstevel@tonic-gate
23130Sstevel@tonic-gate/*
23140Sstevel@tonic-gate * CODE LIKE THIS NEEDS TO RUN IF the peer supports the NAT extension, i.e
23150Sstevel@tonic-gate * we NEED to make sure we are not already using the vtag. If so we
23160Sstevel@tonic-gate * need to send back an ABORT-TRY-AGAIN-WITH-NEW-TAG No middle box bit!
23170Sstevel@tonic-gate	head = &SCTP_BASE_INFO(sctp_asochash)[SCTP_PCBHASH_ASOC(tag,
23180Sstevel@tonic-gate							    SCTP_BASE_INFO(hashasocmark))];
23190Sstevel@tonic-gate	LIST_FOREACH(stcb, head, sctp_asocs) {
23200Sstevel@tonic-gate	        if ((stcb->asoc.my_vtag == tag) && (stcb->rport == rport) && (inp == stcb->sctp_ep))  {
23210Sstevel@tonic-gate		       -- SEND ABORT - TRY AGAIN --
23220Sstevel@tonic-gate		}
23230Sstevel@tonic-gate	}
23240Sstevel@tonic-gate*/
23250Sstevel@tonic-gate
23260Sstevel@tonic-gate/*
23270Sstevel@tonic-gate * handles a COOKIE-ECHO message stcb: modified to either a new or left as
23280Sstevel@tonic-gate * existing (non-NULL) TCB
23290Sstevel@tonic-gate */
23300Sstevel@tonic-gatestatic struct mbuf *
23310Sstevel@tonic-gatesctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
23320Sstevel@tonic-gate    struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp,
23330Sstevel@tonic-gate    struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp,
23340Sstevel@tonic-gate    int auth_skipped, uint32_t auth_offset, uint32_t auth_len,
23350Sstevel@tonic-gate    struct sctp_tcb **locked_tcb, uint32_t vrf_id, uint16_t port)
23360Sstevel@tonic-gate{
23370Sstevel@tonic-gate	struct sctp_state_cookie *cookie;
23380Sstevel@tonic-gate	struct sctp_tcb *l_stcb = *stcb;
23390Sstevel@tonic-gate	struct sctp_inpcb *l_inp;
23400Sstevel@tonic-gate	struct sockaddr *to;
23410Sstevel@tonic-gate	struct sctp_pcb *ep;
23420Sstevel@tonic-gate	struct mbuf *m_sig;
23430Sstevel@tonic-gate	uint8_t calc_sig[SCTP_SIGNATURE_SIZE], tmp_sig[SCTP_SIGNATURE_SIZE];
23440Sstevel@tonic-gate	uint8_t *sig;
23450Sstevel@tonic-gate	uint8_t cookie_ok = 0;
23460Sstevel@tonic-gate	unsigned int size_of_pkt, sig_offset, cookie_offset;
23470Sstevel@tonic-gate	unsigned int cookie_len;
23480Sstevel@tonic-gate	struct timeval now;
23490Sstevel@tonic-gate	struct timeval time_expires;
23500Sstevel@tonic-gate	struct sockaddr_storage dest_store;
23510Sstevel@tonic-gate	struct sockaddr *localep_sa = (struct sockaddr *)&dest_store;
23520Sstevel@tonic-gate	struct ip *iph;
23530Sstevel@tonic-gate	int notification = 0;
23540Sstevel@tonic-gate	struct sctp_nets *netl;
23550Sstevel@tonic-gate	int had_a_existing_tcb = 0;
23560Sstevel@tonic-gate	int send_int_conf = 0;
23570Sstevel@tonic-gate
23580Sstevel@tonic-gate#ifdef INET
23590Sstevel@tonic-gate	struct sockaddr_in sin;
23600Sstevel@tonic-gate
23610Sstevel@tonic-gate#endif
23620Sstevel@tonic-gate#ifdef INET6
23630Sstevel@tonic-gate	struct sockaddr_in6 sin6;
23640Sstevel@tonic-gate
23650Sstevel@tonic-gate#endif
23660Sstevel@tonic-gate
23670Sstevel@tonic-gate	SCTPDBG(SCTP_DEBUG_INPUT2,
23688452SJohn.Wren.Kennedy@Sun.COM	    "sctp_handle_cookie: handling COOKIE-ECHO\n");
23694954Sachimm
23700Sstevel@tonic-gate	if (inp_p == NULL) {
23710Sstevel@tonic-gate		return (NULL);
23720Sstevel@tonic-gate	}
23730Sstevel@tonic-gate	/* First get the destination address setup too. */
23740Sstevel@tonic-gate	iph = mtod(m, struct ip *);
23750Sstevel@tonic-gate	switch (iph->ip_v) {
23760Sstevel@tonic-gate#ifdef INET
23770Sstevel@tonic-gate	case IPVERSION:
23780Sstevel@tonic-gate		{
23790Sstevel@tonic-gate			/* its IPv4 */
23800Sstevel@tonic-gate			struct sockaddr_in *lsin;
23810Sstevel@tonic-gate
23820Sstevel@tonic-gate			lsin = (struct sockaddr_in *)(localep_sa);
23830Sstevel@tonic-gate			memset(lsin, 0, sizeof(*lsin));
23840Sstevel@tonic-gate			lsin->sin_family = AF_INET;
23850Sstevel@tonic-gate			lsin->sin_len = sizeof(*lsin);
23860Sstevel@tonic-gate			lsin->sin_port = sh->dest_port;
23870Sstevel@tonic-gate			lsin->sin_addr.s_addr = iph->ip_dst.s_addr;
23880Sstevel@tonic-gate			size_of_pkt = SCTP_GET_IPV4_LENGTH(iph);
23890Sstevel@tonic-gate			break;
23900Sstevel@tonic-gate		}
23910Sstevel@tonic-gate#endif
23920Sstevel@tonic-gate#ifdef INET6
23930Sstevel@tonic-gate	case IPV6_VERSION >> 4:
23940Sstevel@tonic-gate		{
23950Sstevel@tonic-gate			/* its IPv6 */
23960Sstevel@tonic-gate			struct ip6_hdr *ip6;
23970Sstevel@tonic-gate			struct sockaddr_in6 *lsin6;
23980Sstevel@tonic-gate
23990Sstevel@tonic-gate			lsin6 = (struct sockaddr_in6 *)(localep_sa);
24000Sstevel@tonic-gate			memset(lsin6, 0, sizeof(*lsin6));
24010Sstevel@tonic-gate			lsin6->sin6_family = AF_INET6;
24020Sstevel@tonic-gate			lsin6->sin6_len = sizeof(struct sockaddr_in6);
24030Sstevel@tonic-gate			ip6 = mtod(m, struct ip6_hdr *);
24040Sstevel@tonic-gate			lsin6->sin6_port = sh->dest_port;
24050Sstevel@tonic-gate			lsin6->sin6_addr = ip6->ip6_dst;
24060Sstevel@tonic-gate			size_of_pkt = SCTP_GET_IPV6_LENGTH(ip6) + iphlen;
24070Sstevel@tonic-gate			break;
24080Sstevel@tonic-gate		}
24090Sstevel@tonic-gate#endif
24100Sstevel@tonic-gate	default:
24110Sstevel@tonic-gate		return (NULL);
24120Sstevel@tonic-gate	}
24130Sstevel@tonic-gate
24140Sstevel@tonic-gate	cookie = &cp->cookie;
24150Sstevel@tonic-gate	cookie_offset = offset + sizeof(struct sctp_chunkhdr);
24160Sstevel@tonic-gate	cookie_len = ntohs(cp->ch.chunk_length);
24170Sstevel@tonic-gate
24180Sstevel@tonic-gate	if ((cookie->peerport != sh->src_port) &&
24190Sstevel@tonic-gate	    (cookie->myport != sh->dest_port) &&
24200Sstevel@tonic-gate	    (cookie->my_vtag != sh->v_tag)) {
24210Sstevel@tonic-gate		/*
24220Sstevel@tonic-gate		 * invalid ports or bad tag.  Note that we always leave the
24230Sstevel@tonic-gate		 * v_tag in the header in network order and when we stored
24240Sstevel@tonic-gate		 * it in the my_vtag slot we also left it in network order.
24250Sstevel@tonic-gate		 * This maintains the match even though it may be in the
24260Sstevel@tonic-gate		 * opposite byte order of the machine :->
24270Sstevel@tonic-gate		 */
24280Sstevel@tonic-gate		return (NULL);
24290Sstevel@tonic-gate	}
24300Sstevel@tonic-gate	if (cookie_len > size_of_pkt ||
24310Sstevel@tonic-gate	    cookie_len < sizeof(struct sctp_cookie_echo_chunk) +
24320Sstevel@tonic-gate	    sizeof(struct sctp_init_chunk) +
24330Sstevel@tonic-gate	    sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) {
24340Sstevel@tonic-gate		/* cookie too long!  or too small */
24350Sstevel@tonic-gate		return (NULL);
24360Sstevel@tonic-gate	}
24370Sstevel@tonic-gate	/*
24380Sstevel@tonic-gate	 * split off the signature into its own mbuf (since it should not be
24390Sstevel@tonic-gate	 * calculated in the sctp_hmac_m() call).
24400Sstevel@tonic-gate	 */
24410Sstevel@tonic-gate	sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE;
24420Sstevel@tonic-gate	if (sig_offset > size_of_pkt) {
24430Sstevel@tonic-gate		/* packet not correct size! */
24440Sstevel@tonic-gate		/* XXX this may already be accounted for earlier... */
24450Sstevel@tonic-gate		return (NULL);
24460Sstevel@tonic-gate	}
24470Sstevel@tonic-gate	m_sig = m_split(m, sig_offset, M_DONTWAIT);
24480Sstevel@tonic-gate	if (m_sig == NULL) {
24490Sstevel@tonic-gate		/* out of memory or ?? */
24500Sstevel@tonic-gate		return (NULL);
24510Sstevel@tonic-gate	}
24520Sstevel@tonic-gate#ifdef SCTP_MBUF_LOGGING
24530Sstevel@tonic-gate	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
24540Sstevel@tonic-gate		struct mbuf *mat;
24550Sstevel@tonic-gate
24560Sstevel@tonic-gate		for (mat = m_sig; mat; mat = SCTP_BUF_NEXT(mat)) {
24570Sstevel@tonic-gate			if (SCTP_BUF_IS_EXTENDED(mat)) {
24580Sstevel@tonic-gate				sctp_log_mb(mat, SCTP_MBUF_SPLIT);
24590Sstevel@tonic-gate			}
24600Sstevel@tonic-gate		}
24610Sstevel@tonic-gate	}
24620Sstevel@tonic-gate#endif
24630Sstevel@tonic-gate
24640Sstevel@tonic-gate	/*
24650Sstevel@tonic-gate	 * compute the signature/digest for the cookie
24660Sstevel@tonic-gate	 */
24670Sstevel@tonic-gate	ep = &(*inp_p)->sctp_ep;
24680Sstevel@tonic-gate	l_inp = *inp_p;
24690Sstevel@tonic-gate	if (l_stcb) {
24700Sstevel@tonic-gate		SCTP_TCB_UNLOCK(l_stcb);
24710Sstevel@tonic-gate	}
24720Sstevel@tonic-gate	SCTP_INP_RLOCK(l_inp);
24730Sstevel@tonic-gate	if (l_stcb) {
24740Sstevel@tonic-gate		SCTP_TCB_LOCK(l_stcb);
24750Sstevel@tonic-gate	}
24760Sstevel@tonic-gate	/* which cookie is it? */
24770Sstevel@tonic-gate	if ((cookie->time_entered.tv_sec < (long)ep->time_of_secret_change) &&
24780Sstevel@tonic-gate	    (ep->current_secret_number != ep->last_secret_number)) {
24790Sstevel@tonic-gate		/* it's the old cookie */
24800Sstevel@tonic-gate		(void)sctp_hmac_m(SCTP_HMAC,
24810Sstevel@tonic-gate		    (uint8_t *) ep->secret_key[(int)ep->last_secret_number],
24820Sstevel@tonic-gate		    SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0);
24830Sstevel@tonic-gate	} else {
24840Sstevel@tonic-gate		/* it's the current cookie */
24850Sstevel@tonic-gate		(void)sctp_hmac_m(SCTP_HMAC,
24860Sstevel@tonic-gate		    (uint8_t *) ep->secret_key[(int)ep->current_secret_number],
24870Sstevel@tonic-gate		    SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0);
24880Sstevel@tonic-gate	}
24890Sstevel@tonic-gate	/* get the signature */
24900Sstevel@tonic-gate	SCTP_INP_RUNLOCK(l_inp);
24910Sstevel@tonic-gate	sig = (uint8_t *) sctp_m_getptr(m_sig, 0, SCTP_SIGNATURE_SIZE, (uint8_t *) & tmp_sig);
24920Sstevel@tonic-gate	if (sig == NULL) {
24930Sstevel@tonic-gate		/* couldn't find signature */
24940Sstevel@tonic-gate		sctp_m_freem(m_sig);
24950Sstevel@tonic-gate		return (NULL);
24960Sstevel@tonic-gate	}
24970Sstevel@tonic-gate	/* compare the received digest with the computed digest */
24980Sstevel@tonic-gate	if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) != 0) {
24990Sstevel@tonic-gate		/* try the old cookie? */
25000Sstevel@tonic-gate		if ((cookie->time_entered.tv_sec == (long)ep->time_of_secret_change) &&
25010Sstevel@tonic-gate		    (ep->current_secret_number != ep->last_secret_number)) {
25020Sstevel@tonic-gate			/* compute digest with old */
25030Sstevel@tonic-gate			(void)sctp_hmac_m(SCTP_HMAC,
25040Sstevel@tonic-gate			    (uint8_t *) ep->secret_key[(int)ep->last_secret_number],
25050Sstevel@tonic-gate			    SCTP_SECRET_SIZE, m, cookie_offset, calc_sig, 0);
25060Sstevel@tonic-gate			/* compare */
25070Sstevel@tonic-gate			if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) == 0)
25080Sstevel@tonic-gate				cookie_ok = 1;
25090Sstevel@tonic-gate		}
25100Sstevel@tonic-gate	} else {
25110Sstevel@tonic-gate		cookie_ok = 1;
25120Sstevel@tonic-gate	}
25130Sstevel@tonic-gate
25140Sstevel@tonic-gate	/*
25150Sstevel@tonic-gate	 * Now before we continue we must reconstruct our mbuf so that
25160Sstevel@tonic-gate	 * normal processing of any other chunks will work.
25170Sstevel@tonic-gate	 */
25180Sstevel@tonic-gate	{
25190Sstevel@tonic-gate		struct mbuf *m_at;
25200Sstevel@tonic-gate
25210Sstevel@tonic-gate		m_at = m;
25220Sstevel@tonic-gate		while (SCTP_BUF_NEXT(m_at) != NULL) {
25230Sstevel@tonic-gate			m_at = SCTP_BUF_NEXT(m_at);
25240Sstevel@tonic-gate		}
25250Sstevel@tonic-gate		SCTP_BUF_NEXT(m_at) = m_sig;
25260Sstevel@tonic-gate	}
25270Sstevel@tonic-gate
25280Sstevel@tonic-gate	if (cookie_ok == 0) {
25290Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT2, "handle_cookie_echo: cookie signature validation failed!\n");
25300Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT2,
25310Sstevel@tonic-gate		    "offset = %u, cookie_offset = %u, sig_offset = %u\n",
25320Sstevel@tonic-gate		    (uint32_t) offset, cookie_offset, sig_offset);
25330Sstevel@tonic-gate		return (NULL);
25340Sstevel@tonic-gate	}
25350Sstevel@tonic-gate	/*
25360Sstevel@tonic-gate	 * check the cookie timestamps to be sure it's not stale
25370Sstevel@tonic-gate	 */
25380Sstevel@tonic-gate	(void)SCTP_GETTIME_TIMEVAL(&now);
25390Sstevel@tonic-gate	/* Expire time is in Ticks, so we convert to seconds */
25400Sstevel@tonic-gate	time_expires.tv_sec = cookie->time_entered.tv_sec + TICKS_TO_SEC(cookie->cookie_life);
25410Sstevel@tonic-gate	time_expires.tv_usec = cookie->time_entered.tv_usec;
25420Sstevel@tonic-gate	/*
25430Sstevel@tonic-gate	 * TODO sctp_constants.h needs alternative time macros when _KERNEL
25440Sstevel@tonic-gate	 * is undefined.
25450Sstevel@tonic-gate	 */
25460Sstevel@tonic-gate	if (timevalcmp(&now, &time_expires, >)) {
25470Sstevel@tonic-gate		/* cookie is stale! */
25480Sstevel@tonic-gate		struct mbuf *op_err;
25490Sstevel@tonic-gate		struct sctp_stale_cookie_msg *scm;
25500Sstevel@tonic-gate		uint32_t tim;
25510Sstevel@tonic-gate
25520Sstevel@tonic-gate		op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg),
25530Sstevel@tonic-gate		    0, M_DONTWAIT, 1, MT_DATA);
25540Sstevel@tonic-gate		if (op_err == NULL) {
25550Sstevel@tonic-gate			/* FOOBAR */
25560Sstevel@tonic-gate			return (NULL);
25570Sstevel@tonic-gate		}
25580Sstevel@tonic-gate		/* Set the len */
25590Sstevel@tonic-gate		SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg);
25600Sstevel@tonic-gate		scm = mtod(op_err, struct sctp_stale_cookie_msg *);
25610Sstevel@tonic-gate		scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE);
25620Sstevel@tonic-gate		scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) +
25630Sstevel@tonic-gate		    (sizeof(uint32_t))));
25640Sstevel@tonic-gate		/* seconds to usec */
25650Sstevel@tonic-gate		tim = (now.tv_sec - time_expires.tv_sec) * 1000000;
25660Sstevel@tonic-gate		/* add in usec */
25670Sstevel@tonic-gate		if (tim == 0)
25680Sstevel@tonic-gate			tim = now.tv_usec - cookie->time_entered.tv_usec;
25690Sstevel@tonic-gate		scm->time_usec = htonl(tim);
25700Sstevel@tonic-gate		sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag,
25710Sstevel@tonic-gate		    vrf_id, port);
25720Sstevel@tonic-gate		return (NULL);
25730Sstevel@tonic-gate	}
25740Sstevel@tonic-gate	/*
25750Sstevel@tonic-gate	 * Now we must see with the lookup address if we have an existing
25760Sstevel@tonic-gate	 * asoc. This will only happen if we were in the COOKIE-WAIT state
25770Sstevel@tonic-gate	 * and a INIT collided with us and somewhere the peer sent the
25780Sstevel@tonic-gate	 * cookie on another address besides the single address our assoc
25790Sstevel@tonic-gate	 * had for him. In this case we will have one of the tie-tags set at
25800Sstevel@tonic-gate	 * least AND the address field in the cookie can be used to look it
25810Sstevel@tonic-gate	 * up.
25820Sstevel@tonic-gate	 */
25830Sstevel@tonic-gate	to = NULL;
25840Sstevel@tonic-gate	switch (cookie->addr_type) {
25850Sstevel@tonic-gate#ifdef INET6
25860Sstevel@tonic-gate	case SCTP_IPV6_ADDRESS:
25870Sstevel@tonic-gate		memset(&sin6, 0, sizeof(sin6));
25880Sstevel@tonic-gate		sin6.sin6_family = AF_INET6;
25890Sstevel@tonic-gate		sin6.sin6_len = sizeof(sin6);
25900Sstevel@tonic-gate		sin6.sin6_port = sh->src_port;
25910Sstevel@tonic-gate		sin6.sin6_scope_id = cookie->scope_id;
25920Sstevel@tonic-gate		memcpy(&sin6.sin6_addr.s6_addr, cookie->address,
25930Sstevel@tonic-gate		    sizeof(sin6.sin6_addr.s6_addr));
25940Sstevel@tonic-gate		to = (struct sockaddr *)&sin6;
25950Sstevel@tonic-gate		break;
25960Sstevel@tonic-gate#endif
25970Sstevel@tonic-gate#ifdef INET
25980Sstevel@tonic-gate	case SCTP_IPV4_ADDRESS:
25990Sstevel@tonic-gate		memset(&sin, 0, sizeof(sin));
26000Sstevel@tonic-gate		sin.sin_family = AF_INET;
26010Sstevel@tonic-gate		sin.sin_len = sizeof(sin);
26020Sstevel@tonic-gate		sin.sin_port = sh->src_port;
26030Sstevel@tonic-gate		sin.sin_addr.s_addr = cookie->address[0];
26040Sstevel@tonic-gate		to = (struct sockaddr *)&sin;
26050Sstevel@tonic-gate		break;
26060Sstevel@tonic-gate#endif
26070Sstevel@tonic-gate	default:
26080Sstevel@tonic-gate		/* This should not happen */
26090Sstevel@tonic-gate		return (NULL);
26100Sstevel@tonic-gate	}
26110Sstevel@tonic-gate	if ((*stcb == NULL) && to) {
26120Sstevel@tonic-gate		/* Yep, lets check */
26130Sstevel@tonic-gate		*stcb = sctp_findassociation_ep_addr(inp_p, to, netp, localep_sa, NULL);
26140Sstevel@tonic-gate		if (*stcb == NULL) {
26150Sstevel@tonic-gate			/*
26160Sstevel@tonic-gate			 * We should have only got back the same inp. If we
26170Sstevel@tonic-gate			 * got back a different ep we have a problem. The
26180Sstevel@tonic-gate			 * original findep got back l_inp and now
26190Sstevel@tonic-gate			 */
26200Sstevel@tonic-gate			if (l_inp != *inp_p) {
26210Sstevel@tonic-gate				SCTP_PRINTF("Bad problem find_ep got a diff inp then special_locate?\n");
26220Sstevel@tonic-gate			}
26230Sstevel@tonic-gate		} else {
26240Sstevel@tonic-gate			if (*locked_tcb == NULL) {
26250Sstevel@tonic-gate				/*
26260Sstevel@tonic-gate				 * In this case we found the assoc only
26270Sstevel@tonic-gate				 * after we locked the create lock. This
26280Sstevel@tonic-gate				 * means we are in a colliding case and we
26290Sstevel@tonic-gate				 * must make sure that we unlock the tcb if
26300Sstevel@tonic-gate				 * its one of the cases where we throw away
26310Sstevel@tonic-gate				 * the incoming packets.
26320Sstevel@tonic-gate				 */
26330Sstevel@tonic-gate				*locked_tcb = *stcb;
26340Sstevel@tonic-gate
26350Sstevel@tonic-gate				/*
26360Sstevel@tonic-gate				 * We must also increment the inp ref count
26370Sstevel@tonic-gate				 * since the ref_count flags was set when we
26380Sstevel@tonic-gate				 * did not find the TCB, now we found it
26390Sstevel@tonic-gate				 * which reduces the refcount.. we must
26400Sstevel@tonic-gate				 * raise it back out to balance it all :-)
26410Sstevel@tonic-gate				 */
26420Sstevel@tonic-gate				SCTP_INP_INCR_REF((*stcb)->sctp_ep);
26430Sstevel@tonic-gate				if ((*stcb)->sctp_ep != l_inp) {
26440Sstevel@tonic-gate					SCTP_PRINTF("Huh? ep:%p diff then l_inp:%p?\n",
26450Sstevel@tonic-gate					    (*stcb)->sctp_ep, l_inp);
26460Sstevel@tonic-gate				}
26470Sstevel@tonic-gate			}
26480Sstevel@tonic-gate		}
26490Sstevel@tonic-gate	}
26500Sstevel@tonic-gate	if (to == NULL) {
26510Sstevel@tonic-gate		return (NULL);
26520Sstevel@tonic-gate	}
26530Sstevel@tonic-gate	cookie_len -= SCTP_SIGNATURE_SIZE;
26540Sstevel@tonic-gate	if (*stcb == NULL) {
26550Sstevel@tonic-gate		/* this is the "normal" case... get a new TCB */
26560Sstevel@tonic-gate		*stcb = sctp_process_cookie_new(m, iphlen, offset, sh, cookie,
26570Sstevel@tonic-gate		    cookie_len, *inp_p, netp, to, &notification,
26580Sstevel@tonic-gate		    auth_skipped, auth_offset, auth_len, vrf_id, port);
26590Sstevel@tonic-gate	} else {
26600Sstevel@tonic-gate		/* this is abnormal... cookie-echo on existing TCB */
26610Sstevel@tonic-gate		had_a_existing_tcb = 1;
26620Sstevel@tonic-gate		*stcb = sctp_process_cookie_existing(m, iphlen, offset, sh,
26630Sstevel@tonic-gate		    cookie, cookie_len, *inp_p, *stcb, netp, to,
26640Sstevel@tonic-gate		    &notification, vrf_id, auth_skipped, auth_offset, auth_len, port);
26650Sstevel@tonic-gate	}
26660Sstevel@tonic-gate
26670Sstevel@tonic-gate	if (*stcb == NULL) {
26680Sstevel@tonic-gate		/* still no TCB... must be bad cookie-echo */
26690Sstevel@tonic-gate		return (NULL);
26700Sstevel@tonic-gate	}
26710Sstevel@tonic-gate	if ((*netp != NULL) && (m->m_flags & M_FLOWID)) {
26720Sstevel@tonic-gate		(*netp)->flowid = m->m_pkthdr.flowid;
26730Sstevel@tonic-gate#ifdef INVARIANTS
26740Sstevel@tonic-gate		(*netp)->flowidset = 1;
26750Sstevel@tonic-gate#endif
26760Sstevel@tonic-gate	}
26770Sstevel@tonic-gate	/*
26780Sstevel@tonic-gate	 * Ok, we built an association so confirm the address we sent the
26790Sstevel@tonic-gate	 * INIT-ACK to.
26800Sstevel@tonic-gate	 */
26810Sstevel@tonic-gate	netl = sctp_findnet(*stcb, to);
26820Sstevel@tonic-gate	/*
26830Sstevel@tonic-gate	 * This code should in theory NOT run but
26840Sstevel@tonic-gate	 */
26850Sstevel@tonic-gate	if (netl == NULL) {
26860Sstevel@tonic-gate		/* TSNH! Huh, why do I need to add this address here? */
26870Sstevel@tonic-gate		if (sctp_add_remote_addr(*stcb, to, NULL, SCTP_DONOT_SETSCOPE, SCTP_IN_COOKIE_PROC)) {
26880Sstevel@tonic-gate			return (NULL);
26890Sstevel@tonic-gate		}
26900Sstevel@tonic-gate		netl = sctp_findnet(*stcb, to);
26910Sstevel@tonic-gate	}
26920Sstevel@tonic-gate	if (netl) {
26930Sstevel@tonic-gate		if (netl->dest_state & SCTP_ADDR_UNCONFIRMED) {
26940Sstevel@tonic-gate			netl->dest_state &= ~SCTP_ADDR_UNCONFIRMED;
26950Sstevel@tonic-gate			(void)sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL,
26960Sstevel@tonic-gate			    netl);
26970Sstevel@tonic-gate			send_int_conf = 1;
26980Sstevel@tonic-gate		}
26990Sstevel@tonic-gate	}
27000Sstevel@tonic-gate	sctp_start_net_timers(*stcb);
27010Sstevel@tonic-gate	if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
27020Sstevel@tonic-gate		if (!had_a_existing_tcb ||
27030Sstevel@tonic-gate		    (((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
27040Sstevel@tonic-gate			/*
27050Sstevel@tonic-gate			 * If we have a NEW cookie or the connect never
27060Sstevel@tonic-gate			 * reached the connected state during collision we
27070Sstevel@tonic-gate			 * must do the TCP accept thing.
27080Sstevel@tonic-gate			 */
27090Sstevel@tonic-gate			struct socket *so, *oso;
27100Sstevel@tonic-gate			struct sctp_inpcb *inp;
27110Sstevel@tonic-gate
27120Sstevel@tonic-gate			if (notification == SCTP_NOTIFY_ASSOC_RESTART) {
27130Sstevel@tonic-gate				/*
27140Sstevel@tonic-gate				 * For a restart we will keep the same
27150Sstevel@tonic-gate				 * socket, no need to do anything. I THINK!!
27160Sstevel@tonic-gate				 */
27170Sstevel@tonic-gate				sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
27180Sstevel@tonic-gate				if (send_int_conf) {
27190Sstevel@tonic-gate					sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
27200Sstevel@tonic-gate					    (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
27210Sstevel@tonic-gate				}
27220Sstevel@tonic-gate				return (m);
27230Sstevel@tonic-gate			}
27240Sstevel@tonic-gate			oso = (*inp_p)->sctp_socket;
27250Sstevel@tonic-gate			atomic_add_int(&(*stcb)->asoc.refcnt, 1);
27260Sstevel@tonic-gate			SCTP_TCB_UNLOCK((*stcb));
27270Sstevel@tonic-gate			CURVNET_SET(oso->so_vnet);
27280Sstevel@tonic-gate			so = sonewconn(oso, 0
27290Sstevel@tonic-gate			    );
27300Sstevel@tonic-gate			CURVNET_RESTORE();
27310Sstevel@tonic-gate			SCTP_TCB_LOCK((*stcb));
27320Sstevel@tonic-gate			atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
27330Sstevel@tonic-gate
27340Sstevel@tonic-gate			if (so == NULL) {
27350Sstevel@tonic-gate				struct mbuf *op_err;
27360Sstevel@tonic-gate
27370Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
27380Sstevel@tonic-gate				struct socket *pcb_so;
27390Sstevel@tonic-gate
27400Sstevel@tonic-gate#endif
27410Sstevel@tonic-gate				/* Too many sockets */
27420Sstevel@tonic-gate				SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n");
27430Sstevel@tonic-gate				op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
27440Sstevel@tonic-gate				sctp_abort_association(*inp_p, NULL, m, iphlen,
27450Sstevel@tonic-gate				    sh, op_err, vrf_id, port);
27460Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
27474954Sachimm				pcb_so = SCTP_INP_SO(*inp_p);
27480Sstevel@tonic-gate				atomic_add_int(&(*stcb)->asoc.refcnt, 1);
27490Sstevel@tonic-gate				SCTP_TCB_UNLOCK((*stcb));
27500Sstevel@tonic-gate				SCTP_SOCKET_LOCK(pcb_so, 1);
27510Sstevel@tonic-gate				SCTP_TCB_LOCK((*stcb));
27520Sstevel@tonic-gate				atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
27530Sstevel@tonic-gate#endif
27540Sstevel@tonic-gate				(void)sctp_free_assoc(*inp_p, *stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_20);
27550Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
27560Sstevel@tonic-gate				SCTP_SOCKET_UNLOCK(pcb_so, 1);
27570Sstevel@tonic-gate#endif
27580Sstevel@tonic-gate				return (NULL);
27590Sstevel@tonic-gate			}
27600Sstevel@tonic-gate			inp = (struct sctp_inpcb *)so->so_pcb;
27610Sstevel@tonic-gate			SCTP_INP_INCR_REF(inp);
27620Sstevel@tonic-gate			/*
27630Sstevel@tonic-gate			 * We add the unbound flag here so that if we get an
27640Sstevel@tonic-gate			 * soabort() before we get the move_pcb done, we
27650Sstevel@tonic-gate			 * will properly cleanup.
27660Sstevel@tonic-gate			 */
27670Sstevel@tonic-gate			inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE |
27680Sstevel@tonic-gate			    SCTP_PCB_FLAGS_CONNECTED |
27690Sstevel@tonic-gate			    SCTP_PCB_FLAGS_IN_TCPPOOL |
27700Sstevel@tonic-gate			    SCTP_PCB_FLAGS_UNBOUND |
27710Sstevel@tonic-gate			    (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) |
27720Sstevel@tonic-gate			    SCTP_PCB_FLAGS_DONT_WAKE);
27730Sstevel@tonic-gate			inp->sctp_features = (*inp_p)->sctp_features;
27740Sstevel@tonic-gate			inp->sctp_mobility_features = (*inp_p)->sctp_mobility_features;
27750Sstevel@tonic-gate			inp->sctp_socket = so;
27760Sstevel@tonic-gate			inp->sctp_frag_point = (*inp_p)->sctp_frag_point;
27774954Sachimm			inp->sctp_cmt_on_off = (*inp_p)->sctp_cmt_on_off;
27784954Sachimm			inp->sctp_ecn_enable = (*inp_p)->sctp_ecn_enable;
27790Sstevel@tonic-gate			inp->partial_delivery_point = (*inp_p)->partial_delivery_point;
27800Sstevel@tonic-gate			inp->sctp_context = (*inp_p)->sctp_context;
27810Sstevel@tonic-gate			inp->local_strreset_support = (*inp_p)->local_strreset_support;
27820Sstevel@tonic-gate			inp->inp_starting_point_for_iterator = NULL;
27830Sstevel@tonic-gate			/*
27840Sstevel@tonic-gate			 * copy in the authentication parameters from the
27850Sstevel@tonic-gate			 * original endpoint
27860Sstevel@tonic-gate			 */
27870Sstevel@tonic-gate			if (inp->sctp_ep.local_hmacs)
27880Sstevel@tonic-gate				sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
27890Sstevel@tonic-gate			inp->sctp_ep.local_hmacs =
27900Sstevel@tonic-gate			    sctp_copy_hmaclist((*inp_p)->sctp_ep.local_hmacs);
27910Sstevel@tonic-gate			if (inp->sctp_ep.local_auth_chunks)
27920Sstevel@tonic-gate				sctp_free_chunklist(inp->sctp_ep.local_auth_chunks);
27930Sstevel@tonic-gate			inp->sctp_ep.local_auth_chunks =
27940Sstevel@tonic-gate			    sctp_copy_chunklist((*inp_p)->sctp_ep.local_auth_chunks);
27950Sstevel@tonic-gate
27960Sstevel@tonic-gate			/*
27970Sstevel@tonic-gate			 * Now we must move it from one hash table to
27980Sstevel@tonic-gate			 * another and get the tcb in the right place.
27990Sstevel@tonic-gate			 */
28000Sstevel@tonic-gate
28010Sstevel@tonic-gate			/*
28020Sstevel@tonic-gate			 * This is where the one-2-one socket is put into
28030Sstevel@tonic-gate			 * the accept state waiting for the accept!
28040Sstevel@tonic-gate			 */
28050Sstevel@tonic-gate			if (*stcb) {
28060Sstevel@tonic-gate				(*stcb)->asoc.state |= SCTP_STATE_IN_ACCEPT_QUEUE;
28070Sstevel@tonic-gate			}
28080Sstevel@tonic-gate			sctp_move_pcb_and_assoc(*inp_p, inp, *stcb);
28090Sstevel@tonic-gate
28100Sstevel@tonic-gate			atomic_add_int(&(*stcb)->asoc.refcnt, 1);
28110Sstevel@tonic-gate			SCTP_TCB_UNLOCK((*stcb));
28120Sstevel@tonic-gate
28130Sstevel@tonic-gate			sctp_pull_off_control_to_new_inp((*inp_p), inp, *stcb,
28140Sstevel@tonic-gate			    0);
28150Sstevel@tonic-gate			SCTP_TCB_LOCK((*stcb));
28160Sstevel@tonic-gate			atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
28170Sstevel@tonic-gate
28180Sstevel@tonic-gate
28190Sstevel@tonic-gate			/*
28200Sstevel@tonic-gate			 * now we must check to see if we were aborted while
28210Sstevel@tonic-gate			 * the move was going on and the lock/unlock
28220Sstevel@tonic-gate			 * happened.
28230Sstevel@tonic-gate			 */
28240Sstevel@tonic-gate			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
28250Sstevel@tonic-gate				/*
28260Sstevel@tonic-gate				 * yep it was, we leave the assoc attached
28270Sstevel@tonic-gate				 * to the socket since the sctp_inpcb_free()
28280Sstevel@tonic-gate				 * call will send an abort for us.
28290Sstevel@tonic-gate				 */
28300Sstevel@tonic-gate				SCTP_INP_DECR_REF(inp);
28310Sstevel@tonic-gate				return (NULL);
28320Sstevel@tonic-gate			}
28330Sstevel@tonic-gate			SCTP_INP_DECR_REF(inp);
28340Sstevel@tonic-gate			/* Switch over to the new guy */
28350Sstevel@tonic-gate			*inp_p = inp;
28360Sstevel@tonic-gate			sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
28370Sstevel@tonic-gate			if (send_int_conf) {
28380Sstevel@tonic-gate				sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
28390Sstevel@tonic-gate				    (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
28400Sstevel@tonic-gate			}
28410Sstevel@tonic-gate			/*
28420Sstevel@tonic-gate			 * Pull it from the incomplete queue and wake the
28430Sstevel@tonic-gate			 * guy
28440Sstevel@tonic-gate			 */
28450Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
28460Sstevel@tonic-gate			atomic_add_int(&(*stcb)->asoc.refcnt, 1);
28470Sstevel@tonic-gate			SCTP_TCB_UNLOCK((*stcb));
28480Sstevel@tonic-gate			SCTP_SOCKET_LOCK(so, 1);
28490Sstevel@tonic-gate#endif
28500Sstevel@tonic-gate			soisconnected(so);
28510Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
28520Sstevel@tonic-gate			SCTP_TCB_LOCK((*stcb));
28530Sstevel@tonic-gate			atomic_subtract_int(&(*stcb)->asoc.refcnt, 1);
28540Sstevel@tonic-gate			SCTP_SOCKET_UNLOCK(so, 1);
28550Sstevel@tonic-gate#endif
28560Sstevel@tonic-gate			return (m);
28570Sstevel@tonic-gate		}
28580Sstevel@tonic-gate	}
28590Sstevel@tonic-gate	if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
28600Sstevel@tonic-gate		if (notification) {
28610Sstevel@tonic-gate			sctp_ulp_notify(notification, *stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
28620Sstevel@tonic-gate		}
28630Sstevel@tonic-gate		if (send_int_conf) {
28640Sstevel@tonic-gate			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
28650Sstevel@tonic-gate			    (*stcb), 0, (void *)netl, SCTP_SO_NOT_LOCKED);
28660Sstevel@tonic-gate		}
28670Sstevel@tonic-gate	}
28680Sstevel@tonic-gate	return (m);
28690Sstevel@tonic-gate}
28700Sstevel@tonic-gate
28710Sstevel@tonic-gatestatic void
28720Sstevel@tonic-gatesctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp SCTP_UNUSED,
28730Sstevel@tonic-gate    struct sctp_tcb *stcb, struct sctp_nets *net)
28740Sstevel@tonic-gate{
28750Sstevel@tonic-gate	/* cp must not be used, others call this without a c-ack :-) */
28760Sstevel@tonic-gate	struct sctp_association *asoc;
28770Sstevel@tonic-gate
28780Sstevel@tonic-gate	SCTPDBG(SCTP_DEBUG_INPUT2,
28790Sstevel@tonic-gate	    "sctp_handle_cookie_ack: handling COOKIE-ACK\n");
28800Sstevel@tonic-gate	if (stcb == NULL)
28810Sstevel@tonic-gate		return;
28820Sstevel@tonic-gate
28830Sstevel@tonic-gate	asoc = &stcb->asoc;
28840Sstevel@tonic-gate
28850Sstevel@tonic-gate	sctp_stop_all_cookie_timers(stcb);
28860Sstevel@tonic-gate	/* process according to association state */
28870Sstevel@tonic-gate	if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) {
28880Sstevel@tonic-gate		/* state change only needed when I am in right state */
28890Sstevel@tonic-gate		SCTPDBG(SCTP_DEBUG_INPUT2, "moving to OPEN state\n");
28900Sstevel@tonic-gate		SCTP_SET_STATE(asoc, SCTP_STATE_OPEN);
28910Sstevel@tonic-gate		sctp_start_net_timers(stcb);
28920Sstevel@tonic-gate		if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
28930Sstevel@tonic-gate			sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
28940Sstevel@tonic-gate			    stcb->sctp_ep, stcb, asoc->primary_destination);
28950Sstevel@tonic-gate
28960Sstevel@tonic-gate		}
28970Sstevel@tonic-gate		/* update RTO */
28980Sstevel@tonic-gate		SCTP_STAT_INCR_COUNTER32(sctps_activeestab);
28990Sstevel@tonic-gate		SCTP_STAT_INCR_GAUGE32(sctps_currestab);
29000Sstevel@tonic-gate		if (asoc->overall_error_count == 0) {
29010Sstevel@tonic-gate			net->RTO = sctp_calculate_rto(stcb, asoc, net,
29020Sstevel@tonic-gate			    &asoc->time_entered, sctp_align_safe_nocopy,
29030Sstevel@tonic-gate			    SCTP_RTT_FROM_NON_DATA);
29040Sstevel@tonic-gate		}
29050Sstevel@tonic-gate		(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
29060Sstevel@tonic-gate		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
29070Sstevel@tonic-gate		if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
29080Sstevel@tonic-gate		    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
29090Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
29100Sstevel@tonic-gate			struct socket *so;
29110Sstevel@tonic-gate
29120Sstevel@tonic-gate#endif
29130Sstevel@tonic-gate			stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
29140Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
29150Sstevel@tonic-gate			so = SCTP_INP_SO(stcb->sctp_ep);
29160Sstevel@tonic-gate			atomic_add_int(&stcb->asoc.refcnt, 1);
29170Sstevel@tonic-gate			SCTP_TCB_UNLOCK(stcb);
29180Sstevel@tonic-gate			SCTP_SOCKET_LOCK(so, 1);
29190Sstevel@tonic-gate			SCTP_TCB_LOCK(stcb);
29200Sstevel@tonic-gate			atomic_subtract_int(&stcb->asoc.refcnt, 1);
29210Sstevel@tonic-gate#endif
29220Sstevel@tonic-gate			if ((stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) == 0) {
29230Sstevel@tonic-gate				soisconnected(stcb->sctp_socket);
29240Sstevel@tonic-gate			}
29250Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
29260Sstevel@tonic-gate			SCTP_SOCKET_UNLOCK(so, 1);
29270Sstevel@tonic-gate#endif
29280Sstevel@tonic-gate		}
29290Sstevel@tonic-gate		/*
29300Sstevel@tonic-gate		 * since we did not send a HB make sure we don't double
29310Sstevel@tonic-gate		 * things
29320Sstevel@tonic-gate		 */
29330Sstevel@tonic-gate		net->hb_responded = 1;
29340Sstevel@tonic-gate
29350Sstevel@tonic-gate		if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
29360Sstevel@tonic-gate			/*
29370Sstevel@tonic-gate			 * We don't need to do the asconf thing, nor hb or
29380Sstevel@tonic-gate			 * autoclose if the socket is closed.
29390Sstevel@tonic-gate			 */
29400Sstevel@tonic-gate			goto closed_socket;
29410Sstevel@tonic-gate		}
29420Sstevel@tonic-gate		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
29430Sstevel@tonic-gate		    stcb, net);
29440Sstevel@tonic-gate
29450Sstevel@tonic-gate
29460Sstevel@tonic-gate		if (stcb->asoc.sctp_autoclose_ticks &&
29470Sstevel@tonic-gate		    sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTOCLOSE)) {
29480Sstevel@tonic-gate			sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE,
29490Sstevel@tonic-gate			    stcb->sctp_ep, stcb, NULL);
29500Sstevel@tonic-gate		}
29510Sstevel@tonic-gate		/*
29520Sstevel@tonic-gate		 * send ASCONF if parameters are pending and ASCONFs are
29530Sstevel@tonic-gate		 * allowed (eg. addresses changed when init/cookie echo were
29540Sstevel@tonic-gate		 * in flight)
29550Sstevel@tonic-gate		 */
29560Sstevel@tonic-gate		if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_DO_ASCONF)) &&
29570Sstevel@tonic-gate		    (stcb->asoc.peer_supports_asconf) &&
29580Sstevel@tonic-gate		    (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) {
29598452SJohn.Wren.Kennedy@Sun.COM#ifdef SCTP_TIMER_BASED_ASCONF
29608452SJohn.Wren.Kennedy@Sun.COM			sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
29618452SJohn.Wren.Kennedy@Sun.COM			    stcb->sctp_ep, stcb,
29628452SJohn.Wren.Kennedy@Sun.COM			    stcb->asoc.primary_destination);
29638452SJohn.Wren.Kennedy@Sun.COM#else
29648452SJohn.Wren.Kennedy@Sun.COM			sctp_send_asconf(stcb, stcb->asoc.primary_destination,
29658452SJohn.Wren.Kennedy@Sun.COM			    SCTP_ADDR_NOT_LOCKED);
29668452SJohn.Wren.Kennedy@Sun.COM#endif
29678452SJohn.Wren.Kennedy@Sun.COM		}
29688452SJohn.Wren.Kennedy@Sun.COM	}
29698452SJohn.Wren.Kennedy@Sun.COMclosed_socket:
29708452SJohn.Wren.Kennedy@Sun.COM	/* Toss the cookie if I can */
29718452SJohn.Wren.Kennedy@Sun.COM	sctp_toss_old_cookies(stcb, asoc);
29728452SJohn.Wren.Kennedy@Sun.COM	if (!TAILQ_EMPTY(&asoc->sent_queue)) {
29738452SJohn.Wren.Kennedy@Sun.COM		/* Restart the timer if we have pending data */
29748452SJohn.Wren.Kennedy@Sun.COM		struct sctp_tmit_chunk *chk;
29758452SJohn.Wren.Kennedy@Sun.COM
29768452SJohn.Wren.Kennedy@Sun.COM		chk = TAILQ_FIRST(&asoc->sent_queue);
29778452SJohn.Wren.Kennedy@Sun.COM		sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo);
29788452SJohn.Wren.Kennedy@Sun.COM	}
29798452SJohn.Wren.Kennedy@Sun.COM}
29808452SJohn.Wren.Kennedy@Sun.COM
29818452SJohn.Wren.Kennedy@Sun.COMstatic void
29828452SJohn.Wren.Kennedy@Sun.COMsctp_handle_ecn_echo(struct sctp_ecne_chunk *cp,
29838452SJohn.Wren.Kennedy@Sun.COM    struct sctp_tcb *stcb)
29848452SJohn.Wren.Kennedy@Sun.COM{
29858452SJohn.Wren.Kennedy@Sun.COM	struct sctp_nets *net;
29868452SJohn.Wren.Kennedy@Sun.COM	struct sctp_tmit_chunk *lchk;
29878452SJohn.Wren.Kennedy@Sun.COM	struct sctp_ecne_chunk bkup;
29888452SJohn.Wren.Kennedy@Sun.COM	uint8_t override_bit;
29898452SJohn.Wren.Kennedy@Sun.COM	uint32_t tsn, window_data_tsn;
29908452SJohn.Wren.Kennedy@Sun.COM	int len;
29918452SJohn.Wren.Kennedy@Sun.COM	unsigned int pkt_cnt;
29928452SJohn.Wren.Kennedy@Sun.COM
29938452SJohn.Wren.Kennedy@Sun.COM	len = ntohs(cp->ch.chunk_length);
29948452SJohn.Wren.Kennedy@Sun.COM	if ((len != sizeof(struct sctp_ecne_chunk)) &&
29950Sstevel@tonic-gate	    (len != sizeof(struct old_sctp_ecne_chunk))) {
29960Sstevel@tonic-gate		return;
29970Sstevel@tonic-gate	}
29980Sstevel@tonic-gate	if (len == sizeof(struct old_sctp_ecne_chunk)) {
29990Sstevel@tonic-gate		/* Its the old format */
30000Sstevel@tonic-gate		memcpy(&bkup, cp, sizeof(struct old_sctp_ecne_chunk));
30010Sstevel@tonic-gate		bkup.num_pkts_since_cwr = htonl(1);
30020Sstevel@tonic-gate		cp = &bkup;
30030Sstevel@tonic-gate	}
30040Sstevel@tonic-gate	SCTP_STAT_INCR(sctps_recvecne);
30050Sstevel@tonic-gate	tsn = ntohl(cp->tsn);
30060Sstevel@tonic-gate	pkt_cnt = ntohl(cp->num_pkts_since_cwr);
30070Sstevel@tonic-gate	lchk = TAILQ_LAST(&stcb->asoc.send_queue, sctpchunk_listhead);
30080Sstevel@tonic-gate	if (lchk == NULL) {
30090Sstevel@tonic-gate		window_data_tsn = stcb->asoc.sending_seq - 1;
30100Sstevel@tonic-gate	} else {
30110Sstevel@tonic-gate		window_data_tsn = lchk->rec.data.TSN_seq;
30120Sstevel@tonic-gate	}
30130Sstevel@tonic-gate
30140Sstevel@tonic-gate	/* Find where it was sent to if possible. */
30150Sstevel@tonic-gate	net = NULL;
30160Sstevel@tonic-gate	TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) {
30170Sstevel@tonic-gate		if (lchk->rec.data.TSN_seq == tsn) {
30180Sstevel@tonic-gate			net = lchk->whoTo;
30190Sstevel@tonic-gate			net->ecn_prev_cwnd = lchk->rec.data.cwnd_at_send;
30200Sstevel@tonic-gate			break;
30210Sstevel@tonic-gate		}
30220Sstevel@tonic-gate		if (SCTP_TSN_GT(lchk->rec.data.TSN_seq, tsn)) {
30230Sstevel@tonic-gate			break;
30240Sstevel@tonic-gate		}
30250Sstevel@tonic-gate	}
30260Sstevel@tonic-gate	if (net == NULL) {
30270Sstevel@tonic-gate		/*
30280Sstevel@tonic-gate		 * What to do. A previous send of a CWR was possibly lost.
30290Sstevel@tonic-gate		 * See how old it is, we may have it marked on the actual
30300Sstevel@tonic-gate		 * net.
30310Sstevel@tonic-gate		 */
30320Sstevel@tonic-gate		TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
30330Sstevel@tonic-gate			if (tsn == net->last_cwr_tsn) {
30340Sstevel@tonic-gate				/* Found him, send it off */
30350Sstevel@tonic-gate				break;
30367563SPrasad.Singamsetty@Sun.COM			}
30370Sstevel@tonic-gate		}
30380Sstevel@tonic-gate		if (net == NULL) {
30390Sstevel@tonic-gate			/*
30400Sstevel@tonic-gate			 * If we reach here, we need to send a special CWR
30410Sstevel@tonic-gate			 * that says hey, we did this a long time ago and
30420Sstevel@tonic-gate			 * you lost the response.
30430Sstevel@tonic-gate			 */
30440Sstevel@tonic-gate			net = TAILQ_FIRST(&stcb->asoc.nets);
30450Sstevel@tonic-gate			if (net == NULL) {
30460Sstevel@tonic-gate				/* TSNH */
30470Sstevel@tonic-gate				return;
30480Sstevel@tonic-gate			}
30490Sstevel@tonic-gate			override_bit = SCTP_CWR_REDUCE_OVERRIDE;
30500Sstevel@tonic-gate		} else {
30510Sstevel@tonic-gate			override_bit = 0;
30520Sstevel@tonic-gate		}
30530Sstevel@tonic-gate	} else {
30540Sstevel@tonic-gate		override_bit = 0;
30550Sstevel@tonic-gate	}
30560Sstevel@tonic-gate	if (SCTP_TSN_GT(tsn, net->cwr_window_tsn) &&
30570Sstevel@tonic-gate	    ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) {
30580Sstevel@tonic-gate		/*
30590Sstevel@tonic-gate		 * JRS - Use the congestion control given in the pluggable
30600Sstevel@tonic-gate		 * CC module
30610Sstevel@tonic-gate		 */
30620Sstevel@tonic-gate		stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 0, pkt_cnt);
30630Sstevel@tonic-gate		/*
30640Sstevel@tonic-gate		 * We reduce once every RTT. So we will only lower cwnd at
30650Sstevel@tonic-gate		 * the next sending seq i.e. the window_data_tsn
30660Sstevel@tonic-gate		 */
30670Sstevel@tonic-gate		net->cwr_window_tsn = window_data_tsn;
30680Sstevel@tonic-gate		net->ecn_ce_pkt_cnt += pkt_cnt;
30690Sstevel@tonic-gate		net->lost_cnt = pkt_cnt;
30700Sstevel@tonic-gate		net->last_cwr_tsn = tsn;
30710Sstevel@tonic-gate	} else {
30720Sstevel@tonic-gate		override_bit |= SCTP_CWR_IN_SAME_WINDOW;
30730Sstevel@tonic-gate		if (SCTP_TSN_GT(tsn, net->last_cwr_tsn) &&
30740Sstevel@tonic-gate		    ((override_bit & SCTP_CWR_REDUCE_OVERRIDE) == 0)) {
30750Sstevel@tonic-gate			/*
30760Sstevel@tonic-gate			 * Another loss in the same window update how many
30770Sstevel@tonic-gate			 * marks/packets lost we have had.
30780Sstevel@tonic-gate			 */
30790Sstevel@tonic-gate			int cnt = 1;
30800Sstevel@tonic-gate
30810Sstevel@tonic-gate			if (pkt_cnt > net->lost_cnt) {
30820Sstevel@tonic-gate				/* Should be the case */
30830Sstevel@tonic-gate				cnt = (pkt_cnt - net->lost_cnt);
30840Sstevel@tonic-gate				net->ecn_ce_pkt_cnt += cnt;
30850Sstevel@tonic-gate			}
30860Sstevel@tonic-gate			net->lost_cnt = pkt_cnt;
30870Sstevel@tonic-gate			net->last_cwr_tsn = tsn;
30880Sstevel@tonic-gate			/*
30890Sstevel@tonic-gate			 * Most CC functions will ignore this call, since we
30900Sstevel@tonic-gate			 * are in-window yet of the initial CE the peer saw.
30910Sstevel@tonic-gate			 */
30920Sstevel@tonic-gate			stcb->asoc.cc_functions.sctp_cwnd_update_after_ecn_echo(stcb, net, 1, cnt);
30930Sstevel@tonic-gate		}
30940Sstevel@tonic-gate	}
30950Sstevel@tonic-gate	/*
30969017SJohn.Wren.Kennedy@Sun.COM	 * We always send a CWR this way if our previous one was lost our
30970Sstevel@tonic-gate	 * peer will get an update, or if it is not time again to reduce we
30980Sstevel@tonic-gate	 * still get the cwr to the peer. Note we set the override when we
30990Sstevel@tonic-gate	 * could not find the TSN on the chunk or the destination network.
31000Sstevel@tonic-gate	 */
31019017SJohn.Wren.Kennedy@Sun.COM	sctp_send_cwr(stcb, net, net->last_cwr_tsn, override_bit);
31029017SJohn.Wren.Kennedy@Sun.COM}
31039017SJohn.Wren.Kennedy@Sun.COM
31049017SJohn.Wren.Kennedy@Sun.COMstatic void
31050Sstevel@tonic-gatesctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb, struct sctp_nets *net)
31060Sstevel@tonic-gate{
31070Sstevel@tonic-gate	/*
31080Sstevel@tonic-gate	 * Here we get a CWR from the peer. We must look in the outqueue and
31099017SJohn.Wren.Kennedy@Sun.COM	 * make sure that we have a covered ECNE in teh control chunk part.
31100Sstevel@tonic-gate	 * If so remove it.
31110Sstevel@tonic-gate	 */
31120Sstevel@tonic-gate	struct sctp_tmit_chunk *chk;
31130Sstevel@tonic-gate	struct sctp_ecne_chunk *ecne;
31149017SJohn.Wren.Kennedy@Sun.COM	int override;
31159017SJohn.Wren.Kennedy@Sun.COM	uint32_t cwr_tsn;
31169017SJohn.Wren.Kennedy@Sun.COM
31179017SJohn.Wren.Kennedy@Sun.COM	cwr_tsn = ntohl(cp->tsn);
31189017SJohn.Wren.Kennedy@Sun.COM
31199017SJohn.Wren.Kennedy@Sun.COM	override = cp->ch.chunk_flags & SCTP_CWR_REDUCE_OVERRIDE;
31200Sstevel@tonic-gate	TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
31219017SJohn.Wren.Kennedy@Sun.COM		if (chk->rec.chunk_id.id != SCTP_ECN_ECHO) {
31220Sstevel@tonic-gate			continue;
31230Sstevel@tonic-gate		}
31240Sstevel@tonic-gate		if ((override == 0) && (chk->whoTo != net)) {
31259017SJohn.Wren.Kennedy@Sun.COM			/* Must be from the right src unless override is set */
31260Sstevel@tonic-gate			continue;
31270Sstevel@tonic-gate		}
31280Sstevel@tonic-gate		ecne = mtod(chk->data, struct sctp_ecne_chunk *);
31290Sstevel@tonic-gate		if (SCTP_TSN_GE(cwr_tsn, ntohl(ecne->tsn))) {
31300Sstevel@tonic-gate			/* this covers this ECNE, we can remove it */
31319017SJohn.Wren.Kennedy@Sun.COM			stcb->asoc.ecn_echo_cnt_onq--;
31320Sstevel@tonic-gate			TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk,
31330Sstevel@tonic-gate			    sctp_next);
31340Sstevel@tonic-gate			if (chk->data) {
31350Sstevel@tonic-gate				sctp_m_freem(chk->data);
31369017SJohn.Wren.Kennedy@Sun.COM				chk->data = NULL;
31379017SJohn.Wren.Kennedy@Sun.COM			}
31380Sstevel@tonic-gate			stcb->asoc.ctrl_queue_cnt--;
31399017SJohn.Wren.Kennedy@Sun.COM			sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
31400Sstevel@tonic-gate			if (override == 0) {
31410Sstevel@tonic-gate				break;
31420Sstevel@tonic-gate			}
31430Sstevel@tonic-gate		}
31440Sstevel@tonic-gate	}
31459017SJohn.Wren.Kennedy@Sun.COM}
31469017SJohn.Wren.Kennedy@Sun.COM
31479017SJohn.Wren.Kennedy@Sun.COMstatic void
31489017SJohn.Wren.Kennedy@Sun.COMsctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp SCTP_UNUSED,
31499017SJohn.Wren.Kennedy@Sun.COM    struct sctp_tcb *stcb, struct sctp_nets *net)
31500Sstevel@tonic-gate{
31510Sstevel@tonic-gate	struct sctp_association *asoc;
31529017SJohn.Wren.Kennedy@Sun.COM
31530Sstevel@tonic-gate#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
31549017SJohn.Wren.Kennedy@Sun.COM	struct socket *so;
31550Sstevel@tonic-gate
31560Sstevel@tonic-gate#endif
31570Sstevel@tonic-gate
31580Sstevel@tonic-gate	SCTPDBG(SCTP_DEBUG_INPUT2,
31599017SJohn.Wren.Kennedy@Sun.COM	    "sctp_handle_shutdown_complete: handling SHUTDOWN-COMPLETE\n");
31609017SJohn.Wren.Kennedy@Sun.COM	if (stcb == NULL)
31619017SJohn.Wren.Kennedy@Sun.COM		return;
31620Sstevel@tonic-gate
31630Sstevel@tonic-gate	asoc = &stcb->asoc;
31640Sstevel@tonic-gate	/* process according to association state */
31657563SPrasad.Singamsetty@Sun.COM	if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) {
31667563SPrasad.Singamsetty@Sun.COM		/* unexpected SHUTDOWN-COMPLETE... so ignore... */
31679017SJohn.Wren.Kennedy@Sun.COM		SCTPDBG(SCTP_DEBUG_INPUT2,
31687563SPrasad.Singamsetty@Sun.COM		    "sctp_handle_shutdown_complete: not in SCTP_STATE_SHUTDOWN_ACK_SENT --- ignore\n");
31697563SPrasad.Singamsetty@Sun.COM		SCTP_TCB_UNLOCK(stcb);
31707563SPrasad.Singamsetty@Sun.COM		return;
31717563SPrasad.Singamsetty@Sun.COM	}
31729017SJohn.Wren.Kennedy@Sun.COM	/* notify upper layer protocol */
31739017SJohn.Wren.Kennedy@Sun.COM	if (stcb->sctp_socket) {
31749017SJohn.Wren.Kennedy@Sun.COM		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
31759017SJohn.Wren.Kennedy@Sun.COM		/* are the queues empty? they should be */
31767563SPrasad.Singamsetty@Sun.COM		if (!TAILQ_EMPTY(&asoc->send_queue) ||
31777563SPrasad.Singamsetty@Sun.COM		    !TAILQ_EMPTY(&asoc->sent_queue) ||
31787563SPrasad.Singamsetty@Sun.COM		    !stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
31799017SJohn.Wren.Kennedy@Sun.COM			sctp_report_all_outbound(stcb, 0, SCTP_SO_NOT_LOCKED);
31807563SPrasad.Singamsetty@Sun.COM		}
31817563SPrasad.Singamsetty@Sun.COM	}
31829017SJohn.Wren.Kennedy@Sun.COM	/* stop the timer */
31837563SPrasad.Singamsetty@Sun.COM	sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_22);
31847563SPrasad.Singamsetty@Sun.COM	SCTP_STAT_INCR_COUNTER32(sctps_shutdown);
31857563SPrasad.Singamsetty@Sun.COM	/* free the TCB */
31867563SPrasad.Singamsetty@Sun.COM	SCTPDBG(SCTP_DEBUG_INPUT2,
31877563SPrasad.Singamsetty@Sun.COM	    "sctp_handle_shutdown_complete: calls free-asoc\n");
31889017SJohn.Wren.Kennedy@Sun.COM#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
31897563SPrasad.Singamsetty@Sun.COM	so = SCTP_INP_SO(stcb->sctp_ep);
31907563SPrasad.Singamsetty@Sun.COM	atomic_add_int(&stcb->asoc.refcnt, 1);
31917563SPrasad.Singamsetty@Sun.COM	SCTP_TCB_UNLOCK(stcb);
31927563SPrasad.Singamsetty@Sun.COM	SCTP_SOCKET_LOCK(so, 1);
31939017SJohn.Wren.Kennedy@Sun.COM	SCTP_TCB_LOCK(stcb);
31949017SJohn.Wren.Kennedy@Sun.COM	atomic_subtract_int(&stcb->asoc.refcnt, 1);
31959017SJohn.Wren.Kennedy@Sun.COM#endif
31967563SPrasad.Singamsetty@Sun.COM	(void)sctp_free_assoc(stcb->sctp_ep, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_23);
31977563SPrasad.Singamsetty@Sun.COM#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
31987563SPrasad.Singamsetty@Sun.COM	SCTP_SOCKET_UNLOCK(so, 1);
31997563SPrasad.Singamsetty@Sun.COM#endif
32009017SJohn.Wren.Kennedy@Sun.COM	return;
32019017SJohn.Wren.Kennedy@Sun.COM}
32029017SJohn.Wren.Kennedy@Sun.COM
32037563SPrasad.Singamsetty@Sun.COMstatic int
32047563SPrasad.Singamsetty@Sun.COMprocess_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
32057563SPrasad.Singamsetty@Sun.COM    struct sctp_nets *net, uint8_t flg)
32060Sstevel@tonic-gate{
32070Sstevel@tonic-gate	switch (desc->chunk_type) {
32080Sstevel@tonic-gate	case SCTP_DATA:
32090Sstevel@tonic-gate		/* find the tsn to resend (possibly */
32100Sstevel@tonic-gate		{
32110Sstevel@tonic-gate			uint32_t tsn;
32120Sstevel@tonic-gate			struct sctp_tmit_chunk *tp1;
32130Sstevel@tonic-gate
32140Sstevel@tonic-gate			tsn = ntohl(desc->tsn_ifany);
32150Sstevel@tonic-gate			TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
32164954Sachimm				if (tp1->rec.data.TSN_seq == tsn) {
32170Sstevel@tonic-gate					/* found it */
32180Sstevel@tonic-gate					break;
32190Sstevel@tonic-gate				}
32200Sstevel@tonic-gate				if (SCTP_TSN_GT(tp1->rec.data.TSN_seq, tsn)) {
32210Sstevel@tonic-gate					/* not found */
32220Sstevel@tonic-gate					tp1 = NULL;
32230Sstevel@tonic-gate					break;
32240Sstevel@tonic-gate				}
32250Sstevel@tonic-gate			}
32260Sstevel@tonic-gate			if (tp1 == NULL) {
32274954Sachimm				/*
32280Sstevel@tonic-gate				 * Do it the other way , aka without paying
32290Sstevel@tonic-gate				 * attention to queue seq order.
32300Sstevel@tonic-gate				 */
32310Sstevel@tonic-gate				SCTP_STAT_INCR(sctps_pdrpdnfnd);
32320Sstevel@tonic-gate				TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
32330Sstevel@tonic-gate					if (tp1->rec.data.TSN_seq == tsn) {
32340Sstevel@tonic-gate						/* found it */
32350Sstevel@tonic-gate						break;
32360Sstevel@tonic-gate					}
32370Sstevel@tonic-gate				}
32380Sstevel@tonic-gate			}
32390Sstevel@tonic-gate			if (tp1 == NULL) {
32400Sstevel@tonic-gate				SCTP_STAT_INCR(sctps_pdrptsnnf);
32410Sstevel@tonic-gate			}
32420Sstevel@tonic-gate			if ((tp1) && (tp1->sent < SCTP_DATAGRAM_ACKED)) {
32430Sstevel@tonic-gate				uint8_t *ddp;
32440Sstevel@tonic-gate
32450Sstevel@tonic-gate				if (((flg & SCTP_BADCRC) == 0) &&
32460Sstevel@tonic-gate				    ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) {
32470Sstevel@tonic-gate					return (0);
32480Sstevel@tonic-gate				}
32490Sstevel@tonic-gate				if ((stcb->asoc.peers_rwnd == 0) &&
32500Sstevel@tonic-gate				    ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) {
32510Sstevel@tonic-gate					SCTP_STAT_INCR(sctps_pdrpdiwnp);
32520Sstevel@tonic-gate					return (0);
32530Sstevel@tonic-gate				}
32540Sstevel@tonic-gate				if (stcb->asoc.peers_rwnd == 0 &&
32550Sstevel@tonic-gate				    (flg & SCTP_FROM_MIDDLE_BOX)) {
32560Sstevel@tonic-gate					SCTP_STAT_INCR(sctps_pdrpdizrw);
32570Sstevel@tonic-gate					return (0);
32580Sstevel@tonic-gate				}
32590Sstevel@tonic-gate				ddp = (uint8_t *) (mtod(tp1->data, caddr_t)+
32600Sstevel@tonic-gate				    sizeof(struct sctp_data_chunk));
32610Sstevel@tonic-gate				{
32620Sstevel@tonic-gate					unsigned int iii;
32630Sstevel@tonic-gate
32640Sstevel@tonic-gate					for (iii = 0; iii < sizeof(desc->data_bytes);
32650Sstevel@tonic-gate					    iii++) {
32660Sstevel@tonic-gate						if (ddp[iii] != desc->data_bytes[iii]) {
32670Sstevel@tonic-gate							SCTP_STAT_INCR(sctps_pdrpbadd);
32680Sstevel@tonic-gate							return (-1);
32690Sstevel@tonic-gate						}
32700Sstevel@tonic-gate					}
32710Sstevel@tonic-gate				}
32720Sstevel@tonic-gate
32730Sstevel@tonic-gate				if (tp1->do_rtt) {
32740Sstevel@tonic-gate					/*
32750Sstevel@tonic-gate					 * this guy had a RTO calculation
32760Sstevel@tonic-gate					 * pending on it, cancel it
32770Sstevel@tonic-gate					 */
32780Sstevel@tonic-gate					if (tp1->whoTo->rto_needed == 0) {
32790Sstevel@tonic-gate						tp1->whoTo->rto_needed = 1;
32800Sstevel@tonic-gate					}
32810Sstevel@tonic-gate					tp1->do_rtt = 0;
32820Sstevel@tonic-gate				}
32830Sstevel@tonic-gate				SCTP_STAT_INCR(sctps_pdrpmark);
32840Sstevel@tonic-gate				if (tp1->sent != SCTP_DATAGRAM_RESEND)
32850Sstevel@tonic-gate					sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
32860Sstevel@tonic-gate				/*
32870Sstevel@tonic-gate				 * mark it as if we were doing a FR, since
32880Sstevel@tonic-gate				 * we will be getting gap ack reports behind
32890Sstevel@tonic-gate				 * the info from the router.
32900Sstevel@tonic-gate				 */
32910Sstevel@tonic-gate				tp1->rec.data.doing_fast_retransmit = 1;
32920Sstevel@tonic-gate				/*
32930Sstevel@tonic-gate				 * mark the tsn with what sequences can
32940Sstevel@tonic-gate				 * cause a new FR.
32950Sstevel@tonic-gate				 */
32960Sstevel@tonic-gate				if (TAILQ_EMPTY(&stcb->asoc.send_queue)) {
32970Sstevel@tonic-gate					tp1->rec.data.fast_retran_tsn = stcb->asoc.sending_seq;
32980Sstevel@tonic-gate				} else {
32990Sstevel@tonic-gate					tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq;
33000Sstevel@tonic-gate				}
33010Sstevel@tonic-gate
33020Sstevel@tonic-gate				/* restart the timer */
33030Sstevel@tonic-gate				sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
33040Sstevel@tonic-gate				    stcb, tp1->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_24);
33050Sstevel@tonic-gate				sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
33060Sstevel@tonic-gate				    stcb, tp1->whoTo);
33070Sstevel@tonic-gate
33080Sstevel@tonic-gate				/* fix counts and things */
33090Sstevel@tonic-gate				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
33100Sstevel@tonic-gate					sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PDRP,
33110Sstevel@tonic-gate					    tp1->whoTo->flight_size,
33120Sstevel@tonic-gate					    tp1->book_size,
33130Sstevel@tonic-gate					    (uintptr_t) stcb,
33140Sstevel@tonic-gate					    tp1->rec.data.TSN_seq);
33150Sstevel@tonic-gate				}
33160Sstevel@tonic-gate				if (tp1->sent < SCTP_DATAGRAM_RESEND) {
33170Sstevel@tonic-gate					sctp_flight_size_decrease(tp1);
33180Sstevel@tonic-gate					sctp_total_flight_decrease(stcb, tp1);
33190Sstevel@tonic-gate				}
33200Sstevel@tonic-gate				tp1->sent = SCTP_DATAGRAM_RESEND;
33210Sstevel@tonic-gate			} {
33220Sstevel@tonic-gate				/* audit code */
33230Sstevel@tonic-gate				unsigned int audit;
33240Sstevel@tonic-gate
33250Sstevel@tonic-gate				audit = 0;
33260Sstevel@tonic-gate				TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
33270Sstevel@tonic-gate					if (tp1->sent == SCTP_DATAGRAM_RESEND)
33280Sstevel@tonic-gate						audit++;
33290Sstevel@tonic-gate				}
33300Sstevel@tonic-gate				TAILQ_FOREACH(tp1, &stcb->asoc.control_send_queue,
33310Sstevel@tonic-gate				    sctp_next) {
33320Sstevel@tonic-gate					if (tp1->sent == SCTP_DATAGRAM_RESEND)
33330Sstevel@tonic-gate						audit++;
33340Sstevel@tonic-gate				}
33350Sstevel@tonic-gate				if (audit != stcb->asoc.sent_queue_retran_cnt) {
33360Sstevel@tonic-gate					SCTP_PRINTF("**Local Audit finds cnt:%d asoc cnt:%d\n",
33370Sstevel@tonic-gate					    audit, stcb->asoc.sent_queue_retran_cnt);
33380Sstevel@tonic-gate#ifndef SCTP_AUDITING_ENABLED
33390Sstevel@tonic-gate					stcb->asoc.sent_queue_retran_cnt = audit;
33400Sstevel@tonic-gate#endif
33410Sstevel@tonic-gate				}
33420Sstevel@tonic-gate			}
33430Sstevel@tonic-gate		}
33440Sstevel@tonic-gate		break;
33450Sstevel@tonic-gate	case SCTP_ASCONF:
33460Sstevel@tonic-gate		{
33470Sstevel@tonic-gate			struct sctp_tmit_chunk *asconf;
33480Sstevel@tonic-gate
33490Sstevel@tonic-gate			TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue,
33500Sstevel@tonic-gate			    sctp_next) {
33510Sstevel@tonic-gate				if (asconf->rec.chunk_id.id == SCTP_ASCONF) {
33520Sstevel@tonic-gate					break;
33530Sstevel@tonic-gate				}
33540Sstevel@tonic-gate			}
33550Sstevel@tonic-gate			if (asconf) {
33560Sstevel@tonic-gate				if (asconf->sent != SCTP_DATAGRAM_RESEND)
33570Sstevel@tonic-gate					sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
33580Sstevel@tonic-gate				asconf->sent = SCTP_DATAGRAM_RESEND;
33590Sstevel@tonic-gate				asconf->snd_count--;
33600Sstevel@tonic-gate			}
33610Sstevel@tonic-gate		}
33620Sstevel@tonic-gate		break;
33630Sstevel@tonic-gate	case SCTP_INITIATION:
33640Sstevel@tonic-gate		/* resend the INIT */
33650Sstevel@tonic-gate		stcb->asoc.dropped_special_cnt++;
33660Sstevel@tonic-gate		if (stcb->asoc.dropped_special_cnt < SCTP_RETRY_DROPPED_THRESH) {
33670Sstevel@tonic-gate			/*
33680Sstevel@tonic-gate			 * If we can get it in, in a few attempts we do
33690Sstevel@tonic-gate			 * this, otherwise we let the timer fire.
33700Sstevel@tonic-gate			 */
33710Sstevel@tonic-gate			sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep,
33720Sstevel@tonic-gate			    stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_25);
33730Sstevel@tonic-gate			sctp_send_initiate(stcb->sctp_ep, stcb, SCTP_SO_NOT_LOCKED);
33740Sstevel@tonic-gate		}
33750Sstevel@tonic-gate		break;
33760Sstevel@tonic-gate	case SCTP_SELECTIVE_ACK:
33770Sstevel@tonic-gate	case SCTP_NR_SELECTIVE_ACK:
33780Sstevel@tonic-gate		/* resend the sack */
33790Sstevel@tonic-gate		sctp_send_sack(stcb, SCTP_SO_NOT_LOCKED);
33800Sstevel@tonic-gate		break;
33810Sstevel@tonic-gate	case SCTP_HEARTBEAT_REQUEST:
33820Sstevel@tonic-gate		/* resend a demand HB */
33830Sstevel@tonic-gate		if ((stcb->asoc.overall_error_count + 3) < stcb->asoc.max_send_times) {
33840Sstevel@tonic-gate			/*
33850Sstevel@tonic-gate			 * Only retransmit if we KNOW we wont destroy the
33860Sstevel@tonic-gate			 * tcb
33870Sstevel@tonic-gate			 */
33880Sstevel@tonic-gate			sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
33890Sstevel@tonic-gate		}
33900Sstevel@tonic-gate		break;
33910Sstevel@tonic-gate	case SCTP_SHUTDOWN:
33920Sstevel@tonic-gate		sctp_send_shutdown(stcb, net);
33930Sstevel@tonic-gate		break;
33940Sstevel@tonic-gate	case SCTP_SHUTDOWN_ACK:
33950Sstevel@tonic-gate		sctp_send_shutdown_ack(stcb, net);
33960Sstevel@tonic-gate		break;
33970Sstevel@tonic-gate	case SCTP_COOKIE_ECHO:
33980Sstevel@tonic-gate		{
33990Sstevel@tonic-gate			struct sctp_tmit_chunk *cookie;
34000Sstevel@tonic-gate
34010Sstevel@tonic-gate			cookie = NULL;
34020Sstevel@tonic-gate			TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue,
34030Sstevel@tonic-gate			    sctp_next) {
34040Sstevel@tonic-gate				if (cookie->rec.chunk_id.id == SCTP_COOKIE_ECHO) {
34050Sstevel@tonic-gate					break;
34060Sstevel@tonic-gate				}
34070Sstevel@tonic-gate			}
34080Sstevel@tonic-gate			if (cookie) {
34090Sstevel@tonic-gate				if (cookie->sent != SCTP_DATAGRAM_RESEND)
34100Sstevel@tonic-gate					sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
34110Sstevel@tonic-gate				cookie->sent = SCTP_DATAGRAM_RESEND;
34120Sstevel@tonic-gate				sctp_stop_all_cookie_timers(stcb);
34130Sstevel@tonic-gate			}
34140Sstevel@tonic-gate		}
34150Sstevel@tonic-gate		break;
34160Sstevel@tonic-gate	case SCTP_COOKIE_ACK:
34170Sstevel@tonic-gate		sctp_send_cookie_ack(stcb);
34180Sstevel@tonic-gate		break;
34190Sstevel@tonic-gate	case SCTP_ASCONF_ACK:
34200Sstevel@tonic-gate		/* resend last asconf ack */
34210Sstevel@tonic-gate		sctp_send_asconf_ack(stcb);
34220Sstevel@tonic-gate		break;
34230Sstevel@tonic-gate	case SCTP_FORWARD_CUM_TSN:
34240Sstevel@tonic-gate		send_forward_tsn(stcb, &stcb->asoc);
34250Sstevel@tonic-gate		break;
34260Sstevel@tonic-gate		/* can't do anything with these */
34270Sstevel@tonic-gate	case SCTP_PACKET_DROPPED:
34280Sstevel@tonic-gate	case SCTP_INITIATION_ACK:	/* this should not happen */
34290Sstevel@tonic-gate	case SCTP_HEARTBEAT_ACK:
34300Sstevel@tonic-gate	case SCTP_ABORT_ASSOCIATION:
34310Sstevel@tonic-gate	case SCTP_OPERATION_ERROR:
34320Sstevel@tonic-gate	case SCTP_SHUTDOWN_COMPLETE:
34330Sstevel@tonic-gate	case SCTP_ECN_ECHO:
34340Sstevel@tonic-gate	case SCTP_ECN_CWR:
34350Sstevel@tonic-gate	default:
34360Sstevel@tonic-gate		break;
34370Sstevel@tonic-gate	}
34380Sstevel@tonic-gate	return (0);
34390Sstevel@tonic-gate}
34400Sstevel@tonic-gate
34410Sstevel@tonic-gatevoid
34420Sstevel@tonic-gatesctp_reset_in_stream(struct sctp_tcb *stcb, int number_entries, uint16_t * list)
34430Sstevel@tonic-gate{
34440Sstevel@tonic-gate	int i;
34450Sstevel@tonic-gate	uint16_t temp;
34460Sstevel@tonic-gate
34470Sstevel@tonic-gate	/*
34480Sstevel@tonic-gate	 * We set things to 0xffff since this is the last delivered sequence
34490Sstevel@tonic-gate	 * and we will be sending in 0 after the reset.
34500Sstevel@tonic-gate	 */
34510Sstevel@tonic-gate
34520Sstevel@tonic-gate	if (number_entries) {
34530Sstevel@tonic-gate		for (i = 0; i < number_entries; i++) {
34540Sstevel@tonic-gate			temp = ntohs(list[i]);
34550Sstevel@tonic-gate			if (temp >= stcb->asoc.streamincnt) {
34560Sstevel@tonic-gate				continue;
34570Sstevel@tonic-gate			}
34580Sstevel@tonic-gate			stcb->asoc.strmin[temp].last_sequence_delivered = 0xffff;
34590Sstevel@tonic-gate		}
34600Sstevel@tonic-gate	} else {
34610Sstevel@tonic-gate		list = NULL;
34620Sstevel@tonic-gate		for (i = 0; i < stcb->asoc.streamincnt; i++) {
34630Sstevel@tonic-gate			stcb->asoc.strmin[i].last_sequence_delivered = 0xffff;
34640Sstevel@tonic-gate		}
34650Sstevel@tonic-gate	}
34660Sstevel@tonic-gate	sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);
34670Sstevel@tonic-gate}
34680Sstevel@tonic-gate
34690Sstevel@tonic-gatestatic void
34700Sstevel@tonic-gatesctp_reset_out_streams(struct sctp_tcb *stcb, int number_entries, uint16_t * list)
34710Sstevel@tonic-gate{
34720Sstevel@tonic-gate	int i;
34730Sstevel@tonic-gate
34740Sstevel@tonic-gate	if (number_entries == 0) {
34750Sstevel@tonic-gate		for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
34760Sstevel@tonic-gate			stcb->asoc.strmout[i].next_sequence_sent = 0;
34770Sstevel@tonic-gate		}
34780Sstevel@tonic-gate	} else if (number_entries) {
34790Sstevel@tonic-gate		for (i = 0; i < number_entries; i++) {
34800Sstevel@tonic-gate			uint16_t temp;
34810Sstevel@tonic-gate
34820Sstevel@tonic-gate			temp = ntohs(list[i]);
34830Sstevel@tonic-gate			if (temp >= stcb->asoc.streamoutcnt) {
34840Sstevel@tonic-gate				/* no such stream */
34850Sstevel@tonic-gate				continue;
34860Sstevel@tonic-gate			}
34870Sstevel@tonic-gate			stcb->asoc.strmout[temp].next_sequence_sent = 0;
34880Sstevel@tonic-gate		}
34890Sstevel@tonic-gate	}
34900Sstevel@tonic-gate	sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_SEND, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);
34910Sstevel@tonic-gate}
34920Sstevel@tonic-gate
34930Sstevel@tonic-gate
34940Sstevel@tonic-gatestruct sctp_stream_reset_out_request *
34950Sstevel@tonic-gatesctp_find_stream_reset(struct sctp_tcb *stcb, uint32_t seq, struct sctp_tmit_chunk **bchk)
34960Sstevel@tonic-gate{
34970Sstevel@tonic-gate	struct sctp_association *asoc;
34980Sstevel@tonic-gate	struct sctp_stream_reset_out_req *req;
34990Sstevel@tonic-gate	struct sctp_stream_reset_out_request *r;
35000Sstevel@tonic-gate	struct sctp_tmit_chunk *chk;
35010Sstevel@tonic-gate	int len, clen;
35020Sstevel@tonic-gate
35030Sstevel@tonic-gate	asoc = &stcb->asoc;
35040Sstevel@tonic-gate	if (TAILQ_EMPTY(&stcb->asoc.control_send_queue)) {
35050Sstevel@tonic-gate		asoc->stream_reset_outstanding = 0;
35060Sstevel@tonic-gate		return (NULL);
35070Sstevel@tonic-gate	}
35080Sstevel@tonic-gate	if (stcb->asoc.str_reset == NULL) {
35090Sstevel@tonic-gate		asoc->stream_reset_outstanding = 0;
35100Sstevel@tonic-gate		return (NULL);
35110Sstevel@tonic-gate	}
35120Sstevel@tonic-gate	chk = stcb->asoc.str_reset;
35130Sstevel@tonic-gate	if (chk->data == NULL) {
35140Sstevel@tonic-gate		return (NULL);
35150Sstevel@tonic-gate	}
35160Sstevel@tonic-gate	if (bchk) {
35170Sstevel@tonic-gate		/* he wants a copy of the chk pointer */
35180Sstevel@tonic-gate		*bchk = chk;
35190Sstevel@tonic-gate	}
35200Sstevel@tonic-gate	clen = chk->send_size;
35210Sstevel@tonic-gate	req = mtod(chk->data, struct sctp_stream_reset_out_req *);
35220Sstevel@tonic-gate	r = &req->sr_req;
35230Sstevel@tonic-gate	if (ntohl(r->request_seq) == seq) {
35240Sstevel@tonic-gate		/* found it */
35250Sstevel@tonic-gate		return (r);
35260Sstevel@tonic-gate	}
35270Sstevel@tonic-gate	len = SCTP_SIZE32(ntohs(r->ph.param_length));
35280Sstevel@tonic-gate	if (clen > (len + (int)sizeof(struct sctp_chunkhdr))) {
35290Sstevel@tonic-gate		/* move to the next one, there can only be a max of two */
35300Sstevel@tonic-gate		r = (struct sctp_stream_reset_out_request *)((caddr_t)r + len);
35310Sstevel@tonic-gate		if (ntohl(r->request_seq) == seq) {
35320Sstevel@tonic-gate			return (r);
35330Sstevel@tonic-gate		}
35340Sstevel@tonic-gate	}
35350Sstevel@tonic-gate	/* that seq is not here */
35360Sstevel@tonic-gate	return (NULL);
35370Sstevel@tonic-gate}
35380Sstevel@tonic-gate
35390Sstevel@tonic-gatestatic void
35400Sstevel@tonic-gatesctp_clean_up_stream_reset(struct sctp_tcb *stcb)
35410Sstevel@tonic-gate{
35420Sstevel@tonic-gate	struct sctp_association *asoc;
35430Sstevel@tonic-gate	struct sctp_tmit_chunk *chk = stcb->asoc.str_reset;
35440Sstevel@tonic-gate
35450Sstevel@tonic-gate	if (stcb->asoc.str_reset == NULL) {
35460Sstevel@tonic-gate		return;
35470Sstevel@tonic-gate	}
35480Sstevel@tonic-gate	asoc = &stcb->asoc;
35490Sstevel@tonic-gate
35500Sstevel@tonic-gate	sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo, SCTP_FROM_SCTP_INPUT + SCTP_LOC_26);
35510Sstevel@tonic-gate	TAILQ_REMOVE(&asoc->control_send_queue,
35520Sstevel@tonic-gate	    chk,
35530Sstevel@tonic-gate	    sctp_next);
35540Sstevel@tonic-gate	if (chk->data) {
35550Sstevel@tonic-gate		sctp_m_freem(chk->data);
35560Sstevel@tonic-gate		chk->data = NULL;
35570Sstevel@tonic-gate	}
35580Sstevel@tonic-gate	asoc->ctrl_queue_cnt--;
35590Sstevel@tonic-gate	sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
35600Sstevel@tonic-gate	/* sa_ignore NO_NULL_CHK */
35610Sstevel@tonic-gate	stcb->asoc.str_reset = NULL;
35620Sstevel@tonic-gate}
35630Sstevel@tonic-gate
35640Sstevel@tonic-gate
35650Sstevel@tonic-gatestatic int
35660Sstevel@tonic-gatesctp_handle_stream_reset_response(struct sctp_tcb *stcb,
35670Sstevel@tonic-gate    uint32_t seq, uint32_t action,
35680Sstevel@tonic-gate    struct sctp_stream_reset_response *respin)
35690Sstevel@tonic-gate{
35700Sstevel@tonic-gate	uint16_t type;
35710Sstevel@tonic-gate	int lparm_len;
35720Sstevel@tonic-gate	struct sctp_association *asoc = &stcb->asoc;
35730Sstevel@tonic-gate	struct sctp_tmit_chunk *chk;
35740Sstevel@tonic-gate	struct sctp_stream_reset_out_request *srparam;
35750Sstevel@tonic-gate	int number_entries;
35760Sstevel@tonic-gate
35770Sstevel@tonic-gate	if (asoc->stream_reset_outstanding == 0) {
35780Sstevel@tonic-gate		/* duplicate */
35790Sstevel@tonic-gate		return (0);
35800Sstevel@tonic-gate	}
35810Sstevel@tonic-gate	if (seq == stcb->asoc.str_reset_seq_out) {
35820Sstevel@tonic-gate		srparam = sctp_find_stream_reset(stcb, seq, &chk);
35830Sstevel@tonic-gate		if (srparam) {
35840Sstevel@tonic-gate			stcb->asoc.str_reset_seq_out++;
35850Sstevel@tonic-gate			type = ntohs(srparam->ph.param_type);
35860Sstevel@tonic-gate			lparm_len = ntohs(srparam->ph.param_length);
35870Sstevel@tonic-gate			if (type == SCTP_STR_RESET_OUT_REQUEST) {
35880Sstevel@tonic-gate				number_entries = (lparm_len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t);
35890Sstevel@tonic-gate				asoc->stream_reset_out_is_outstanding = 0;
35900Sstevel@tonic-gate				if (asoc->stream_reset_outstanding)
35910Sstevel@tonic-gate					asoc->stream_reset_outstanding--;
35920Sstevel@tonic-gate				if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
35930Sstevel@tonic-gate					/* do it */
35940Sstevel@tonic-gate					sctp_reset_out_streams(stcb, number_entries, srparam->list_of_streams);
35950Sstevel@tonic-gate				} else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
35960Sstevel@tonic-gate					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
35970Sstevel@tonic-gate				} else {
35980Sstevel@tonic-gate					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_OUT, stcb, number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
35990Sstevel@tonic-gate				}
36000Sstevel@tonic-gate			} else if (type == SCTP_STR_RESET_IN_REQUEST) {
36010Sstevel@tonic-gate				/* Answered my request */
36020Sstevel@tonic-gate				number_entries = (lparm_len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t);
36030Sstevel@tonic-gate				if (asoc->stream_reset_outstanding)
36040Sstevel@tonic-gate					asoc->stream_reset_outstanding--;
36050Sstevel@tonic-gate				if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
36060Sstevel@tonic-gate					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_DENIED_IN, stcb,
36070Sstevel@tonic-gate					    number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
36080Sstevel@tonic-gate				} else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) {
36090Sstevel@tonic-gate					sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_FAILED_IN, stcb,
36100Sstevel@tonic-gate					    number_entries, srparam->list_of_streams, SCTP_SO_NOT_LOCKED);
36110Sstevel@tonic-gate				}
36120Sstevel@tonic-gate			} else if (type == SCTP_STR_RESET_ADD_OUT_STREAMS) {
36130Sstevel@tonic-gate				/* Ok we now may have more streams */
36140Sstevel@tonic-gate				int num_stream;
36150Sstevel@tonic-gate
36160Sstevel@tonic-gate				num_stream = stcb->asoc.strm_pending_add_size;
36170Sstevel@tonic-gate				if (num_stream > (stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt)) {
36180Sstevel@tonic-gate					/* TSNH */
36190Sstevel@tonic-gate					num_stream = stcb->asoc.strm_realoutsize - stcb->asoc.streamoutcnt;
36200Sstevel@tonic-gate				}
36210Sstevel@tonic-gate				stcb->asoc.strm_pending_add_size = 0;
36220Sstevel@tonic-gate				if (asoc->stream_reset_outstanding)
36230Sstevel@tonic-gate					asoc->stream_reset_outstanding--;
36240Sstevel@tonic-gate				if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
36250Sstevel@tonic-gate					/* Put the new streams into effect */
36260Sstevel@tonic-gate					stcb->asoc.streamoutcnt += num_stream;
36270Sstevel@tonic-gate					sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0);
36280Sstevel@tonic-gate				} else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
36290Sstevel@tonic-gate					sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
36300Sstevel@tonic-gate					    SCTP_STREAM_CHANGE_DENIED);
36310Sstevel@tonic-gate				} else {
36320Sstevel@tonic-gate					sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
36330Sstevel@tonic-gate					    SCTP_STREAM_CHANGE_FAILED);
36340Sstevel@tonic-gate				}
36350Sstevel@tonic-gate			} else if (type == SCTP_STR_RESET_ADD_IN_STREAMS) {
36360Sstevel@tonic-gate				if (asoc->stream_reset_outstanding)
36370Sstevel@tonic-gate					asoc->stream_reset_outstanding--;
36380Sstevel@tonic-gate				if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
36390Sstevel@tonic-gate					sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
36400Sstevel@tonic-gate					    SCTP_STREAM_CHANGE_DENIED);
36410Sstevel@tonic-gate				} else if (action != SCTP_STREAM_RESET_RESULT_PERFORMED) {
36420Sstevel@tonic-gate					sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt,
36430Sstevel@tonic-gate					    SCTP_STREAM_CHANGE_FAILED);
36440Sstevel@tonic-gate				}
36450Sstevel@tonic-gate			} else if (type == SCTP_STR_RESET_TSN_REQUEST) {
36460Sstevel@tonic-gate				/**
36470Sstevel@tonic-gate				 * a) Adopt the new in tsn.
36480Sstevel@tonic-gate				 * b) reset the map
36490Sstevel@tonic-gate				 * c) Adopt the new out-tsn
36500Sstevel@tonic-gate				 */
36510Sstevel@tonic-gate				struct sctp_stream_reset_response_tsn *resp;
36520Sstevel@tonic-gate				struct sctp_forward_tsn_chunk fwdtsn;
36530Sstevel@tonic-gate				int abort_flag = 0;
36540Sstevel@tonic-gate
36550Sstevel@tonic-gate				if (respin == NULL) {
36560Sstevel@tonic-gate					/* huh ? */
36570Sstevel@tonic-gate					return (0);
36580Sstevel@tonic-gate				}
36590Sstevel@tonic-gate				if (action == SCTP_STREAM_RESET_RESULT_PERFORMED) {
36600Sstevel@tonic-gate					resp = (struct sctp_stream_reset_response_tsn *)respin;
36610Sstevel@tonic-gate					asoc->stream_reset_outstanding--;
36620Sstevel@tonic-gate					fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk));
36630Sstevel@tonic-gate					fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN;
36640Sstevel@tonic-gate					fwdtsn.new_cumulative_tsn = htonl(ntohl(resp->senders_next_tsn) - 1);
36650Sstevel@tonic-gate					sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0);
36660Sstevel@tonic-gate					if (abort_flag) {
36670Sstevel@tonic-gate						return (1);
36680Sstevel@tonic-gate					}
36690Sstevel@tonic-gate					stcb->asoc.highest_tsn_inside_map = (ntohl(resp->senders_next_tsn) - 1);
36700Sstevel@tonic-gate					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
36710Sstevel@tonic-gate						sctp_log_map(0, 7, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
36720Sstevel@tonic-gate					}
36730Sstevel@tonic-gate					stcb->asoc.tsn_last_delivered = stcb->asoc.cumulative_tsn = stcb->asoc.highest_tsn_inside_map;
36740Sstevel@tonic-gate					stcb->asoc.mapping_array_base_tsn = ntohl(resp->senders_next_tsn);
36750Sstevel@tonic-gate					memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size);
36760Sstevel@tonic-gate
36770Sstevel@tonic-gate					stcb->asoc.highest_tsn_inside_nr_map = stcb->asoc.highest_tsn_inside_map;
36780Sstevel@tonic-gate					memset(stcb->asoc.nr_mapping_array, 0, stcb->asoc.mapping_array_size);
36790Sstevel@tonic-gate
36800Sstevel@tonic-gate					stcb->asoc.sending_seq = ntohl(resp->receivers_next_tsn);
36810Sstevel@tonic-gate					stcb->asoc.last_acked_seq = stcb->asoc.cumulative_tsn;
36820Sstevel@tonic-gate
36830Sstevel@tonic-gate					sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL);
36840Sstevel@tonic-gate					sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL);
36850Sstevel@tonic-gate					sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1), 0);
36860Sstevel@tonic-gate				} else if (action == SCTP_STREAM_RESET_RESULT_DENIED) {
36870Sstevel@tonic-gate					sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1),
36880Sstevel@tonic-gate					    SCTP_ASSOC_RESET_DENIED);
36890Sstevel@tonic-gate				} else {
36900Sstevel@tonic-gate					sctp_notify_stream_reset_tsn(stcb, stcb->asoc.sending_seq, (stcb->asoc.mapping_array_base_tsn + 1),
36910Sstevel@tonic-gate					    SCTP_ASSOC_RESET_FAILED);
36920Sstevel@tonic-gate				}
36930Sstevel@tonic-gate			}
36940Sstevel@tonic-gate			/* get rid of the request and get the request flags */
36950Sstevel@tonic-gate			if (asoc->stream_reset_outstanding == 0) {
36960Sstevel@tonic-gate				sctp_clean_up_stream_reset(stcb);
36970Sstevel@tonic-gate			}
36980Sstevel@tonic-gate		}
36990Sstevel@tonic-gate	}
37000Sstevel@tonic-gate	return (0);
37010Sstevel@tonic-gate}
37020Sstevel@tonic-gate
37030Sstevel@tonic-gatestatic void
37040Sstevel@tonic-gatesctp_handle_str_reset_request_in(struct sctp_tcb *stcb,
37050Sstevel@tonic-gate    struct sctp_tmit_chunk *chk,
37060Sstevel@tonic-gate    struct sctp_stream_reset_in_request *req, int trunc)
37070Sstevel@tonic-gate{
37080Sstevel@tonic-gate	uint32_t seq;
37090Sstevel@tonic-gate	int len, i;
37100Sstevel@tonic-gate	int number_entries;
37110Sstevel@tonic-gate	uint16_t temp;
37120Sstevel@tonic-gate
37130Sstevel@tonic-gate	/*
37140Sstevel@tonic-gate	 * peer wants me to send a str-reset to him for my outgoing seq's if
37150Sstevel@tonic-gate	 * seq_in is right.
37160Sstevel@tonic-gate	 */
37170Sstevel@tonic-gate	struct sctp_association *asoc = &stcb->asoc;
37180Sstevel@tonic-gate
37190Sstevel@tonic-gate	seq = ntohl(req->request_seq);
37200Sstevel@tonic-gate	if (asoc->str_reset_seq_in == seq) {
37210Sstevel@tonic-gate		asoc->last_reset_action[1] = asoc->last_reset_action[0];
37220Sstevel@tonic-gate		if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) {
37230Sstevel@tonic-gate			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
37240Sstevel@tonic-gate		} else if (trunc) {
37254954Sachimm			/* Can't do it, since they exceeded our buffer size  */
37264954Sachimm			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
37274954Sachimm		} else if (stcb->asoc.stream_reset_out_is_outstanding == 0) {
37284954Sachimm			len = ntohs(req->ph.param_length);
37290Sstevel@tonic-gate			number_entries = ((len - sizeof(struct sctp_stream_reset_in_request)) / sizeof(uint16_t));
37300Sstevel@tonic-gate			for (i = 0; i < number_entries; i++) {
37310Sstevel@tonic-gate				temp = ntohs(req->list_of_streams[i]);
37320Sstevel@tonic-gate				req->list_of_streams[i] = temp;
37330Sstevel@tonic-gate			}
37340Sstevel@tonic-gate			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
37350Sstevel@tonic-gate			sctp_add_stream_reset_out(chk, number_entries, req->list_of_streams,
37360Sstevel@tonic-gate			    asoc->str_reset_seq_out,
37370Sstevel@tonic-gate			    seq, (asoc->sending_seq - 1));
37380Sstevel@tonic-gate			asoc->stream_reset_out_is_outstanding = 1;
37390Sstevel@tonic-gate			asoc->str_reset = chk;
37400Sstevel@tonic-gate			sctp_timer_start(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo);
37410Sstevel@tonic-gate			stcb->asoc.stream_reset_outstanding++;
37420Sstevel@tonic-gate		} else {
37430Sstevel@tonic-gate			/* Can't do it, since we have sent one out */
37440Sstevel@tonic-gate			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS;
37450Sstevel@tonic-gate		}
37460Sstevel@tonic-gate		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
37470Sstevel@tonic-gate		asoc->str_reset_seq_in++;
37480Sstevel@tonic-gate	} else if (asoc->str_reset_seq_in - 1 == seq) {
37490Sstevel@tonic-gate		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
37500Sstevel@tonic-gate	} else if (asoc->str_reset_seq_in - 2 == seq) {
37510Sstevel@tonic-gate		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
37520Sstevel@tonic-gate	} else {
37530Sstevel@tonic-gate		sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
37540Sstevel@tonic-gate	}
37550Sstevel@tonic-gate}
37560Sstevel@tonic-gate
37570Sstevel@tonic-gatestatic int
37580Sstevel@tonic-gatesctp_handle_str_reset_request_tsn(struct sctp_tcb *stcb,
37590Sstevel@tonic-gate    struct sctp_tmit_chunk *chk,
37600Sstevel@tonic-gate    struct sctp_stream_reset_tsn_request *req)
37610Sstevel@tonic-gate{
37620Sstevel@tonic-gate	/* reset all in and out and update the tsn */
37634954Sachimm	/*
37640Sstevel@tonic-gate	 * A) reset my str-seq's on in and out. B) Select a receive next,
37650Sstevel@tonic-gate	 * and set cum-ack to it. Also process this selected number as a
37660Sstevel@tonic-gate	 * fwd-tsn as well. C) set in the response my next sending seq.
37670Sstevel@tonic-gate	 */
37680Sstevel@tonic-gate	struct sctp_forward_tsn_chunk fwdtsn;
37690Sstevel@tonic-gate	struct sctp_association *asoc = &stcb->asoc;
37700Sstevel@tonic-gate	int abort_flag = 0;
37710Sstevel@tonic-gate	uint32_t seq;
37720Sstevel@tonic-gate
37730Sstevel@tonic-gate	seq = ntohl(req->request_seq);
37740Sstevel@tonic-gate	if (asoc->str_reset_seq_in == seq) {
37750Sstevel@tonic-gate		asoc->last_reset_action[1] = stcb->asoc.last_reset_action[0];
37760Sstevel@tonic-gate		if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) {
37770Sstevel@tonic-gate			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
37780Sstevel@tonic-gate		} else {
37790Sstevel@tonic-gate			fwdtsn.ch.chunk_length = htons(sizeof(struct sctp_forward_tsn_chunk));
37800Sstevel@tonic-gate			fwdtsn.ch.chunk_type = SCTP_FORWARD_CUM_TSN;
37810Sstevel@tonic-gate			fwdtsn.ch.chunk_flags = 0;
37820Sstevel@tonic-gate			fwdtsn.new_cumulative_tsn = htonl(stcb->asoc.highest_tsn_inside_map + 1);
37830Sstevel@tonic-gate			sctp_handle_forward_tsn(stcb, &fwdtsn, &abort_flag, NULL, 0);
37840Sstevel@tonic-gate			if (abort_flag) {
37850Sstevel@tonic-gate				return (1);
37860Sstevel@tonic-gate			}
37870Sstevel@tonic-gate			asoc->highest_tsn_inside_map += SCTP_STREAM_RESET_TSN_DELTA;
37880Sstevel@tonic-gate			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MAP_LOGGING_ENABLE) {
37890Sstevel@tonic-gate				sctp_log_map(0, 10, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
37900Sstevel@tonic-gate			}
37910Sstevel@tonic-gate			asoc->tsn_last_delivered = asoc->cumulative_tsn = asoc->highest_tsn_inside_map;
37920Sstevel@tonic-gate			asoc->mapping_array_base_tsn = asoc->highest_tsn_inside_map + 1;
37930Sstevel@tonic-gate			memset(asoc->mapping_array, 0, asoc->mapping_array_size);
37940Sstevel@tonic-gate			asoc->highest_tsn_inside_nr_map = asoc->highest_tsn_inside_map;
37950Sstevel@tonic-gate			memset(asoc->nr_mapping_array, 0, asoc->mapping_array_size);
37960Sstevel@tonic-gate			atomic_add_int(&asoc->sending_seq, 1);
37970Sstevel@tonic-gate			/* save off historical data for retrans */
37980Sstevel@tonic-gate			asoc->last_sending_seq[1] = asoc->last_sending_seq[0];
37990Sstevel@tonic-gate			asoc->last_sending_seq[0] = asoc->sending_seq;
38000Sstevel@tonic-gate			asoc->last_base_tsnsent[1] = asoc->last_base_tsnsent[0];
38014954Sachimm			asoc->last_base_tsnsent[0] = asoc->mapping_array_base_tsn;
38020Sstevel@tonic-gate			sctp_reset_out_streams(stcb, 0, (uint16_t *) NULL);
38030Sstevel@tonic-gate			sctp_reset_in_stream(stcb, 0, (uint16_t *) NULL);
38040Sstevel@tonic-gate			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
38050Sstevel@tonic-gate			sctp_notify_stream_reset_tsn(stcb, asoc->sending_seq, (asoc->mapping_array_base_tsn + 1), 0);
38060Sstevel@tonic-gate		}
38070Sstevel@tonic-gate		sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0],
38080Sstevel@tonic-gate		    asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]);
38090Sstevel@tonic-gate		asoc->str_reset_seq_in++;
38100Sstevel@tonic-gate	} else if (asoc->str_reset_seq_in - 1 == seq) {
38110Sstevel@tonic-gate		sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[0],
38120Sstevel@tonic-gate		    asoc->last_sending_seq[0], asoc->last_base_tsnsent[0]);
38130Sstevel@tonic-gate	} else if (asoc->str_reset_seq_in - 2 == seq) {
38140Sstevel@tonic-gate		sctp_add_stream_reset_result_tsn(chk, seq, asoc->last_reset_action[1],
38154954Sachimm		    asoc->last_sending_seq[1], asoc->last_base_tsnsent[1]);
38160Sstevel@tonic-gate	} else {
38170Sstevel@tonic-gate		sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
38180Sstevel@tonic-gate	}
38190Sstevel@tonic-gate	return (0);
38200Sstevel@tonic-gate}
38210Sstevel@tonic-gate
38224954Sachimmstatic void
38230Sstevel@tonic-gatesctp_handle_str_reset_request_out(struct sctp_tcb *stcb,
38240Sstevel@tonic-gate    struct sctp_tmit_chunk *chk,
38250Sstevel@tonic-gate    struct sctp_stream_reset_out_request *req, int trunc)
38260Sstevel@tonic-gate{
38270Sstevel@tonic-gate	uint32_t seq, tsn;
38280Sstevel@tonic-gate	int number_entries, len;
38290Sstevel@tonic-gate	struct sctp_association *asoc = &stcb->asoc;
38300Sstevel@tonic-gate
38310Sstevel@tonic-gate	seq = ntohl(req->request_seq);
38320Sstevel@tonic-gate
38330Sstevel@tonic-gate	/* now if its not a duplicate we process it */
38340Sstevel@tonic-gate	if (asoc->str_reset_seq_in == seq) {
38350Sstevel@tonic-gate		len = ntohs(req->ph.param_length);
38360Sstevel@tonic-gate		number_entries = ((len - sizeof(struct sctp_stream_reset_out_request)) / sizeof(uint16_t));
38370Sstevel@tonic-gate		/*
38380Sstevel@tonic-gate		 * the sender is resetting, handle the list issue.. we must
38390Sstevel@tonic-gate		 * a) verify if we can do the reset, if so no problem b) If
38400Sstevel@tonic-gate		 * we can't do the reset we must copy the request. c) queue
38410Sstevel@tonic-gate		 * it, and setup the data in processor to trigger it off
38420Sstevel@tonic-gate		 * when needed and dequeue all the queued data.
38430Sstevel@tonic-gate		 */
38440Sstevel@tonic-gate		tsn = ntohl(req->send_reset_at_tsn);
38450Sstevel@tonic-gate
38460Sstevel@tonic-gate		/* move the reset action back one */
38470Sstevel@tonic-gate		asoc->last_reset_action[1] = asoc->last_reset_action[0];
38480Sstevel@tonic-gate		if (!(asoc->local_strreset_support & SCTP_ENABLE_RESET_STREAM_REQ)) {
38490Sstevel@tonic-gate			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
38500Sstevel@tonic-gate		} else if (trunc) {
38510Sstevel@tonic-gate			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
38520Sstevel@tonic-gate		} else if (SCTP_TSN_GE(asoc->cumulative_tsn, tsn)) {
38530Sstevel@tonic-gate			/* we can do it now */
38540Sstevel@tonic-gate			sctp_reset_in_stream(stcb, number_entries, req->list_of_streams);
38550Sstevel@tonic-gate			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
38560Sstevel@tonic-gate		} else {
38570Sstevel@tonic-gate			/*
38580Sstevel@tonic-gate			 * we must queue it up and thus wait for the TSN's
38590Sstevel@tonic-gate			 * to arrive that are at or before tsn
38600Sstevel@tonic-gate			 */
38610Sstevel@tonic-gate			struct sctp_stream_reset_list *liste;
38620Sstevel@tonic-gate			int siz;
38630Sstevel@tonic-gate
38640Sstevel@tonic-gate			siz = sizeof(struct sctp_stream_reset_list) + (number_entries * sizeof(uint16_t));
38650Sstevel@tonic-gate			SCTP_MALLOC(liste, struct sctp_stream_reset_list *,
38660Sstevel@tonic-gate			    siz, SCTP_M_STRESET);
38670Sstevel@tonic-gate			if (liste == NULL) {
38680Sstevel@tonic-gate				/* gak out of memory */
38694954Sachimm				asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
38700Sstevel@tonic-gate				sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
38710Sstevel@tonic-gate				return;
38720Sstevel@tonic-gate			}
38730Sstevel@tonic-gate			liste->tsn = tsn;
38740Sstevel@tonic-gate			liste->number_entries = number_entries;
38750Sstevel@tonic-gate			memcpy(&liste->req, req,
38760Sstevel@tonic-gate			    (sizeof(struct sctp_stream_reset_out_request) + (number_entries * sizeof(uint16_t))));
38770Sstevel@tonic-gate			TAILQ_INSERT_TAIL(&asoc->resetHead, liste, next_resp);
38780Sstevel@tonic-gate			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
38790Sstevel@tonic-gate		}
38804954Sachimm		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
38814954Sachimm		asoc->str_reset_seq_in++;
38820Sstevel@tonic-gate	} else if ((asoc->str_reset_seq_in - 1) == seq) {
38830Sstevel@tonic-gate		/*
38840Sstevel@tonic-gate		 * one seq back, just echo back last action since my
38850Sstevel@tonic-gate		 * response was lost.
38860Sstevel@tonic-gate		 */
38870Sstevel@tonic-gate		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
38880Sstevel@tonic-gate	} else if ((asoc->str_reset_seq_in - 2) == seq) {
38890Sstevel@tonic-gate		/*
38900Sstevel@tonic-gate		 * two seq back, just echo back last action since my
38914954Sachimm		 * response was lost.
38924954Sachimm		 */
38930Sstevel@tonic-gate		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
38940Sstevel@tonic-gate	} else {
38950Sstevel@tonic-gate		sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
38960Sstevel@tonic-gate	}
38970Sstevel@tonic-gate}
38984954Sachimm
38994954Sachimmstatic void
39000Sstevel@tonic-gatesctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk,
39010Sstevel@tonic-gate    struct sctp_stream_reset_add_strm *str_add)
39020Sstevel@tonic-gate{
39030Sstevel@tonic-gate	/*
39040Sstevel@tonic-gate	 * Peer is requesting to add more streams. If its within our
39050Sstevel@tonic-gate	 * max-streams we will allow it.
39060Sstevel@tonic-gate	 */
39070Sstevel@tonic-gate	uint32_t num_stream, i;
39080Sstevel@tonic-gate	uint32_t seq;
39094954Sachimm	struct sctp_association *asoc = &stcb->asoc;
39104954Sachimm	struct sctp_queued_to_read *ctl, *nctl;
39110Sstevel@tonic-gate
39120Sstevel@tonic-gate	/* Get the number. */
39130Sstevel@tonic-gate	seq = ntohl(str_add->request_seq);
39140Sstevel@tonic-gate	num_stream = ntohs(str_add->number_of_streams);
39154954Sachimm	/* Now what would be the new total? */
39164954Sachimm	if (asoc->str_reset_seq_in == seq) {
39170Sstevel@tonic-gate		num_stream += stcb->asoc.streamincnt;
39180Sstevel@tonic-gate		stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0];
39190Sstevel@tonic-gate		if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) {
39200Sstevel@tonic-gate			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
39210Sstevel@tonic-gate		} else if ((num_stream > stcb->asoc.max_inbound_streams) ||
39220Sstevel@tonic-gate		    (num_stream > 0xffff)) {
39230Sstevel@tonic-gate			/* We must reject it they ask for to many */
39240Sstevel@tonic-gate	denied:
39250Sstevel@tonic-gate			stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
39260Sstevel@tonic-gate		} else {
39270Sstevel@tonic-gate			/* Ok, we can do that :-) */
39280Sstevel@tonic-gate			struct sctp_stream_in *oldstrm;
39290Sstevel@tonic-gate
39300Sstevel@tonic-gate			/* save off the old */
39310Sstevel@tonic-gate			oldstrm = stcb->asoc.strmin;
3932			SCTP_MALLOC(stcb->asoc.strmin, struct sctp_stream_in *,
3933			    (num_stream * sizeof(struct sctp_stream_in)),
3934			    SCTP_M_STRMI);
3935			if (stcb->asoc.strmin == NULL) {
3936				stcb->asoc.strmin = oldstrm;
3937				goto denied;
3938			}
3939			/* copy off the old data */
3940			for (i = 0; i < stcb->asoc.streamincnt; i++) {
3941				TAILQ_INIT(&stcb->asoc.strmin[i].inqueue);
3942				stcb->asoc.strmin[i].stream_no = i;
3943				stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered;
3944				stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started;
3945				/* now anything on those queues? */
3946				TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next, nctl) {
3947					TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next);
3948					TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next);
3949				}
3950			}
3951			/* Init the new streams */
3952			for (i = stcb->asoc.streamincnt; i < num_stream; i++) {
3953				TAILQ_INIT(&stcb->asoc.strmin[i].inqueue);
3954				stcb->asoc.strmin[i].stream_no = i;
3955				stcb->asoc.strmin[i].last_sequence_delivered = 0xffff;
3956				stcb->asoc.strmin[i].delivery_started = 0;
3957			}
3958			SCTP_FREE(oldstrm, SCTP_M_STRMI);
3959			/* update the size */
3960			stcb->asoc.streamincnt = num_stream;
3961			stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
3962			sctp_notify_stream_reset_add(stcb, stcb->asoc.streamincnt, stcb->asoc.streamoutcnt, 0);
3963		}
3964		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
3965		asoc->str_reset_seq_in++;
3966	} else if ((asoc->str_reset_seq_in - 1) == seq) {
3967		/*
3968		 * one seq back, just echo back last action since my
3969		 * response was lost.
3970		 */
3971		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
3972	} else if ((asoc->str_reset_seq_in - 2) == seq) {
3973		/*
3974		 * two seq back, just echo back last action since my
3975		 * response was lost.
3976		 */
3977		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
3978	} else {
3979		sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
3980
3981	}
3982}
3983
3984static void
3985sctp_handle_str_reset_add_out_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *chk,
3986    struct sctp_stream_reset_add_strm *str_add)
3987{
3988	/*
3989	 * Peer is requesting to add more streams. If its within our
3990	 * max-streams we will allow it.
3991	 */
3992	uint16_t num_stream;
3993	uint32_t seq;
3994	struct sctp_association *asoc = &stcb->asoc;
3995
3996	/* Get the number. */
3997	seq = ntohl(str_add->request_seq);
3998	num_stream = ntohs(str_add->number_of_streams);
3999	/* Now what would be the new total? */
4000	if (asoc->str_reset_seq_in == seq) {
4001		stcb->asoc.last_reset_action[1] = stcb->asoc.last_reset_action[0];
4002		if (!(asoc->local_strreset_support & SCTP_ENABLE_CHANGE_ASSOC_REQ)) {
4003			asoc->last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
4004		} else if (stcb->asoc.stream_reset_outstanding) {
4005			/* We must reject it we have something pending */
4006			stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_ERR_IN_PROGRESS;
4007		} else {
4008			/* Ok, we can do that :-) */
4009			int mychk;
4010
4011			mychk = stcb->asoc.streamoutcnt;
4012			mychk += num_stream;
4013			if (mychk < 0x10000) {
4014				stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_PERFORMED;
4015				if (sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, 1, num_stream, 0, 1)) {
4016					stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
4017				}
4018			} else {
4019				stcb->asoc.last_reset_action[0] = SCTP_STREAM_RESET_RESULT_DENIED;
4020			}
4021		}
4022		sctp_add_stream_reset_result(chk, seq, stcb->asoc.last_reset_action[0]);
4023		asoc->str_reset_seq_in++;
4024	} else if ((asoc->str_reset_seq_in - 1) == seq) {
4025		/*
4026		 * one seq back, just echo back last action since my
4027		 * response was lost.
4028		 */
4029		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[0]);
4030	} else if ((asoc->str_reset_seq_in - 2) == seq) {
4031		/*
4032		 * two seq back, just echo back last action since my
4033		 * response was lost.
4034		 */
4035		sctp_add_stream_reset_result(chk, seq, asoc->last_reset_action[1]);
4036	} else {
4037		sctp_add_stream_reset_result(chk, seq, SCTP_STREAM_RESET_RESULT_ERR_BAD_SEQNO);
4038	}
4039}
4040
4041#ifdef __GNUC__
4042__attribute__((noinline))
4043#endif
4044	static int
4045	    sctp_handle_stream_reset(struct sctp_tcb *stcb, struct mbuf *m, int offset,
4046        struct sctp_stream_reset_out_req *sr_req)
4047{
4048	int chk_length, param_len, ptype;
4049	struct sctp_paramhdr pstore;
4050	uint8_t cstore[SCTP_CHUNK_BUFFER_SIZE];
4051	uint32_t seq = 0;
4052	int num_req = 0;
4053	int trunc = 0;
4054	struct sctp_tmit_chunk *chk;
4055	struct sctp_chunkhdr *ch;
4056	struct sctp_paramhdr *ph;
4057	int ret_code = 0;
4058	int num_param = 0;
4059
4060	/* now it may be a reset or a reset-response */
4061	chk_length = ntohs(sr_req->ch.chunk_length);
4062
4063	/* setup for adding the response */
4064	sctp_alloc_a_chunk(stcb, chk);
4065	if (chk == NULL) {
4066		return (ret_code);
4067	}
4068	chk->rec.chunk_id.id = SCTP_STREAM_RESET;
4069	chk->rec.chunk_id.can_take_data = 0;
4070	chk->asoc = &stcb->asoc;
4071	chk->no_fr_allowed = 0;
4072	chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr);
4073	chk->book_size_scale = 0;
4074	chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
4075	if (chk->data == NULL) {
4076strres_nochunk:
4077		if (chk->data) {
4078			sctp_m_freem(chk->data);
4079			chk->data = NULL;
4080		}
4081		sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
4082		return (ret_code);
4083	}
4084	SCTP_BUF_RESV_UF(chk->data, SCTP_MIN_OVERHEAD);
4085
4086	/* setup chunk parameters */
4087	chk->sent = SCTP_DATAGRAM_UNSENT;
4088	chk->snd_count = 0;
4089	chk->whoTo = NULL;
4090
4091	ch = mtod(chk->data, struct sctp_chunkhdr *);
4092	ch->chunk_type = SCTP_STREAM_RESET;
4093	ch->chunk_flags = 0;
4094	ch->chunk_length = htons(chk->send_size);
4095	SCTP_BUF_LEN(chk->data) = SCTP_SIZE32(chk->send_size);
4096	offset += sizeof(struct sctp_chunkhdr);
4097	while ((size_t)chk_length >= sizeof(struct sctp_stream_reset_tsn_request)) {
4098		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, sizeof(pstore), (uint8_t *) & pstore);
4099		if (ph == NULL)
4100			break;
4101		param_len = ntohs(ph->param_length);
4102		if (param_len < (int)sizeof(struct sctp_stream_reset_tsn_request)) {
4103			/* bad param */
4104			break;
4105		}
4106		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset, min(param_len, (int)sizeof(cstore)),
4107		    (uint8_t *) & cstore);
4108		ptype = ntohs(ph->param_type);
4109		num_param++;
4110		if (param_len > (int)sizeof(cstore)) {
4111			trunc = 1;
4112		} else {
4113			trunc = 0;
4114		}
4115		if (num_param > SCTP_MAX_RESET_PARAMS) {
4116			/* hit the max of parameters already sorry.. */
4117			break;
4118		}
4119		if (ptype == SCTP_STR_RESET_OUT_REQUEST) {
4120			struct sctp_stream_reset_out_request *req_out;
4121
4122			req_out = (struct sctp_stream_reset_out_request *)ph;
4123			num_req++;
4124			if (stcb->asoc.stream_reset_outstanding) {
4125				seq = ntohl(req_out->response_seq);
4126				if (seq == stcb->asoc.str_reset_seq_out) {
4127					/* implicit ack */
4128					(void)sctp_handle_stream_reset_response(stcb, seq, SCTP_STREAM_RESET_RESULT_PERFORMED, NULL);
4129				}
4130			}
4131			sctp_handle_str_reset_request_out(stcb, chk, req_out, trunc);
4132		} else if (ptype == SCTP_STR_RESET_ADD_OUT_STREAMS) {
4133			struct sctp_stream_reset_add_strm *str_add;
4134
4135			str_add = (struct sctp_stream_reset_add_strm *)ph;
4136			num_req++;
4137			sctp_handle_str_reset_add_strm(stcb, chk, str_add);
4138		} else if (ptype == SCTP_STR_RESET_ADD_IN_STREAMS) {
4139			struct sctp_stream_reset_add_strm *str_add;
4140
4141			str_add = (struct sctp_stream_reset_add_strm *)ph;
4142			num_req++;
4143			sctp_handle_str_reset_add_out_strm(stcb, chk, str_add);
4144		} else if (ptype == SCTP_STR_RESET_IN_REQUEST) {
4145			struct sctp_stream_reset_in_request *req_in;
4146
4147			num_req++;
4148			req_in = (struct sctp_stream_reset_in_request *)ph;
4149			sctp_handle_str_reset_request_in(stcb, chk, req_in, trunc);
4150		} else if (ptype == SCTP_STR_RESET_TSN_REQUEST) {
4151			struct sctp_stream_reset_tsn_request *req_tsn;
4152
4153			num_req++;
4154			req_tsn = (struct sctp_stream_reset_tsn_request *)ph;
4155			if (sctp_handle_str_reset_request_tsn(stcb, chk, req_tsn)) {
4156				ret_code = 1;
4157				goto strres_nochunk;
4158			}
4159			/* no more */
4160			break;
4161		} else if (ptype == SCTP_STR_RESET_RESPONSE) {
4162			struct sctp_stream_reset_response *resp;
4163			uint32_t result;
4164
4165			resp = (struct sctp_stream_reset_response *)ph;
4166			seq = ntohl(resp->response_seq);
4167			result = ntohl(resp->result);
4168			if (sctp_handle_stream_reset_response(stcb, seq, result, resp)) {
4169				ret_code = 1;
4170				goto strres_nochunk;
4171			}
4172		} else {
4173			break;
4174		}
4175		offset += SCTP_SIZE32(param_len);
4176		chk_length -= SCTP_SIZE32(param_len);
4177	}
4178	if (num_req == 0) {
4179		/* we have no response free the stuff */
4180		goto strres_nochunk;
4181	}
4182	/* ok we have a chunk to link in */
4183	TAILQ_INSERT_TAIL(&stcb->asoc.control_send_queue,
4184	    chk,
4185	    sctp_next);
4186	stcb->asoc.ctrl_queue_cnt++;
4187	return (ret_code);
4188}
4189
4190/*
4191 * Handle a router or endpoints report of a packet loss, there are two ways
4192 * to handle this, either we get the whole packet and must disect it
4193 * ourselves (possibly with truncation and or corruption) or it is a summary
4194 * from a middle box that did the disectting for us.
4195 */
4196static void
4197sctp_handle_packet_dropped(struct sctp_pktdrop_chunk *cp,
4198    struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t limit)
4199{
4200	uint32_t bottle_bw, on_queue;
4201	uint16_t trunc_len;
4202	unsigned int chlen;
4203	unsigned int at;
4204	struct sctp_chunk_desc desc;
4205	struct sctp_chunkhdr *ch;
4206
4207	chlen = ntohs(cp->ch.chunk_length);
4208	chlen -= sizeof(struct sctp_pktdrop_chunk);
4209	/* XXX possible chlen underflow */
4210	if (chlen == 0) {
4211		ch = NULL;
4212		if (cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)
4213			SCTP_STAT_INCR(sctps_pdrpbwrpt);
4214	} else {
4215		ch = (struct sctp_chunkhdr *)(cp->data + sizeof(struct sctphdr));
4216		chlen -= sizeof(struct sctphdr);
4217		/* XXX possible chlen underflow */
4218		memset(&desc, 0, sizeof(desc));
4219	}
4220	trunc_len = (uint16_t) ntohs(cp->trunc_len);
4221	if (trunc_len > limit) {
4222		trunc_len = limit;
4223	}
4224	/* now the chunks themselves */
4225	while ((ch != NULL) && (chlen >= sizeof(struct sctp_chunkhdr))) {
4226		desc.chunk_type = ch->chunk_type;
4227		/* get amount we need to move */
4228		at = ntohs(ch->chunk_length);
4229		if (at < sizeof(struct sctp_chunkhdr)) {
4230			/* corrupt chunk, maybe at the end? */
4231			SCTP_STAT_INCR(sctps_pdrpcrupt);
4232			break;
4233		}
4234		if (trunc_len == 0) {
4235			/* we are supposed to have all of it */
4236			if (at > chlen) {
4237				/* corrupt skip it */
4238				SCTP_STAT_INCR(sctps_pdrpcrupt);
4239				break;
4240			}
4241		} else {
4242			/* is there enough of it left ? */
4243			if (desc.chunk_type == SCTP_DATA) {
4244				if (chlen < (sizeof(struct sctp_data_chunk) +
4245				    sizeof(desc.data_bytes))) {
4246					break;
4247				}
4248			} else {
4249				if (chlen < sizeof(struct sctp_chunkhdr)) {
4250					break;
4251				}
4252			}
4253		}
4254		if (desc.chunk_type == SCTP_DATA) {
4255			/* can we get out the tsn? */
4256			if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX))
4257				SCTP_STAT_INCR(sctps_pdrpmbda);
4258
4259			if (chlen >= (sizeof(struct sctp_data_chunk) + sizeof(uint32_t))) {
4260				/* yep */
4261				struct sctp_data_chunk *dcp;
4262				uint8_t *ddp;
4263				unsigned int iii;
4264
4265				dcp = (struct sctp_data_chunk *)ch;
4266				ddp = (uint8_t *) (dcp + 1);
4267				for (iii = 0; iii < sizeof(desc.data_bytes); iii++) {
4268					desc.data_bytes[iii] = ddp[iii];
4269				}
4270				desc.tsn_ifany = dcp->dp.tsn;
4271			} else {
4272				/* nope we are done. */
4273				SCTP_STAT_INCR(sctps_pdrpnedat);
4274				break;
4275			}
4276		} else {
4277			if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX))
4278				SCTP_STAT_INCR(sctps_pdrpmbct);
4279		}
4280
4281		if (process_chunk_drop(stcb, &desc, net, cp->ch.chunk_flags)) {
4282			SCTP_STAT_INCR(sctps_pdrppdbrk);
4283			break;
4284		}
4285		if (SCTP_SIZE32(at) > chlen) {
4286			break;
4287		}
4288		chlen -= SCTP_SIZE32(at);
4289		if (chlen < sizeof(struct sctp_chunkhdr)) {
4290			/* done, none left */
4291			break;
4292		}
4293		ch = (struct sctp_chunkhdr *)((caddr_t)ch + SCTP_SIZE32(at));
4294	}
4295	/* Now update any rwnd --- possibly */
4296	if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) == 0) {
4297		/* From a peer, we get a rwnd report */
4298		uint32_t a_rwnd;
4299
4300		SCTP_STAT_INCR(sctps_pdrpfehos);
4301
4302		bottle_bw = ntohl(cp->bottle_bw);
4303		on_queue = ntohl(cp->current_onq);
4304		if (bottle_bw && on_queue) {
4305			/* a rwnd report is in here */
4306			if (bottle_bw > on_queue)
4307				a_rwnd = bottle_bw - on_queue;
4308			else
4309				a_rwnd = 0;
4310
4311			if (a_rwnd == 0)
4312				stcb->asoc.peers_rwnd = 0;
4313			else {
4314				if (a_rwnd > stcb->asoc.total_flight) {
4315					stcb->asoc.peers_rwnd =
4316					    a_rwnd - stcb->asoc.total_flight;
4317				} else {
4318					stcb->asoc.peers_rwnd = 0;
4319				}
4320				if (stcb->asoc.peers_rwnd <
4321				    stcb->sctp_ep->sctp_ep.sctp_sws_sender) {
4322					/* SWS sender side engages */
4323					stcb->asoc.peers_rwnd = 0;
4324				}
4325			}
4326		}
4327	} else {
4328		SCTP_STAT_INCR(sctps_pdrpfmbox);
4329	}
4330
4331	/* now middle boxes in sat networks get a cwnd bump */
4332	if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) &&
4333	    (stcb->asoc.sat_t3_loss_recovery == 0) &&
4334	    (stcb->asoc.sat_network)) {
4335		/*
4336		 * This is debateable but for sat networks it makes sense
4337		 * Note if a T3 timer has went off, we will prohibit any
4338		 * changes to cwnd until we exit the t3 loss recovery.
4339		 */
4340		stcb->asoc.cc_functions.sctp_cwnd_update_after_packet_dropped(stcb,
4341		    net, cp, &bottle_bw, &on_queue);
4342	}
4343}
4344
4345/*
4346 * handles all control chunks in a packet inputs: - m: mbuf chain, assumed to
4347 * still contain IP/SCTP header - stcb: is the tcb found for this packet -
4348 * offset: offset into the mbuf chain to first chunkhdr - length: is the
4349 * length of the complete packet outputs: - length: modified to remaining
4350 * length after control processing - netp: modified to new sctp_nets after
4351 * cookie-echo processing - return NULL to discard the packet (ie. no asoc,
4352 * bad packet,...) otherwise return the tcb for this packet
4353 */
4354#ifdef __GNUC__
4355__attribute__((noinline))
4356#endif
4357	static struct sctp_tcb *
4358	         sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
4359             struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp,
4360             struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen,
4361             uint32_t vrf_id, uint16_t port)
4362{
4363	struct sctp_association *asoc;
4364	uint32_t vtag_in;
4365	int num_chunks = 0;	/* number of control chunks processed */
4366	uint32_t chk_length;
4367	int ret;
4368	int abort_no_unlock = 0;
4369	int ecne_seen = 0;
4370
4371	/*
4372	 * How big should this be, and should it be alloc'd? Lets try the
4373	 * d-mtu-ceiling for now (2k) and that should hopefully work ...
4374	 * until we get into jumbo grams and such..
4375	 */
4376	uint8_t chunk_buf[SCTP_CHUNK_BUFFER_SIZE];
4377	struct sctp_tcb *locked_tcb = stcb;
4378	int got_auth = 0;
4379	uint32_t auth_offset = 0, auth_len = 0;
4380	int auth_skipped = 0;
4381	int asconf_cnt = 0;
4382
4383#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4384	struct socket *so;
4385
4386#endif
4387
4388	SCTPDBG(SCTP_DEBUG_INPUT1, "sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n",
4389	    iphlen, *offset, length, stcb);
4390
4391	/* validate chunk header length... */
4392	if (ntohs(ch->chunk_length) < sizeof(*ch)) {
4393		SCTPDBG(SCTP_DEBUG_INPUT1, "Invalid header length %d\n",
4394		    ntohs(ch->chunk_length));
4395		if (locked_tcb) {
4396			SCTP_TCB_UNLOCK(locked_tcb);
4397		}
4398		return (NULL);
4399	}
4400	/*
4401	 * validate the verification tag
4402	 */
4403	vtag_in = ntohl(sh->v_tag);
4404
4405	if (locked_tcb) {
4406		SCTP_TCB_LOCK_ASSERT(locked_tcb);
4407	}
4408	if (ch->chunk_type == SCTP_INITIATION) {
4409		SCTPDBG(SCTP_DEBUG_INPUT1, "Its an INIT of len:%d vtag:%x\n",
4410		    ntohs(ch->chunk_length), vtag_in);
4411		if (vtag_in != 0) {
4412			/* protocol error- silently discard... */
4413			SCTP_STAT_INCR(sctps_badvtag);
4414			if (locked_tcb) {
4415				SCTP_TCB_UNLOCK(locked_tcb);
4416			}
4417			return (NULL);
4418		}
4419	} else if (ch->chunk_type != SCTP_COOKIE_ECHO) {
4420		/*
4421		 * If there is no stcb, skip the AUTH chunk and process
4422		 * later after a stcb is found (to validate the lookup was
4423		 * valid.
4424		 */
4425		if ((ch->chunk_type == SCTP_AUTHENTICATION) &&
4426		    (stcb == NULL) &&
4427		    !SCTP_BASE_SYSCTL(sctp_auth_disable)) {
4428			/* save this chunk for later processing */
4429			auth_skipped = 1;
4430			auth_offset = *offset;
4431			auth_len = ntohs(ch->chunk_length);
4432
4433			/* (temporarily) move past this chunk */
4434			*offset += SCTP_SIZE32(auth_len);
4435			if (*offset >= length) {
4436				/* no more data left in the mbuf chain */
4437				*offset = length;
4438				if (locked_tcb) {
4439					SCTP_TCB_UNLOCK(locked_tcb);
4440				}
4441				return (NULL);
4442			}
4443			ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
4444			    sizeof(struct sctp_chunkhdr), chunk_buf);
4445		}
4446		if (ch == NULL) {
4447			/* Help */
4448			*offset = length;
4449			if (locked_tcb) {
4450				SCTP_TCB_UNLOCK(locked_tcb);
4451			}
4452			return (NULL);
4453		}
4454		if (ch->chunk_type == SCTP_COOKIE_ECHO) {
4455			goto process_control_chunks;
4456		}
4457		/*
4458		 * first check if it's an ASCONF with an unknown src addr we
4459		 * need to look inside to find the association
4460		 */
4461		if (ch->chunk_type == SCTP_ASCONF && stcb == NULL) {
4462			struct sctp_chunkhdr *asconf_ch = ch;
4463			uint32_t asconf_offset = 0, asconf_len = 0;
4464
4465			/* inp's refcount may be reduced */
4466			SCTP_INP_INCR_REF(inp);
4467
4468			asconf_offset = *offset;
4469			do {
4470				asconf_len = ntohs(asconf_ch->chunk_length);
4471				if (asconf_len < sizeof(struct sctp_asconf_paramhdr))
4472					break;
4473				stcb = sctp_findassociation_ep_asconf(m,
4474				    *offset, sh, &inp, netp, vrf_id);
4475				if (stcb != NULL)
4476					break;
4477				asconf_offset += SCTP_SIZE32(asconf_len);
4478				asconf_ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, asconf_offset,
4479				    sizeof(struct sctp_chunkhdr), chunk_buf);
4480			} while (asconf_ch != NULL && asconf_ch->chunk_type == SCTP_ASCONF);
4481			if (stcb == NULL) {
4482				/*
4483				 * reduce inp's refcount if not reduced in
4484				 * sctp_findassociation_ep_asconf().
4485				 */
4486				SCTP_INP_DECR_REF(inp);
4487			} else {
4488				locked_tcb = stcb;
4489			}
4490
4491			/* now go back and verify any auth chunk to be sure */
4492			if (auth_skipped && (stcb != NULL)) {
4493				struct sctp_auth_chunk *auth;
4494
4495				auth = (struct sctp_auth_chunk *)
4496				    sctp_m_getptr(m, auth_offset,
4497				    auth_len, chunk_buf);
4498				got_auth = 1;
4499				auth_skipped = 0;
4500				if ((auth == NULL) || sctp_handle_auth(stcb, auth, m,
4501				    auth_offset)) {
4502					/* auth HMAC failed so dump it */
4503					*offset = length;
4504					if (locked_tcb) {
4505						SCTP_TCB_UNLOCK(locked_tcb);
4506					}
4507					return (NULL);
4508				} else {
4509					/* remaining chunks are HMAC checked */
4510					stcb->asoc.authenticated = 1;
4511				}
4512			}
4513		}
4514		if (stcb == NULL) {
4515			/* no association, so it's out of the blue... */
4516			sctp_handle_ootb(m, iphlen, *offset, sh, inp, NULL,
4517			    vrf_id, port);
4518			*offset = length;
4519			if (locked_tcb) {
4520				SCTP_TCB_UNLOCK(locked_tcb);
4521			}
4522			return (NULL);
4523		}
4524		asoc = &stcb->asoc;
4525		/* ABORT and SHUTDOWN can use either v_tag... */
4526		if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) ||
4527		    (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) ||
4528		    (ch->chunk_type == SCTP_PACKET_DROPPED)) {
4529			if ((vtag_in == asoc->my_vtag) ||
4530			    ((ch->chunk_flags & SCTP_HAD_NO_TCB) &&
4531			    (vtag_in == asoc->peer_vtag))) {
4532				/* this is valid */
4533			} else {
4534				/* drop this packet... */
4535				SCTP_STAT_INCR(sctps_badvtag);
4536				if (locked_tcb) {
4537					SCTP_TCB_UNLOCK(locked_tcb);
4538				}
4539				return (NULL);
4540			}
4541		} else if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
4542			if (vtag_in != asoc->my_vtag) {
4543				/*
4544				 * this could be a stale SHUTDOWN-ACK or the
4545				 * peer never got the SHUTDOWN-COMPLETE and
4546				 * is still hung; we have started a new asoc
4547				 * but it won't complete until the shutdown
4548				 * is completed
4549				 */
4550				if (locked_tcb) {
4551					SCTP_TCB_UNLOCK(locked_tcb);
4552				}
4553				sctp_handle_ootb(m, iphlen, *offset, sh, inp,
4554				    NULL, vrf_id, port);
4555				return (NULL);
4556			}
4557		} else {
4558			/* for all other chunks, vtag must match */
4559			if (vtag_in != asoc->my_vtag) {
4560				/* invalid vtag... */
4561				SCTPDBG(SCTP_DEBUG_INPUT3,
4562				    "invalid vtag: %xh, expect %xh\n",
4563				    vtag_in, asoc->my_vtag);
4564				SCTP_STAT_INCR(sctps_badvtag);
4565				if (locked_tcb) {
4566					SCTP_TCB_UNLOCK(locked_tcb);
4567				}
4568				*offset = length;
4569				return (NULL);
4570			}
4571		}
4572	}			/* end if !SCTP_COOKIE_ECHO */
4573	/*
4574	 * process all control chunks...
4575	 */
4576	if (((ch->chunk_type == SCTP_SELECTIVE_ACK) ||
4577	    (ch->chunk_type == SCTP_NR_SELECTIVE_ACK) ||
4578	    (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) &&
4579	    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
4580		/* implied cookie-ack.. we must have lost the ack */
4581		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
4582			sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
4583			    stcb->asoc.overall_error_count,
4584			    0,
4585			    SCTP_FROM_SCTP_INPUT,
4586			    __LINE__);
4587		}
4588		stcb->asoc.overall_error_count = 0;
4589		sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb,
4590		    *netp);
4591	}
4592process_control_chunks:
4593	while (IS_SCTP_CONTROL(ch)) {
4594		/* validate chunk length */
4595		chk_length = ntohs(ch->chunk_length);
4596		SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_process_control: processing a chunk type=%u, len=%u\n",
4597		    ch->chunk_type, chk_length);
4598		SCTP_LTRACE_CHK(inp, stcb, ch->chunk_type, chk_length);
4599		if (chk_length < sizeof(*ch) ||
4600		    (*offset + (int)chk_length) > length) {
4601			*offset = length;
4602			if (locked_tcb) {
4603				SCTP_TCB_UNLOCK(locked_tcb);
4604			}
4605			return (NULL);
4606		}
4607		SCTP_STAT_INCR_COUNTER64(sctps_incontrolchunks);
4608		/*
4609		 * INIT-ACK only gets the init ack "header" portion only
4610		 * because we don't have to process the peer's COOKIE. All
4611		 * others get a complete chunk.
4612		 */
4613		if ((ch->chunk_type == SCTP_INITIATION_ACK) ||
4614		    (ch->chunk_type == SCTP_INITIATION)) {
4615			/* get an init-ack chunk */
4616			ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
4617			    sizeof(struct sctp_init_ack_chunk), chunk_buf);
4618			if (ch == NULL) {
4619				*offset = length;
4620				if (locked_tcb) {
4621					SCTP_TCB_UNLOCK(locked_tcb);
4622				}
4623				return (NULL);
4624			}
4625		} else {
4626			/* For cookies and all other chunks. */
4627			if (chk_length > sizeof(chunk_buf)) {
4628				/*
4629				 * use just the size of the chunk buffer so
4630				 * the front part of our chunks fit in
4631				 * contiguous space up to the chunk buffer
4632				 * size (508 bytes). For chunks that need to
4633				 * get more than that they must use the
4634				 * sctp_m_getptr() function or other means
4635				 * (e.g. know how to parse mbuf chains).
4636				 * Cookies do this already.
4637				 */
4638				ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
4639				    (sizeof(chunk_buf) - 4),
4640				    chunk_buf);
4641				if (ch == NULL) {
4642					*offset = length;
4643					if (locked_tcb) {
4644						SCTP_TCB_UNLOCK(locked_tcb);
4645					}
4646					return (NULL);
4647				}
4648			} else {
4649				/* We can fit it all */
4650				ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
4651				    chk_length, chunk_buf);
4652				if (ch == NULL) {
4653					SCTP_PRINTF("sctp_process_control: Can't get the all data....\n");
4654					*offset = length;
4655					if (locked_tcb) {
4656						SCTP_TCB_UNLOCK(locked_tcb);
4657					}
4658					return (NULL);
4659				}
4660			}
4661		}
4662		num_chunks++;
4663		/* Save off the last place we got a control from */
4664		if (stcb != NULL) {
4665			if (((netp != NULL) && (*netp != NULL)) || (ch->chunk_type == SCTP_ASCONF)) {
4666				/*
4667				 * allow last_control to be NULL if
4668				 * ASCONF... ASCONF processing will find the
4669				 * right net later
4670				 */
4671				if ((netp != NULL) && (*netp != NULL))
4672					stcb->asoc.last_control_chunk_from = *netp;
4673			}
4674		}
4675#ifdef SCTP_AUDITING_ENABLED
4676		sctp_audit_log(0xB0, ch->chunk_type);
4677#endif
4678
4679		/* check to see if this chunk required auth, but isn't */
4680		if ((stcb != NULL) &&
4681		    !SCTP_BASE_SYSCTL(sctp_auth_disable) &&
4682		    sctp_auth_is_required_chunk(ch->chunk_type, stcb->asoc.local_auth_chunks) &&
4683		    !stcb->asoc.authenticated) {
4684			/* "silently" ignore */
4685			SCTP_STAT_INCR(sctps_recvauthmissing);
4686			goto next_chunk;
4687		}
4688		switch (ch->chunk_type) {
4689		case SCTP_INITIATION:
4690			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT\n");
4691			/* The INIT chunk must be the only chunk. */
4692			if ((num_chunks > 1) ||
4693			    (length - *offset > (int)SCTP_SIZE32(chk_length))) {
4694				sctp_abort_association(inp, stcb, m,
4695				    iphlen, sh, NULL, vrf_id, port);
4696				*offset = length;
4697				return (NULL);
4698			}
4699			/* Honor our resource limit. */
4700			if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) {
4701				struct mbuf *op_err;
4702
4703				op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
4704				sctp_abort_association(inp, stcb, m,
4705				    iphlen, sh, op_err, vrf_id, port);
4706				*offset = length;
4707				return (NULL);
4708			}
4709			sctp_handle_init(m, iphlen, *offset, sh,
4710			    (struct sctp_init_chunk *)ch, inp,
4711			    stcb, &abort_no_unlock, vrf_id, port);
4712			*offset = length;
4713			if ((!abort_no_unlock) && (locked_tcb)) {
4714				SCTP_TCB_UNLOCK(locked_tcb);
4715			}
4716			return (NULL);
4717			break;
4718		case SCTP_PAD_CHUNK:
4719			break;
4720		case SCTP_INITIATION_ACK:
4721			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_INIT-ACK\n");
4722			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
4723				/* We are not interested anymore */
4724				if ((stcb) && (stcb->asoc.total_output_queue_size)) {
4725					;
4726				} else {
4727					if (locked_tcb != stcb) {
4728						/* Very unlikely */
4729						SCTP_TCB_UNLOCK(locked_tcb);
4730					}
4731					*offset = length;
4732					if (stcb) {
4733#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4734						so = SCTP_INP_SO(inp);
4735						atomic_add_int(&stcb->asoc.refcnt, 1);
4736						SCTP_TCB_UNLOCK(stcb);
4737						SCTP_SOCKET_LOCK(so, 1);
4738						SCTP_TCB_LOCK(stcb);
4739						atomic_subtract_int(&stcb->asoc.refcnt, 1);
4740#endif
4741						(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
4742#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
4743						SCTP_SOCKET_UNLOCK(so, 1);
4744#endif
4745					}
4746					return (NULL);
4747				}
4748			}
4749			/* The INIT-ACK chunk must be the only chunk. */
4750			if ((num_chunks > 1) ||
4751			    (length - *offset > (int)SCTP_SIZE32(chk_length))) {
4752				*offset = length;
4753				if (locked_tcb) {
4754					SCTP_TCB_UNLOCK(locked_tcb);
4755				}
4756				return (NULL);
4757			}
4758			if ((netp) && (*netp)) {
4759				ret = sctp_handle_init_ack(m, iphlen, *offset, sh,
4760				    (struct sctp_init_ack_chunk *)ch, stcb, *netp, &abort_no_unlock, vrf_id);
4761			} else {
4762				ret = -1;
4763			}
4764			*offset = length;
4765			if (abort_no_unlock) {
4766				return (NULL);
4767			}
4768			/*
4769			 * Special case, I must call the output routine to
4770			 * get the cookie echoed
4771			 */
4772			if ((stcb != NULL) && (ret == 0)) {
4773				sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
4774			}
4775			if (locked_tcb) {
4776				SCTP_TCB_UNLOCK(locked_tcb);
4777			}
4778			return (NULL);
4779			break;
4780		case SCTP_SELECTIVE_ACK:
4781			{
4782				struct sctp_sack_chunk *sack;
4783				int abort_now = 0;
4784				uint32_t a_rwnd, cum_ack;
4785				uint16_t num_seg, num_dup;
4786				uint8_t flags;
4787				int offset_seg, offset_dup;
4788
4789				SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK\n");
4790				SCTP_STAT_INCR(sctps_recvsacks);
4791				if (stcb == NULL) {
4792					SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing SACK chunk\n");
4793					break;
4794				}
4795				if (chk_length < sizeof(struct sctp_sack_chunk)) {
4796					SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on SACK chunk, too small\n");
4797					break;
4798				}
4799				if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
4800					/*-
4801					 * If we have sent a shutdown-ack, we will pay no
4802					 * attention to a sack sent in to us since
4803					 * we don't care anymore.
4804					 */
4805					break;
4806				}
4807				sack = (struct sctp_sack_chunk *)ch;
4808				flags = ch->chunk_flags;
4809				cum_ack = ntohl(sack->sack.cum_tsn_ack);
4810				num_seg = ntohs(sack->sack.num_gap_ack_blks);
4811				num_dup = ntohs(sack->sack.num_dup_tsns);
4812				a_rwnd = (uint32_t) ntohl(sack->sack.a_rwnd);
4813				if (sizeof(struct sctp_sack_chunk) +
4814				    num_seg * sizeof(struct sctp_gap_ack_block) +
4815				    num_dup * sizeof(uint32_t) != chk_length) {
4816					SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of SACK chunk\n");
4817					break;
4818				}
4819				offset_seg = *offset + sizeof(struct sctp_sack_chunk);
4820				offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block);
4821				SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n",
4822				    cum_ack, num_seg, a_rwnd);
4823				stcb->asoc.seen_a_sack_this_pkt = 1;
4824				if ((stcb->asoc.pr_sctp_cnt == 0) &&
4825				    (num_seg == 0) &&
4826				    SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) &&
4827				    (stcb->asoc.saw_sack_with_frags == 0) &&
4828				    (stcb->asoc.saw_sack_with_nr_frags == 0) &&
4829				    (!TAILQ_EMPTY(&stcb->asoc.sent_queue))
4830				    ) {
4831					/*
4832					 * We have a SIMPLE sack having no
4833					 * prior segments and data on sent
4834					 * queue to be acked.. Use the
4835					 * faster path sack processing. We
4836					 * also allow window update sacks
4837					 * with no missing segments to go
4838					 * this way too.
4839					 */
4840					sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now, ecne_seen);
4841				} else {
4842					if (netp && *netp)
4843						sctp_handle_sack(m, offset_seg, offset_dup, stcb,
4844						    num_seg, 0, num_dup, &abort_now, flags,
4845						    cum_ack, a_rwnd, ecne_seen);
4846				}
4847				if (abort_now) {
4848					/* ABORT signal from sack processing */
4849					*offset = length;
4850					return (NULL);
4851				}
4852				if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
4853				    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
4854				    (stcb->asoc.stream_queue_cnt == 0)) {
4855					sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
4856				}
4857			}
4858			break;
4859			/*
4860			 * EY - nr_sack:  If the received chunk is an
4861			 * nr_sack chunk
4862			 */
4863		case SCTP_NR_SELECTIVE_ACK:
4864			{
4865				struct sctp_nr_sack_chunk *nr_sack;
4866				int abort_now = 0;
4867				uint32_t a_rwnd, cum_ack;
4868				uint16_t num_seg, num_nr_seg, num_dup;
4869				uint8_t flags;
4870				int offset_seg, offset_dup;
4871
4872				SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK\n");
4873				SCTP_STAT_INCR(sctps_recvsacks);
4874				if (stcb == NULL) {
4875					SCTPDBG(SCTP_DEBUG_INDATA1, "No stcb when processing NR-SACK chunk\n");
4876					break;
4877				}
4878				if ((stcb->asoc.sctp_nr_sack_on_off == 0) ||
4879				    (stcb->asoc.peer_supports_nr_sack == 0)) {
4880					goto unknown_chunk;
4881				}
4882				if (chk_length < sizeof(struct sctp_nr_sack_chunk)) {
4883					SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size on NR-SACK chunk, too small\n");
4884					break;
4885				}
4886				if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
4887					/*-
4888					 * If we have sent a shutdown-ack, we will pay no
4889					 * attention to a sack sent in to us since
4890					 * we don't care anymore.
4891					 */
4892					break;
4893				}
4894				nr_sack = (struct sctp_nr_sack_chunk *)ch;
4895				flags = ch->chunk_flags;
4896				cum_ack = ntohl(nr_sack->nr_sack.cum_tsn_ack);
4897				num_seg = ntohs(nr_sack->nr_sack.num_gap_ack_blks);
4898				num_nr_seg = ntohs(nr_sack->nr_sack.num_nr_gap_ack_blks);
4899				num_dup = ntohs(nr_sack->nr_sack.num_dup_tsns);
4900				a_rwnd = (uint32_t) ntohl(nr_sack->nr_sack.a_rwnd);
4901				if (sizeof(struct sctp_nr_sack_chunk) +
4902				    (num_seg + num_nr_seg) * sizeof(struct sctp_gap_ack_block) +
4903				    num_dup * sizeof(uint32_t) != chk_length) {
4904					SCTPDBG(SCTP_DEBUG_INDATA1, "Bad size of NR_SACK chunk\n");
4905					break;
4906				}
4907				offset_seg = *offset + sizeof(struct sctp_nr_sack_chunk);
4908				offset_dup = offset_seg + num_seg * sizeof(struct sctp_gap_ack_block);
4909				SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_NR_SACK process cum_ack:%x num_seg:%d a_rwnd:%d\n",
4910				    cum_ack, num_seg, a_rwnd);
4911				stcb->asoc.seen_a_sack_this_pkt = 1;
4912				if ((stcb->asoc.pr_sctp_cnt == 0) &&
4913				    (num_seg == 0) && (num_nr_seg == 0) &&
4914				    SCTP_TSN_GE(cum_ack, stcb->asoc.last_acked_seq) &&
4915				    (stcb->asoc.saw_sack_with_frags == 0) &&
4916				    (stcb->asoc.saw_sack_with_nr_frags == 0) &&
4917				    (!TAILQ_EMPTY(&stcb->asoc.sent_queue))) {
4918					/*
4919					 * We have a SIMPLE sack having no
4920					 * prior segments and data on sent
4921					 * queue to be acked. Use the faster
4922					 * path sack processing. We also
4923					 * allow window update sacks with no
4924					 * missing segments to go this way
4925					 * too.
4926					 */
4927					sctp_express_handle_sack(stcb, cum_ack, a_rwnd,
4928					    &abort_now, ecne_seen);
4929				} else {
4930					if (netp && *netp)
4931						sctp_handle_sack(m, offset_seg, offset_dup, stcb,
4932						    num_seg, num_nr_seg, num_dup, &abort_now, flags,
4933						    cum_ack, a_rwnd, ecne_seen);
4934				}
4935				if (abort_now) {
4936					/* ABORT signal from sack processing */
4937					*offset = length;
4938					return (NULL);
4939				}
4940				if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
4941				    TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
4942				    (stcb->asoc.stream_queue_cnt == 0)) {
4943					sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
4944				}
4945			}
4946			break;
4947
4948		case SCTP_HEARTBEAT_REQUEST:
4949			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT\n");
4950			if ((stcb) && netp && *netp) {
4951				SCTP_STAT_INCR(sctps_recvheartbeat);
4952				sctp_send_heartbeat_ack(stcb, m, *offset,
4953				    chk_length, *netp);
4954
4955				/* He's alive so give him credit */
4956				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
4957					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
4958					    stcb->asoc.overall_error_count,
4959					    0,
4960					    SCTP_FROM_SCTP_INPUT,
4961					    __LINE__);
4962				}
4963				stcb->asoc.overall_error_count = 0;
4964			}
4965			break;
4966		case SCTP_HEARTBEAT_ACK:
4967			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_HEARTBEAT-ACK\n");
4968			if ((stcb == NULL) || (chk_length != sizeof(struct sctp_heartbeat_chunk))) {
4969				/* Its not ours */
4970				*offset = length;
4971				if (locked_tcb) {
4972					SCTP_TCB_UNLOCK(locked_tcb);
4973				}
4974				return (NULL);
4975			}
4976			/* He's alive so give him credit */
4977			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
4978				sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
4979				    stcb->asoc.overall_error_count,
4980				    0,
4981				    SCTP_FROM_SCTP_INPUT,
4982				    __LINE__);
4983			}
4984			stcb->asoc.overall_error_count = 0;
4985			SCTP_STAT_INCR(sctps_recvheartbeatack);
4986			if (netp && *netp)
4987				sctp_handle_heartbeat_ack((struct sctp_heartbeat_chunk *)ch,
4988				    stcb, *netp);
4989			break;
4990		case SCTP_ABORT_ASSOCIATION:
4991			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ABORT, stcb %p\n",
4992			    stcb);
4993			if ((stcb) && netp && *netp)
4994				sctp_handle_abort((struct sctp_abort_chunk *)ch,
4995				    stcb, *netp);
4996			*offset = length;
4997			return (NULL);
4998			break;
4999		case SCTP_SHUTDOWN:
5000			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN, stcb %p\n",
5001			    stcb);
5002			if ((stcb == NULL) || (chk_length != sizeof(struct sctp_shutdown_chunk))) {
5003				*offset = length;
5004				if (locked_tcb) {
5005					SCTP_TCB_UNLOCK(locked_tcb);
5006				}
5007				return (NULL);
5008			}
5009			if (netp && *netp) {
5010				int abort_flag = 0;
5011
5012				sctp_handle_shutdown((struct sctp_shutdown_chunk *)ch,
5013				    stcb, *netp, &abort_flag);
5014				if (abort_flag) {
5015					*offset = length;
5016					return (NULL);
5017				}
5018			}
5019			break;
5020		case SCTP_SHUTDOWN_ACK:
5021			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-ACK, stcb %p\n", stcb);
5022			if ((stcb) && (netp) && (*netp))
5023				sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp);
5024			*offset = length;
5025			return (NULL);
5026			break;
5027
5028		case SCTP_OPERATION_ERROR:
5029			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_OP-ERR\n");
5030			if ((stcb) && netp && *netp && sctp_handle_error(ch, stcb, *netp) < 0) {
5031				*offset = length;
5032				return (NULL);
5033			}
5034			break;
5035		case SCTP_COOKIE_ECHO:
5036			SCTPDBG(SCTP_DEBUG_INPUT3,
5037			    "SCTP_COOKIE-ECHO, stcb %p\n", stcb);
5038			if ((stcb) && (stcb->asoc.total_output_queue_size)) {
5039				;
5040			} else {
5041				if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
5042					/* We are not interested anymore */
5043			abend:
5044					if (stcb) {
5045						SCTP_TCB_UNLOCK(stcb);
5046					}
5047					*offset = length;
5048					return (NULL);
5049				}
5050			}
5051			/*
5052			 * First are we accepting? We do this again here
5053			 * since it is possible that a previous endpoint WAS
5054			 * listening responded to a INIT-ACK and then
5055			 * closed. We opened and bound.. and are now no
5056			 * longer listening.
5057			 */
5058
5059			if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) {
5060				if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
5061				    (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) {
5062					struct mbuf *op_err;
5063
5064					op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
5065					sctp_abort_association(inp, stcb, m,
5066					    iphlen, sh, op_err, vrf_id, port);
5067				}
5068				*offset = length;
5069				return (NULL);
5070			} else {
5071				struct mbuf *ret_buf;
5072				struct sctp_inpcb *linp;
5073
5074				if (stcb) {
5075					linp = NULL;
5076				} else {
5077					linp = inp;
5078				}
5079
5080				if (linp) {
5081					SCTP_ASOC_CREATE_LOCK(linp);
5082					if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
5083					    (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE)) {
5084						SCTP_ASOC_CREATE_UNLOCK(linp);
5085						goto abend;
5086					}
5087				}
5088				if (netp) {
5089					ret_buf =
5090					    sctp_handle_cookie_echo(m, iphlen,
5091					    *offset, sh,
5092					    (struct sctp_cookie_echo_chunk *)ch,
5093					    &inp, &stcb, netp,
5094					    auth_skipped,
5095					    auth_offset,
5096					    auth_len,
5097					    &locked_tcb,
5098					    vrf_id,
5099					    port);
5100				} else {
5101					ret_buf = NULL;
5102				}
5103				if (linp) {
5104					SCTP_ASOC_CREATE_UNLOCK(linp);
5105				}
5106				if (ret_buf == NULL) {
5107					if (locked_tcb) {
5108						SCTP_TCB_UNLOCK(locked_tcb);
5109					}
5110					SCTPDBG(SCTP_DEBUG_INPUT3,
5111					    "GAK, null buffer\n");
5112					*offset = length;
5113					return (NULL);
5114				}
5115				/* if AUTH skipped, see if it verified... */
5116				if (auth_skipped) {
5117					got_auth = 1;
5118					auth_skipped = 0;
5119				}
5120				if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
5121					/*
5122					 * Restart the timer if we have
5123					 * pending data
5124					 */
5125					struct sctp_tmit_chunk *chk;
5126
5127					chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
5128					sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, chk->whoTo);
5129				}
5130			}
5131			break;
5132		case SCTP_COOKIE_ACK:
5133			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_COOKIE-ACK, stcb %p\n", stcb);
5134			if ((stcb == NULL) || chk_length != sizeof(struct sctp_cookie_ack_chunk)) {
5135				if (locked_tcb) {
5136					SCTP_TCB_UNLOCK(locked_tcb);
5137				}
5138				return (NULL);
5139			}
5140			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
5141				/* We are not interested anymore */
5142				if ((stcb) && (stcb->asoc.total_output_queue_size)) {
5143					;
5144				} else if (stcb) {
5145#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
5146					so = SCTP_INP_SO(inp);
5147					atomic_add_int(&stcb->asoc.refcnt, 1);
5148					SCTP_TCB_UNLOCK(stcb);
5149					SCTP_SOCKET_LOCK(so, 1);
5150					SCTP_TCB_LOCK(stcb);
5151					atomic_subtract_int(&stcb->asoc.refcnt, 1);
5152#endif
5153					(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_27);
5154#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
5155					SCTP_SOCKET_UNLOCK(so, 1);
5156#endif
5157					*offset = length;
5158					return (NULL);
5159				}
5160			}
5161			/* He's alive so give him credit */
5162			if ((stcb) && netp && *netp) {
5163				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5164					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5165					    stcb->asoc.overall_error_count,
5166					    0,
5167					    SCTP_FROM_SCTP_INPUT,
5168					    __LINE__);
5169				}
5170				stcb->asoc.overall_error_count = 0;
5171				sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, *netp);
5172			}
5173			break;
5174		case SCTP_ECN_ECHO:
5175			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-ECHO\n");
5176			/* He's alive so give him credit */
5177			if ((stcb == NULL) || (chk_length != sizeof(struct sctp_ecne_chunk))) {
5178				/* Its not ours */
5179				if (locked_tcb) {
5180					SCTP_TCB_UNLOCK(locked_tcb);
5181				}
5182				*offset = length;
5183				return (NULL);
5184			}
5185			if (stcb) {
5186				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5187					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5188					    stcb->asoc.overall_error_count,
5189					    0,
5190					    SCTP_FROM_SCTP_INPUT,
5191					    __LINE__);
5192				}
5193				stcb->asoc.overall_error_count = 0;
5194				sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch,
5195				    stcb);
5196				ecne_seen = 1;
5197			}
5198			break;
5199		case SCTP_ECN_CWR:
5200			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ECN-CWR\n");
5201			/* He's alive so give him credit */
5202			if ((stcb == NULL) || (chk_length != sizeof(struct sctp_cwr_chunk))) {
5203				/* Its not ours */
5204				if (locked_tcb) {
5205					SCTP_TCB_UNLOCK(locked_tcb);
5206				}
5207				*offset = length;
5208				return (NULL);
5209			}
5210			if (stcb) {
5211				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5212					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5213					    stcb->asoc.overall_error_count,
5214					    0,
5215					    SCTP_FROM_SCTP_INPUT,
5216					    __LINE__);
5217				}
5218				stcb->asoc.overall_error_count = 0;
5219				sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb, *netp);
5220			}
5221			break;
5222		case SCTP_SHUTDOWN_COMPLETE:
5223			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_SHUTDOWN-COMPLETE, stcb %p\n", stcb);
5224			/* must be first and only chunk */
5225			if ((num_chunks > 1) ||
5226			    (length - *offset > (int)SCTP_SIZE32(chk_length))) {
5227				*offset = length;
5228				if (locked_tcb) {
5229					SCTP_TCB_UNLOCK(locked_tcb);
5230				}
5231				return (NULL);
5232			}
5233			if ((stcb) && netp && *netp) {
5234				sctp_handle_shutdown_complete((struct sctp_shutdown_complete_chunk *)ch,
5235				    stcb, *netp);
5236			}
5237			*offset = length;
5238			return (NULL);
5239			break;
5240		case SCTP_ASCONF:
5241			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF\n");
5242			/* He's alive so give him credit */
5243			if (stcb) {
5244				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5245					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5246					    stcb->asoc.overall_error_count,
5247					    0,
5248					    SCTP_FROM_SCTP_INPUT,
5249					    __LINE__);
5250				}
5251				stcb->asoc.overall_error_count = 0;
5252				sctp_handle_asconf(m, *offset,
5253				    (struct sctp_asconf_chunk *)ch, stcb, asconf_cnt == 0);
5254				asconf_cnt++;
5255			}
5256			break;
5257		case SCTP_ASCONF_ACK:
5258			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_ASCONF-ACK\n");
5259			if (chk_length < sizeof(struct sctp_asconf_ack_chunk)) {
5260				/* Its not ours */
5261				if (locked_tcb) {
5262					SCTP_TCB_UNLOCK(locked_tcb);
5263				}
5264				*offset = length;
5265				return (NULL);
5266			}
5267			if ((stcb) && netp && *netp) {
5268				/* He's alive so give him credit */
5269				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5270					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5271					    stcb->asoc.overall_error_count,
5272					    0,
5273					    SCTP_FROM_SCTP_INPUT,
5274					    __LINE__);
5275				}
5276				stcb->asoc.overall_error_count = 0;
5277				sctp_handle_asconf_ack(m, *offset,
5278				    (struct sctp_asconf_ack_chunk *)ch, stcb, *netp, &abort_no_unlock);
5279				if (abort_no_unlock)
5280					return (NULL);
5281			}
5282			break;
5283		case SCTP_FORWARD_CUM_TSN:
5284			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_FWD-TSN\n");
5285			if (chk_length < sizeof(struct sctp_forward_tsn_chunk)) {
5286				/* Its not ours */
5287				if (locked_tcb) {
5288					SCTP_TCB_UNLOCK(locked_tcb);
5289				}
5290				*offset = length;
5291				return (NULL);
5292			}
5293			/* He's alive so give him credit */
5294			if (stcb) {
5295				int abort_flag = 0;
5296
5297				stcb->asoc.overall_error_count = 0;
5298				if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5299					sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5300					    stcb->asoc.overall_error_count,
5301					    0,
5302					    SCTP_FROM_SCTP_INPUT,
5303					    __LINE__);
5304				}
5305				*fwd_tsn_seen = 1;
5306				if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
5307					/* We are not interested anymore */
5308#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
5309					so = SCTP_INP_SO(inp);
5310					atomic_add_int(&stcb->asoc.refcnt, 1);
5311					SCTP_TCB_UNLOCK(stcb);
5312					SCTP_SOCKET_LOCK(so, 1);
5313					SCTP_TCB_LOCK(stcb);
5314					atomic_subtract_int(&stcb->asoc.refcnt, 1);
5315#endif
5316					(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_29);
5317#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
5318					SCTP_SOCKET_UNLOCK(so, 1);
5319#endif
5320					*offset = length;
5321					return (NULL);
5322				}
5323				sctp_handle_forward_tsn(stcb,
5324				    (struct sctp_forward_tsn_chunk *)ch, &abort_flag, m, *offset);
5325				if (abort_flag) {
5326					*offset = length;
5327					return (NULL);
5328				} else {
5329					if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5330						sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5331						    stcb->asoc.overall_error_count,
5332						    0,
5333						    SCTP_FROM_SCTP_INPUT,
5334						    __LINE__);
5335					}
5336					stcb->asoc.overall_error_count = 0;
5337				}
5338
5339			}
5340			break;
5341		case SCTP_STREAM_RESET:
5342			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_STREAM_RESET\n");
5343			if (((stcb == NULL) || (ch == NULL) || (chk_length < sizeof(struct sctp_stream_reset_tsn_req)))) {
5344				/* Its not ours */
5345				if (locked_tcb) {
5346					SCTP_TCB_UNLOCK(locked_tcb);
5347				}
5348				*offset = length;
5349				return (NULL);
5350			}
5351			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
5352				/* We are not interested anymore */
5353#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
5354				so = SCTP_INP_SO(inp);
5355				atomic_add_int(&stcb->asoc.refcnt, 1);
5356				SCTP_TCB_UNLOCK(stcb);
5357				SCTP_SOCKET_LOCK(so, 1);
5358				SCTP_TCB_LOCK(stcb);
5359				atomic_subtract_int(&stcb->asoc.refcnt, 1);
5360#endif
5361				(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_INPUT + SCTP_LOC_30);
5362#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
5363				SCTP_SOCKET_UNLOCK(so, 1);
5364#endif
5365				*offset = length;
5366				return (NULL);
5367			}
5368			if (stcb->asoc.peer_supports_strreset == 0) {
5369				/*
5370				 * hmm, peer should have announced this, but
5371				 * we will turn it on since he is sending us
5372				 * a stream reset.
5373				 */
5374				stcb->asoc.peer_supports_strreset = 1;
5375			}
5376			if (sctp_handle_stream_reset(stcb, m, *offset, (struct sctp_stream_reset_out_req *)ch)) {
5377				/* stop processing */
5378				*offset = length;
5379				return (NULL);
5380			}
5381			break;
5382		case SCTP_PACKET_DROPPED:
5383			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_PACKET_DROPPED\n");
5384			/* re-get it all please */
5385			if (chk_length < sizeof(struct sctp_pktdrop_chunk)) {
5386				/* Its not ours */
5387				if (locked_tcb) {
5388					SCTP_TCB_UNLOCK(locked_tcb);
5389				}
5390				*offset = length;
5391				return (NULL);
5392			}
5393			if (ch && (stcb) && netp && (*netp)) {
5394				sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch,
5395				    stcb, *netp,
5396				    min(chk_length, (sizeof(chunk_buf) - 4)));
5397
5398			}
5399			break;
5400
5401		case SCTP_AUTHENTICATION:
5402			SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_AUTHENTICATION\n");
5403			if (SCTP_BASE_SYSCTL(sctp_auth_disable))
5404				goto unknown_chunk;
5405
5406			if (stcb == NULL) {
5407				/* save the first AUTH for later processing */
5408				if (auth_skipped == 0) {
5409					auth_offset = *offset;
5410					auth_len = chk_length;
5411					auth_skipped = 1;
5412				}
5413				/* skip this chunk (temporarily) */
5414				goto next_chunk;
5415			}
5416			if ((chk_length < (sizeof(struct sctp_auth_chunk))) ||
5417			    (chk_length > (sizeof(struct sctp_auth_chunk) +
5418			    SCTP_AUTH_DIGEST_LEN_MAX))) {
5419				/* Its not ours */
5420				if (locked_tcb) {
5421					SCTP_TCB_UNLOCK(locked_tcb);
5422				}
5423				*offset = length;
5424				return (NULL);
5425			}
5426			if (got_auth == 1) {
5427				/* skip this chunk... it's already auth'd */
5428				goto next_chunk;
5429			}
5430			got_auth = 1;
5431			if ((ch == NULL) || sctp_handle_auth(stcb, (struct sctp_auth_chunk *)ch,
5432			    m, *offset)) {
5433				/* auth HMAC failed so dump the packet */
5434				*offset = length;
5435				return (stcb);
5436			} else {
5437				/* remaining chunks are HMAC checked */
5438				stcb->asoc.authenticated = 1;
5439			}
5440			break;
5441
5442		default:
5443	unknown_chunk:
5444			/* it's an unknown chunk! */
5445			if ((ch->chunk_type & 0x40) && (stcb != NULL)) {
5446				struct mbuf *mm;
5447				struct sctp_paramhdr *phd;
5448
5449				mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr),
5450				    0, M_DONTWAIT, 1, MT_DATA);
5451				if (mm) {
5452					phd = mtod(mm, struct sctp_paramhdr *);
5453					/*
5454					 * We cheat and use param type since
5455					 * we did not bother to define a
5456					 * error cause struct. They are the
5457					 * same basic format with different
5458					 * names.
5459					 */
5460					phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK);
5461					phd->param_length = htons(chk_length + sizeof(*phd));
5462					SCTP_BUF_LEN(mm) = sizeof(*phd);
5463					SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, M_DONTWAIT);
5464					if (SCTP_BUF_NEXT(mm)) {
5465						if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL)) {
5466							sctp_m_freem(mm);
5467						} else {
5468#ifdef SCTP_MBUF_LOGGING
5469							if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
5470								struct mbuf *mat;
5471
5472								for (mat = SCTP_BUF_NEXT(mm); mat; mat = SCTP_BUF_NEXT(mat)) {
5473									if (SCTP_BUF_IS_EXTENDED(mat)) {
5474										sctp_log_mb(mat, SCTP_MBUF_ICOPY);
5475									}
5476								}
5477							}
5478#endif
5479							sctp_queue_op_err(stcb, mm);
5480						}
5481					} else {
5482						sctp_m_freem(mm);
5483					}
5484				}
5485			}
5486			if ((ch->chunk_type & 0x80) == 0) {
5487				/* discard this packet */
5488				*offset = length;
5489				return (stcb);
5490			}	/* else skip this bad chunk and continue... */
5491			break;
5492		}		/* switch (ch->chunk_type) */
5493
5494
5495next_chunk:
5496		/* get the next chunk */
5497		*offset += SCTP_SIZE32(chk_length);
5498		if (*offset >= length) {
5499			/* no more data left in the mbuf chain */
5500			break;
5501		}
5502		ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
5503		    sizeof(struct sctp_chunkhdr), chunk_buf);
5504		if (ch == NULL) {
5505			if (locked_tcb) {
5506				SCTP_TCB_UNLOCK(locked_tcb);
5507			}
5508			*offset = length;
5509			return (NULL);
5510		}
5511	}			/* while */
5512
5513	if (asconf_cnt > 0 && stcb != NULL) {
5514		sctp_send_asconf_ack(stcb);
5515	}
5516	return (stcb);
5517}
5518
5519
5520#ifdef INVARIANTS
5521#ifdef __GNUC__
5522__attribute__((noinline))
5523#endif
5524	void
5525	     sctp_validate_no_locks(struct sctp_inpcb *inp)
5526{
5527	struct sctp_tcb *lstcb;
5528
5529	LIST_FOREACH(lstcb, &inp->sctp_asoc_list, sctp_tcblist) {
5530		if (mtx_owned(&lstcb->tcb_mtx)) {
5531			panic("Own lock on stcb at return from input");
5532		}
5533	}
5534	if (mtx_owned(&inp->inp_create_mtx)) {
5535		panic("Own create lock on inp");
5536	}
5537	if (mtx_owned(&inp->inp_mtx)) {
5538		panic("Own inp lock on inp");
5539	}
5540}
5541
5542#endif
5543
5544/*
5545 * common input chunk processing (v4 and v6)
5546 */
5547void
5548sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
5549    int length, struct sctphdr *sh, struct sctp_chunkhdr *ch,
5550    struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets *net,
5551    uint8_t ecn_bits, uint32_t vrf_id, uint16_t port)
5552{
5553	/*
5554	 * Control chunk processing
5555	 */
5556	uint32_t high_tsn;
5557	int fwd_tsn_seen = 0, data_processed = 0;
5558	struct mbuf *m = *mm;
5559	int un_sent;
5560	int cnt_ctrl_ready = 0;
5561
5562	SCTP_STAT_INCR(sctps_recvdatagrams);
5563#ifdef SCTP_AUDITING_ENABLED
5564	sctp_audit_log(0xE0, 1);
5565	sctp_auditing(0, inp, stcb, net);
5566#endif
5567
5568	SCTPDBG(SCTP_DEBUG_INPUT1, "Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d stcb:%p\n",
5569	    m, iphlen, offset, length, stcb);
5570	if (stcb) {
5571		/* always clear this before beginning a packet */
5572		stcb->asoc.authenticated = 0;
5573		stcb->asoc.seen_a_sack_this_pkt = 0;
5574		SCTPDBG(SCTP_DEBUG_INPUT1, "stcb:%p state:%x\n",
5575		    stcb, stcb->asoc.state);
5576
5577		if ((stcb->asoc.state & SCTP_STATE_WAS_ABORTED) ||
5578		    (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED)) {
5579			/*-
5580			 * If we hit here, we had a ref count
5581			 * up when the assoc was aborted and the
5582			 * timer is clearing out the assoc, we should
5583			 * NOT respond to any packet.. its OOTB.
5584			 */
5585			SCTP_TCB_UNLOCK(stcb);
5586			sctp_handle_ootb(m, iphlen, offset, sh, inp, NULL,
5587			    vrf_id, port);
5588			goto out_now;
5589		}
5590	}
5591	if (IS_SCTP_CONTROL(ch)) {
5592		/* process the control portion of the SCTP packet */
5593		/* sa_ignore NO_NULL_CHK */
5594		stcb = sctp_process_control(m, iphlen, &offset, length, sh, ch,
5595		    inp, stcb, &net, &fwd_tsn_seen, vrf_id, port);
5596		if (stcb) {
5597			/*
5598			 * This covers us if the cookie-echo was there and
5599			 * it changes our INP.
5600			 */
5601			inp = stcb->sctp_ep;
5602			if ((net) && (port)) {
5603				if (net->port == 0) {
5604					sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
5605				}
5606				net->port = port;
5607			}
5608		}
5609	} else {
5610		/*
5611		 * no control chunks, so pre-process DATA chunks (these
5612		 * checks are taken care of by control processing)
5613		 */
5614
5615		/*
5616		 * if DATA only packet, and auth is required, then punt...
5617		 * can't have authenticated without any AUTH (control)
5618		 * chunks
5619		 */
5620		if ((stcb != NULL) &&
5621		    !SCTP_BASE_SYSCTL(sctp_auth_disable) &&
5622		    sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks)) {
5623			/* "silently" ignore */
5624			SCTP_STAT_INCR(sctps_recvauthmissing);
5625			SCTP_TCB_UNLOCK(stcb);
5626			goto out_now;
5627		}
5628		if (stcb == NULL) {
5629			/* out of the blue DATA chunk */
5630			sctp_handle_ootb(m, iphlen, offset, sh, inp, NULL,
5631			    vrf_id, port);
5632			goto out_now;
5633		}
5634		if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) {
5635			/* v_tag mismatch! */
5636			SCTP_STAT_INCR(sctps_badvtag);
5637			SCTP_TCB_UNLOCK(stcb);
5638			goto out_now;
5639		}
5640	}
5641
5642	if (stcb == NULL) {
5643		/*
5644		 * no valid TCB for this packet, or we found it's a bad
5645		 * packet while processing control, or we're done with this
5646		 * packet (done or skip rest of data), so we drop it...
5647		 */
5648		goto out_now;
5649	}
5650	/*
5651	 * DATA chunk processing
5652	 */
5653	/* plow through the data chunks while length > offset */
5654
5655	/*
5656	 * Rest should be DATA only.  Check authentication state if AUTH for
5657	 * DATA is required.
5658	 */
5659	if ((length > offset) &&
5660	    (stcb != NULL) &&
5661	    !SCTP_BASE_SYSCTL(sctp_auth_disable) &&
5662	    sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.local_auth_chunks) &&
5663	    !stcb->asoc.authenticated) {
5664		/* "silently" ignore */
5665		SCTP_STAT_INCR(sctps_recvauthmissing);
5666		SCTPDBG(SCTP_DEBUG_AUTH1,
5667		    "Data chunk requires AUTH, skipped\n");
5668		goto trigger_send;
5669	}
5670	if (length > offset) {
5671		int retval;
5672
5673		/*
5674		 * First check to make sure our state is correct. We would
5675		 * not get here unless we really did have a tag, so we don't
5676		 * abort if this happens, just dump the chunk silently.
5677		 */
5678		switch (SCTP_GET_STATE(&stcb->asoc)) {
5679		case SCTP_STATE_COOKIE_ECHOED:
5680			/*
5681			 * we consider data with valid tags in this state
5682			 * shows us the cookie-ack was lost. Imply it was
5683			 * there.
5684			 */
5685			if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
5686				sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
5687				    stcb->asoc.overall_error_count,
5688				    0,
5689				    SCTP_FROM_SCTP_INPUT,
5690				    __LINE__);
5691			}
5692			stcb->asoc.overall_error_count = 0;
5693			sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, net);
5694			break;
5695		case SCTP_STATE_COOKIE_WAIT:
5696			/*
5697			 * We consider OOTB any data sent during asoc setup.
5698			 */
5699			sctp_handle_ootb(m, iphlen, offset, sh, inp, NULL,
5700			    vrf_id, port);
5701			SCTP_TCB_UNLOCK(stcb);
5702			goto out_now;
5703			/* sa_ignore NOTREACHED */
5704			break;
5705		case SCTP_STATE_EMPTY:	/* should not happen */
5706		case SCTP_STATE_INUSE:	/* should not happen */
5707		case SCTP_STATE_SHUTDOWN_RECEIVED:	/* This is a peer error */
5708		case SCTP_STATE_SHUTDOWN_ACK_SENT:
5709		default:
5710			SCTP_TCB_UNLOCK(stcb);
5711			goto out_now;
5712			/* sa_ignore NOTREACHED */
5713			break;
5714		case SCTP_STATE_OPEN:
5715		case SCTP_STATE_SHUTDOWN_SENT:
5716			break;
5717		}
5718		/* plow through the data chunks while length > offset */
5719		retval = sctp_process_data(mm, iphlen, &offset, length, sh,
5720		    inp, stcb, net, &high_tsn);
5721		if (retval == 2) {
5722			/*
5723			 * The association aborted, NO UNLOCK needed since
5724			 * the association is destroyed.
5725			 */
5726			goto out_now;
5727		}
5728		data_processed = 1;
5729		/*
5730		 * Anything important needs to have been m_copy'ed in
5731		 * process_data
5732		 */
5733	}
5734	/* take care of ecn */
5735	if ((data_processed == 1) &&
5736	    (stcb->asoc.ecn_allowed == 1) &&
5737	    ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS)) {
5738		/* Yep, we need to add a ECNE */
5739		sctp_send_ecn_echo(stcb, net, high_tsn);
5740	}
5741	if ((data_processed == 0) && (fwd_tsn_seen)) {
5742		int was_a_gap;
5743		uint32_t highest_tsn;
5744
5745		if (SCTP_TSN_GT(stcb->asoc.highest_tsn_inside_nr_map, stcb->asoc.highest_tsn_inside_map)) {
5746			highest_tsn = stcb->asoc.highest_tsn_inside_nr_map;
5747		} else {
5748			highest_tsn = stcb->asoc.highest_tsn_inside_map;
5749		}
5750		was_a_gap = SCTP_TSN_GT(highest_tsn, stcb->asoc.cumulative_tsn);
5751		stcb->asoc.send_sack = 1;
5752		sctp_sack_check(stcb, was_a_gap);
5753	} else if (fwd_tsn_seen) {
5754		stcb->asoc.send_sack = 1;
5755	}
5756	/* trigger send of any chunks in queue... */
5757trigger_send:
5758#ifdef SCTP_AUDITING_ENABLED
5759	sctp_audit_log(0xE0, 2);
5760	sctp_auditing(1, inp, stcb, net);
5761#endif
5762	SCTPDBG(SCTP_DEBUG_INPUT1,
5763	    "Check for chunk output prw:%d tqe:%d tf=%d\n",
5764	    stcb->asoc.peers_rwnd,
5765	    TAILQ_EMPTY(&stcb->asoc.control_send_queue),
5766	    stcb->asoc.total_flight);
5767	un_sent = (stcb->asoc.total_output_queue_size - stcb->asoc.total_flight);
5768	if (!TAILQ_EMPTY(&stcb->asoc.control_send_queue)) {
5769		cnt_ctrl_ready = stcb->asoc.ctrl_queue_cnt - stcb->asoc.ecn_echo_cnt_onq;
5770	}
5771	if (cnt_ctrl_ready ||
5772	    ((un_sent) &&
5773	    (stcb->asoc.peers_rwnd > 0 ||
5774	    (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)))) {
5775		SCTPDBG(SCTP_DEBUG_INPUT3, "Calling chunk OUTPUT\n");
5776		sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CONTROL_PROC, SCTP_SO_NOT_LOCKED);
5777		SCTPDBG(SCTP_DEBUG_INPUT3, "chunk OUTPUT returns\n");
5778	}
5779#ifdef SCTP_AUDITING_ENABLED
5780	sctp_audit_log(0xE0, 3);
5781	sctp_auditing(2, inp, stcb, net);
5782#endif
5783	SCTP_TCB_UNLOCK(stcb);
5784out_now:
5785#ifdef INVARIANTS
5786	sctp_validate_no_locks(inp);
5787#endif
5788	return;
5789}
5790
5791#if 0
5792static void
5793sctp_print_mbuf_chain(struct mbuf *m)
5794{
5795	for (; m; m = SCTP_BUF_NEXT(m)) {
5796		SCTP_PRINTF("%p: m_len = %ld\n", m, SCTP_BUF_LEN(m));
5797		if (SCTP_BUF_IS_EXTENDED(m))
5798			SCTP_PRINTF("%p: extend_size = %d\n", m, SCTP_BUF_EXTEND_SIZE(m));
5799	}
5800}
5801
5802#endif
5803
5804#ifdef INET
5805void
5806sctp_input_with_port(struct mbuf *i_pak, int off, uint16_t port)
5807{
5808	struct mbuf *m;
5809	int iphlen;
5810	uint32_t vrf_id = 0;
5811	uint8_t ecn_bits;
5812	struct ip *ip;
5813	struct sctphdr *sh;
5814	struct sctp_inpcb *inp = NULL;
5815	struct sctp_nets *net;
5816	struct sctp_tcb *stcb = NULL;
5817	struct sctp_chunkhdr *ch;
5818	int refcount_up = 0;
5819	int length, mlen, offset;
5820
5821#if !defined(SCTP_WITH_NO_CSUM)
5822	uint32_t check, calc_check;
5823
5824#endif
5825
5826	if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) {
5827		SCTP_RELEASE_PKT(i_pak);
5828		return;
5829	}
5830	mlen = SCTP_HEADER_LEN(i_pak);
5831	iphlen = off;
5832	m = SCTP_HEADER_TO_CHAIN(i_pak);
5833
5834	net = NULL;
5835	SCTP_STAT_INCR(sctps_recvpackets);
5836	SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
5837
5838
5839#ifdef SCTP_MBUF_LOGGING
5840	/* Log in any input mbufs */
5841	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
5842		struct mbuf *mat;
5843
5844		for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
5845			if (SCTP_BUF_IS_EXTENDED(mat)) {
5846				sctp_log_mb(mat, SCTP_MBUF_INPUT);
5847			}
5848		}
5849	}
5850#endif
5851#ifdef  SCTP_PACKET_LOGGING
5852	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
5853		sctp_packet_log(m, mlen);
5854#endif
5855	/*
5856	 * Must take out the iphlen, since mlen expects this (only effect lb
5857	 * case)
5858	 */
5859	mlen -= iphlen;
5860
5861	/*
5862	 * Get IP, SCTP, and first chunk header together in first mbuf.
5863	 */
5864	ip = mtod(m, struct ip *);
5865	offset = iphlen + sizeof(*sh) + sizeof(*ch);
5866	if (SCTP_BUF_LEN(m) < offset) {
5867		if ((m = m_pullup(m, offset)) == 0) {
5868			SCTP_STAT_INCR(sctps_hdrops);
5869			return;
5870		}
5871		ip = mtod(m, struct ip *);
5872	}
5873	/* validate mbuf chain length with IP payload length */
5874	if (mlen < (SCTP_GET_IPV4_LENGTH(ip) - iphlen)) {
5875		SCTP_STAT_INCR(sctps_hdrops);
5876		goto bad;
5877	}
5878	sh = (struct sctphdr *)((caddr_t)ip + iphlen);
5879	ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(*sh));
5880	SCTPDBG(SCTP_DEBUG_INPUT1,
5881	    "sctp_input() length:%d iphlen:%d\n", mlen, iphlen);
5882
5883	/* SCTP does not allow broadcasts or multicasts */
5884	if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
5885		goto bad;
5886	}
5887	if (SCTP_IS_IT_BROADCAST(ip->ip_dst, m)) {
5888		/*
5889		 * We only look at broadcast if its a front state, All
5890		 * others we will not have a tcb for anyway.
5891		 */
5892		goto bad;
5893	}
5894	/* validate SCTP checksum */
5895	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
5896	    "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
5897	    m->m_pkthdr.len,
5898	    if_name(m->m_pkthdr.rcvif),
5899	    m->m_pkthdr.csum_flags);
5900#if defined(SCTP_WITH_NO_CSUM)
5901	SCTP_STAT_INCR(sctps_recvnocrc);
5902#else
5903	if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
5904		SCTP_STAT_INCR(sctps_recvhwcrc);
5905		goto sctp_skip_csum_4;
5906	}
5907	check = sh->checksum;	/* save incoming checksum */
5908	sh->checksum = 0;	/* prepare for calc */
5909	calc_check = sctp_calculate_cksum(m, iphlen);
5910	sh->checksum = check;
5911	SCTP_STAT_INCR(sctps_recvswcrc);
5912	if (calc_check != check) {
5913		SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x  m:%p mlen:%d iphlen:%d\n",
5914		    calc_check, check, m, mlen, iphlen);
5915
5916		stcb = sctp_findassociation_addr(m,
5917		    offset - sizeof(*ch),
5918		    sh, ch, &inp, &net,
5919		    vrf_id);
5920		if ((net) && (port)) {
5921			if (net->port == 0) {
5922				sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
5923			}
5924			net->port = port;
5925		}
5926		if ((net != NULL) && (m->m_flags & M_FLOWID)) {
5927			net->flowid = m->m_pkthdr.flowid;
5928#ifdef INVARIANTS
5929			net->flowidset = 1;
5930#endif
5931		}
5932		if ((inp) && (stcb)) {
5933			sctp_send_packet_dropped(stcb, net, m, iphlen, 1);
5934			sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_INPUT_ERROR, SCTP_SO_NOT_LOCKED);
5935		} else if ((inp != NULL) && (stcb == NULL)) {
5936			refcount_up = 1;
5937		}
5938		SCTP_STAT_INCR(sctps_badsum);
5939		SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
5940		goto bad;
5941	}
5942sctp_skip_csum_4:
5943#endif
5944	/* destination port of 0 is illegal, based on RFC2960. */
5945	if (sh->dest_port == 0) {
5946		SCTP_STAT_INCR(sctps_hdrops);
5947		goto bad;
5948	}
5949	/*
5950	 * Locate pcb and tcb for datagram sctp_findassociation_addr() wants
5951	 * IP/SCTP/first chunk header...
5952	 */
5953	stcb = sctp_findassociation_addr(m, offset - sizeof(*ch),
5954	    sh, ch, &inp, &net, vrf_id);
5955	if ((net) && (port)) {
5956		if (net->port == 0) {
5957			sctp_pathmtu_adjustment(stcb, net->mtu - sizeof(struct udphdr));
5958		}
5959		net->port = port;
5960	}
5961	if ((net != NULL) && (m->m_flags & M_FLOWID)) {
5962		net->flowid = m->m_pkthdr.flowid;
5963#ifdef INVARIANTS
5964		net->flowidset = 1;
5965#endif
5966	}
5967	/* inp's ref-count increased && stcb locked */
5968	if (inp == NULL) {
5969		struct sctp_init_chunk *init_chk, chunk_buf;
5970
5971		SCTP_STAT_INCR(sctps_noport);
5972#ifdef ICMP_BANDLIM
5973		/*
5974		 * we use the bandwidth limiting to protect against sending
5975		 * too many ABORTS all at once. In this case these count the
5976		 * same as an ICMP message.
5977		 */
5978		if (badport_bandlim(0) < 0)
5979			goto bad;
5980#endif				/* ICMP_BANDLIM */
5981		SCTPDBG(SCTP_DEBUG_INPUT1,
5982		    "Sending a ABORT from packet entry!\n");
5983		if (ch->chunk_type == SCTP_INITIATION) {
5984			/*
5985			 * we do a trick here to get the INIT tag, dig in
5986			 * and get the tag from the INIT and put it in the
5987			 * common header.
5988			 */
5989			init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
5990			    iphlen + sizeof(*sh), sizeof(*init_chk),
5991			    (uint8_t *) & chunk_buf);
5992			if (init_chk != NULL)
5993				sh->v_tag = init_chk->init.initiate_tag;
5994		}
5995		if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
5996			sctp_send_shutdown_complete2(m, sh, vrf_id, port);
5997			goto bad;
5998		}
5999		if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
6000			goto bad;
6001		}
6002		if (ch->chunk_type != SCTP_ABORT_ASSOCIATION) {
6003			if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) ||
6004			    ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) &&
6005			    (ch->chunk_type != SCTP_INIT))) {
6006				sctp_send_abort(m, iphlen, sh, 0, NULL, vrf_id, port);
6007			}
6008		}
6009		goto bad;
6010	} else if (stcb == NULL) {
6011		refcount_up = 1;
6012	}
6013#ifdef IPSEC
6014	/*
6015	 * I very much doubt any of the IPSEC stuff will work but I have no
6016	 * idea, so I will leave it in place.
6017	 */
6018	if (inp && ipsec4_in_reject(m, &inp->ip_inp.inp)) {
6019		MODULE_GLOBAL(ipsec4stat).in_polvio++;
6020		SCTP_STAT_INCR(sctps_hdrops);
6021		goto bad;
6022	}
6023#endif				/* IPSEC */
6024
6025	/*
6026	 * common chunk processing
6027	 */
6028	length = ip->ip_len + iphlen;
6029	offset -= sizeof(struct sctp_chunkhdr);
6030
6031	ecn_bits = ip->ip_tos;
6032
6033	/* sa_ignore NO_NULL_CHK */
6034	sctp_common_input_processing(&m, iphlen, offset, length, sh, ch,
6035	    inp, stcb, net, ecn_bits, vrf_id, port);
6036	/* inp's ref-count reduced && stcb unlocked */
6037	if (m) {
6038		sctp_m_freem(m);
6039	}
6040	if ((inp) && (refcount_up)) {
6041		/* reduce ref-count */
6042		SCTP_INP_DECR_REF(inp);
6043	}
6044	return;
6045bad:
6046	if (stcb) {
6047		SCTP_TCB_UNLOCK(stcb);
6048	}
6049	if ((inp) && (refcount_up)) {
6050		/* reduce ref-count */
6051		SCTP_INP_DECR_REF(inp);
6052	}
6053	if (m) {
6054		sctp_m_freem(m);
6055	}
6056	return;
6057}
6058
6059#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
6060extern int *sctp_cpuarry;
6061
6062#endif
6063
6064void
6065sctp_input(struct mbuf *m, int off)
6066{
6067#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
6068	struct ip *ip;
6069	struct sctphdr *sh;
6070	int offset;
6071	int cpu_to_use;
6072	uint32_t flowid, tag;
6073
6074	if (mp_ncpus > 1) {
6075		if (m->m_flags & M_FLOWID) {
6076			flowid = m->m_pkthdr.flowid;
6077		} else {
6078			/*
6079			 * No flow id built by lower layers fix it so we
6080			 * create one.
6081			 */
6082			ip = mtod(m, struct ip *);
6083			offset = off + sizeof(*sh);
6084			if (SCTP_BUF_LEN(m) < offset) {
6085				if ((m = m_pullup(m, offset)) == 0) {
6086					SCTP_STAT_INCR(sctps_hdrops);
6087					return;
6088				}
6089				ip = mtod(m, struct ip *);
6090			}
6091			sh = (struct sctphdr *)((caddr_t)ip + off);
6092			tag = htonl(sh->v_tag);
6093			flowid = tag ^ ntohs(sh->dest_port) ^ ntohs(sh->src_port);
6094			m->m_pkthdr.flowid = flowid;
6095			m->m_flags |= M_FLOWID;
6096		}
6097		cpu_to_use = sctp_cpuarry[flowid % mp_ncpus];
6098		sctp_queue_to_mcore(m, off, cpu_to_use);
6099		return;
6100	}
6101#endif
6102	sctp_input_with_port(m, off, 0);
6103}
6104
6105#endif
6106