xref: /netbsd-src/sys/netinet/sctp_input.c (revision 481d3881954fd794ca5f2d880b68c53a5db8620e)
18c2654abSrjs /*	$KAME: sctp_input.c,v 1.28 2005/04/21 18:36:21 nishida Exp $	*/
2*481d3881Srin /*	$NetBSD: sctp_input.c,v 1.18 2024/07/05 04:31:54 rin Exp $	*/
38c2654abSrjs 
48c2654abSrjs /*
58c2654abSrjs  * Copyright (C) 2002, 2003, 2004 Cisco Systems Inc,
68c2654abSrjs  * All rights reserved.
78c2654abSrjs  *
88c2654abSrjs  * Redistribution and use in source and binary forms, with or without
98c2654abSrjs  * modification, are permitted provided that the following conditions
108c2654abSrjs  * are met:
118c2654abSrjs  * 1. Redistributions of source code must retain the above copyright
128c2654abSrjs  *    notice, this list of conditions and the following disclaimer.
138c2654abSrjs  * 2. Redistributions in binary form must reproduce the above copyright
148c2654abSrjs  *    notice, this list of conditions and the following disclaimer in the
158c2654abSrjs  *    documentation and/or other materials provided with the distribution.
168c2654abSrjs  * 3. Neither the name of the project nor the names of its contributors
178c2654abSrjs  *    may be used to endorse or promote products derived from this software
188c2654abSrjs  *    without specific prior written permission.
198c2654abSrjs  *
208c2654abSrjs  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
218c2654abSrjs  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
228c2654abSrjs  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238c2654abSrjs  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
248c2654abSrjs  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
258c2654abSrjs  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
268c2654abSrjs  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
278c2654abSrjs  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
288c2654abSrjs  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
298c2654abSrjs  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
308c2654abSrjs  * SUCH DAMAGE.
318c2654abSrjs  */
328c2654abSrjs 
338c2654abSrjs #include <sys/cdefs.h>
34*481d3881Srin __KERNEL_RCSID(0, "$NetBSD: sctp_input.c,v 1.18 2024/07/05 04:31:54 rin Exp $");
358c2654abSrjs 
368c2654abSrjs #ifdef _KERNEL_OPT
378c2654abSrjs #include "opt_ipsec.h"
388c2654abSrjs #include "opt_inet.h"
398c2654abSrjs #include "opt_sctp.h"
408c2654abSrjs #endif /* _KERNEL_OPT */
418c2654abSrjs 
428c2654abSrjs #include <sys/param.h>
438c2654abSrjs #include <sys/systm.h>
448c2654abSrjs #include <sys/malloc.h>
458c2654abSrjs #include <sys/mbuf.h>
468c2654abSrjs #include <sys/socket.h>
478c2654abSrjs #include <sys/socketvar.h>
488c2654abSrjs #include <sys/sysctl.h>
498c2654abSrjs #include <sys/domain.h>
508c2654abSrjs #include <sys/protosw.h>
518c2654abSrjs #include <sys/kernel.h>
528c2654abSrjs #include <sys/errno.h>
538c2654abSrjs #include <sys/syslog.h>
548c2654abSrjs 
558c2654abSrjs #include <machine/limits.h>
568c2654abSrjs #include <machine/cpu.h>
578c2654abSrjs 
588c2654abSrjs #include <net/if.h>
598c2654abSrjs #include <net/route.h>
608c2654abSrjs #include <net/if_types.h>
618c2654abSrjs 
628c2654abSrjs #include <netinet/in.h>
638c2654abSrjs #include <netinet/in_systm.h>
648c2654abSrjs #include <netinet/ip.h>
658c2654abSrjs #include <netinet/in_pcb.h>
668c2654abSrjs #include <netinet/in_var.h>
678c2654abSrjs #include <netinet/ip_var.h>
688c2654abSrjs 
698c2654abSrjs #ifdef INET6
708c2654abSrjs #include <netinet/ip6.h>
718c2654abSrjs #include <netinet6/ip6_var.h>
728c2654abSrjs #endif /* INET6 */
738c2654abSrjs 
748c2654abSrjs #include <netinet/ip_icmp.h>
758c2654abSrjs #include <netinet/icmp_var.h>
768c2654abSrjs #include <netinet/sctp_var.h>
778c2654abSrjs #include <netinet/sctp_pcb.h>
788c2654abSrjs #include <netinet/sctp_header.h>
798c2654abSrjs #include <netinet/sctputil.h>
808c2654abSrjs #include <netinet/sctp_output.h>
818c2654abSrjs #include <netinet/sctp_input.h>
828c2654abSrjs #include <netinet/sctp_hashdriver.h>
838c2654abSrjs #include <netinet/sctp_indata.h>
848c2654abSrjs #include <netinet/sctp_asconf.h>
858c2654abSrjs 
868c2654abSrjs #ifdef IPSEC
87505ea976Srjs #include <netipsec/ipsec.h>
88505ea976Srjs #include <netipsec/key.h>
898c2654abSrjs #endif /*IPSEC*/
908c2654abSrjs 
918c2654abSrjs #ifdef SCTP_DEBUG
928c2654abSrjs extern u_int32_t sctp_debug_on;
938c2654abSrjs #endif
948c2654abSrjs 
958c2654abSrjs /* INIT handler */
968c2654abSrjs static void
sctp_handle_init(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_init_chunk * cp,struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets * net)978c2654abSrjs sctp_handle_init(struct mbuf *m, int iphlen, int offset,
988c2654abSrjs     struct sctphdr *sh, struct sctp_init_chunk *cp, struct sctp_inpcb *inp,
998c2654abSrjs     struct sctp_tcb *stcb, struct sctp_nets *net)
1008c2654abSrjs {
1018c2654abSrjs 	struct sctp_init *init;
1028c2654abSrjs 	struct mbuf *op_err;
1038c2654abSrjs #ifdef SCTP_DEBUG
1048c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
1058c2654abSrjs 		printf("sctp_handle_init: handling INIT tcb:%p\n", stcb);
1068c2654abSrjs 	}
1078c2654abSrjs #endif
1088c2654abSrjs 	op_err = NULL;
1098c2654abSrjs 	init = &cp->init;
1108c2654abSrjs 	/* First are we accepting? */
1118c2654abSrjs 	if (((inp->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING) == 0) ||
1128c2654abSrjs 	    (inp->sctp_socket->so_qlimit == 0)) {
1138c2654abSrjs 		sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1148c2654abSrjs 		return;
1158c2654abSrjs 	}
1168c2654abSrjs 	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) {
1178c2654abSrjs 		/* Invalid length */
1188c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1198c2654abSrjs 		sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1208c2654abSrjs 		return;
1218c2654abSrjs 	}
1228c2654abSrjs 	/* validate parameters */
1238c2654abSrjs 	if (init->initiate_tag == 0) {
1248c2654abSrjs 		/* protocol error... send abort */
1258c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1268c2654abSrjs 		sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1278c2654abSrjs 		return;
1288c2654abSrjs 	}
1298c2654abSrjs 	if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) {
1308c2654abSrjs 		/* invalid parameter... send abort */
1318c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1328c2654abSrjs 		sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1338c2654abSrjs 		return;
1348c2654abSrjs 	}
1358c2654abSrjs 	if (init->num_inbound_streams == 0) {
1368c2654abSrjs 		/* protocol error... send abort */
1378c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1388c2654abSrjs 		sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1398c2654abSrjs 		return;
1408c2654abSrjs 	}
1418c2654abSrjs 	if (init->num_outbound_streams == 0) {
1428c2654abSrjs 		/* protocol error... send abort */
1438c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1448c2654abSrjs 		sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1458c2654abSrjs 		return;
1468c2654abSrjs 	}
1478c2654abSrjs 
1488c2654abSrjs 	/* send an INIT-ACK w/cookie */
1498c2654abSrjs #ifdef SCTP_DEBUG
1508c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
1518c2654abSrjs 		printf("sctp_handle_init: sending INIT-ACK\n");
1528c2654abSrjs 	}
1538c2654abSrjs #endif
1548c2654abSrjs 
1558c2654abSrjs 	sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, sh, cp);
1568c2654abSrjs }
1578c2654abSrjs 
1588c2654abSrjs /*
1598c2654abSrjs  * process peer "INIT/INIT-ACK" chunk
1608c2654abSrjs  * returns value < 0 on error
1618c2654abSrjs  */
1628c2654abSrjs 
1638c2654abSrjs static int
sctp_process_init(struct sctp_init_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)1648c2654abSrjs sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
1658c2654abSrjs     struct sctp_nets *net)
1668c2654abSrjs {
1678c2654abSrjs 	struct sctp_init *init;
1688c2654abSrjs 	struct sctp_association *asoc;
1698c2654abSrjs 	struct sctp_nets *lnet;
1708c2654abSrjs 	unsigned int i;
1718c2654abSrjs 
1728c2654abSrjs 	init = &cp->init;
1738c2654abSrjs 	asoc = &stcb->asoc;
1748c2654abSrjs 	/* save off parameters */
1758c2654abSrjs 	asoc->peer_vtag = ntohl(init->initiate_tag);
1768c2654abSrjs 	asoc->peers_rwnd = ntohl(init->a_rwnd);
1778c2654abSrjs 
1788c2654abSrjs 	if (TAILQ_FIRST(&asoc->nets)) {
1798c2654abSrjs 		/* update any ssthresh's that may have a default */
1808c2654abSrjs 		TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) {
1818c2654abSrjs 			lnet->ssthresh = asoc->peers_rwnd;
1828c2654abSrjs 		}
1838c2654abSrjs 	}
1848c2654abSrjs 	if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) {
1858c2654abSrjs 		unsigned int newcnt;
1868c2654abSrjs 		struct sctp_stream_out *outs;
1878c2654abSrjs 		struct sctp_tmit_chunk *chk;
1888c2654abSrjs 
1898c2654abSrjs 		/* cut back on number of streams */
1908c2654abSrjs 		newcnt = ntohs(init->num_inbound_streams);
1918c2654abSrjs 		/* This if is probably not needed but I am cautious */
1928c2654abSrjs 		if (asoc->strmout) {
1938c2654abSrjs 			/* First make sure no data chunks are trapped */
1948c2654abSrjs 			for (i=newcnt; i < asoc->pre_open_streams; i++) {
1958c2654abSrjs 				outs = &asoc->strmout[i];
1968c2654abSrjs 				chk = TAILQ_FIRST(&outs->outqueue);
1978c2654abSrjs 				while (chk) {
1988c2654abSrjs 					TAILQ_REMOVE(&outs->outqueue, chk,
1998c2654abSrjs 						     sctp_next);
2008c2654abSrjs 					asoc->stream_queue_cnt--;
2018c2654abSrjs 					sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL,
2028c2654abSrjs 					    stcb, SCTP_NOTIFY_DATAGRAM_UNSENT,
2038c2654abSrjs 					    chk);
2048c2654abSrjs 					sctp_m_freem(chk->data);
2058c2654abSrjs 					chk->data = NULL;
2068c2654abSrjs 					sctp_free_remote_addr(chk->whoTo);
2078c2654abSrjs 					chk->whoTo = NULL;
2088c2654abSrjs 					chk->asoc = NULL;
2098c2654abSrjs 					/* Free the chunk */
2108c2654abSrjs 					SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2118c2654abSrjs 					sctppcbinfo.ipi_count_chunk--;
2128c2654abSrjs 					if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2138c2654abSrjs 						panic("Chunk count is negative");
2148c2654abSrjs 					}
2158c2654abSrjs 					sctppcbinfo.ipi_gencnt_chunk++;
2168c2654abSrjs 					chk = TAILQ_FIRST(&outs->outqueue);
2178c2654abSrjs 				}
2188c2654abSrjs 			}
2198c2654abSrjs 		}
2208c2654abSrjs 		/* cut back the count and abandon the upper streams */
2218c2654abSrjs 		asoc->pre_open_streams = newcnt;
2228c2654abSrjs 	}
2238c2654abSrjs 	asoc->streamincnt = ntohs(init->num_outbound_streams);
2248c2654abSrjs 	if (asoc->streamincnt > MAX_SCTP_STREAMS) {
2258c2654abSrjs 		asoc->streamincnt = MAX_SCTP_STREAMS;
2268c2654abSrjs 	}
2278c2654abSrjs 
2288c2654abSrjs 	asoc->streamoutcnt = asoc->pre_open_streams;
2298c2654abSrjs 	/* init tsn's */
2308c2654abSrjs 	asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1;
2318c2654abSrjs #ifdef SCTP_MAP_LOGGING
2328c2654abSrjs 	sctp_log_map(0, 5, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
2338c2654abSrjs #endif
2348c2654abSrjs 	/* This is the next one we expect */
2358c2654abSrjs 	asoc->str_reset_seq_in = asoc->asconf_seq_in + 1;
2368c2654abSrjs 
2378c2654abSrjs 	asoc->mapping_array_base_tsn = ntohl(init->initial_tsn);
2388c2654abSrjs 	asoc->cumulative_tsn = asoc->asconf_seq_in;
2398c2654abSrjs 	asoc->last_echo_tsn = asoc->asconf_seq_in;
2408c2654abSrjs 	asoc->advanced_peer_ack_point = asoc->last_acked_seq;
2418c2654abSrjs 	/* open the requested streams */
2428c2654abSrjs 	if (asoc->strmin != NULL) {
2438c2654abSrjs 		/* Free the old ones */
2448c2654abSrjs 		free(asoc->strmin, M_PCB);
2458c2654abSrjs 	}
2468c2654abSrjs 	asoc->strmin = malloc(asoc->streamincnt * sizeof(struct sctp_stream_in),
2478c2654abSrjs 				M_PCB, M_NOWAIT);
2488c2654abSrjs 	if (asoc->strmin == NULL) {
2498c2654abSrjs 		/* we didn't get memory for the streams! */
2508c2654abSrjs #ifdef SCTP_DEBUG
2518c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
2528c2654abSrjs 			printf("process_init: couldn't get memory for the streams!\n");
2538c2654abSrjs 		}
2548c2654abSrjs #endif
2558c2654abSrjs 		return (-1);
2568c2654abSrjs 	}
2578c2654abSrjs 	for (i = 0; i < asoc->streamincnt; i++) {
2588c2654abSrjs 		asoc->strmin[i].stream_no = i;
2598c2654abSrjs 		asoc->strmin[i].last_sequence_delivered = 0xffff;
2608c2654abSrjs 		/*
2618c2654abSrjs 		 * U-stream ranges will be set when the cookie
2628c2654abSrjs 		 * is unpacked. Or for the INIT sender they
2638c2654abSrjs 		 * are un set (if pr-sctp not supported) when the
2648c2654abSrjs 		 * INIT-ACK arrives.
2658c2654abSrjs 		 */
2668c2654abSrjs 		TAILQ_INIT(&asoc->strmin[i].inqueue);
2678c2654abSrjs 		/*
2688c2654abSrjs 		 * we are not on any wheel, pr-sctp streams
2698c2654abSrjs 		 * will go on the wheel when they have data waiting
2708c2654abSrjs 		 * for reorder.
2718c2654abSrjs 		 */
2728c2654abSrjs 		asoc->strmin[i].next_spoke.tqe_next = 0;
2738c2654abSrjs 		asoc->strmin[i].next_spoke.tqe_prev = 0;
2748c2654abSrjs 	}
2758c2654abSrjs 
2768c2654abSrjs 	/*
2778c2654abSrjs 	 * load_address_from_init will put the addresses into the
2788c2654abSrjs 	 * association when the COOKIE is processed or the INIT-ACK
2798c2654abSrjs 	 * is processed. Both types of COOKIE's existing and new
2808c2654abSrjs 	 * call this routine. It will remove addresses that
2818c2654abSrjs 	 * are no longer in the association (for the restarting
2828c2654abSrjs 	 * case where addresses are removed). Up front when the
2838c2654abSrjs 	 * INIT arrives we will discard it if it is a restart
2848c2654abSrjs 	 * and new addresses have been added.
2858c2654abSrjs 	 */
2868c2654abSrjs 	return (0);
2878c2654abSrjs }
2888c2654abSrjs 
2898c2654abSrjs /*
2908c2654abSrjs  * INIT-ACK message processing/consumption
2918c2654abSrjs  * returns value < 0 on error
2928c2654abSrjs  */
2938c2654abSrjs static int
sctp_process_init_ack(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_init_ack_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)2948c2654abSrjs sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
2958c2654abSrjs     struct sctphdr *sh, struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
2968c2654abSrjs     struct sctp_nets *net)
2978c2654abSrjs {
2988c2654abSrjs 	struct sctp_association *asoc;
2998c2654abSrjs 	struct mbuf *op_err;
3008c2654abSrjs 	int retval, abort_flag;
3018c2654abSrjs 	uint32_t initack_limit;
3028c2654abSrjs 	/* First verify that we have no illegal param's */
3038c2654abSrjs 	abort_flag = 0;
3048c2654abSrjs 	op_err = NULL;
3058c2654abSrjs 
3068c2654abSrjs 	op_err = sctp_arethere_unrecognized_parameters(m,
3078c2654abSrjs 	    (offset+sizeof(struct sctp_init_chunk)) ,
3088c2654abSrjs 	    &abort_flag, (struct sctp_chunkhdr *)cp);
3098c2654abSrjs 	if (abort_flag) {
3108c2654abSrjs 		/* Send an abort and notify peer */
3118c2654abSrjs 		if (op_err != NULL) {
3128c2654abSrjs 			sctp_send_operr_to(m, iphlen, op_err, cp->init.initiate_tag);
3138c2654abSrjs 		} else {
3148c2654abSrjs 			/*
3158c2654abSrjs 			 * Just notify (abort_assoc does this if
3168c2654abSrjs 			 * we send an abort).
3178c2654abSrjs 			 */
3188c2654abSrjs 			sctp_abort_notification(stcb, 0);
3198c2654abSrjs 			/*
3208c2654abSrjs 			 * No sense in further INIT's since
3218c2654abSrjs 			 * we will get the same param back
3228c2654abSrjs 			 */
3238c2654abSrjs 			sctp_free_assoc(stcb->sctp_ep, stcb);
3248c2654abSrjs 		}
3258c2654abSrjs 		return (-1);
3268c2654abSrjs 	}
3278c2654abSrjs 	asoc = &stcb->asoc;
3288c2654abSrjs 	/* process the peer's parameters in the INIT-ACK */
3298c2654abSrjs 	retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb, net);
3308c2654abSrjs 	if (retval < 0) {
3318c2654abSrjs 		return (retval);
3328c2654abSrjs 	}
3338c2654abSrjs 
3348c2654abSrjs 	initack_limit = offset + ntohs(cp->ch.chunk_length);
3358c2654abSrjs 	/* load all addresses */
3368c2654abSrjs 	if (sctp_load_addresses_from_init(stcb, m, iphlen,
3378c2654abSrjs 	    (offset + sizeof(struct sctp_init_chunk)), initack_limit, sh,
3388c2654abSrjs 	    NULL)) {
3398c2654abSrjs 		/* Huh, we should abort */
3408c2654abSrjs 		sctp_abort_notification(stcb, 0);
3418c2654abSrjs 		sctp_free_assoc(stcb->sctp_ep, stcb);
3428c2654abSrjs 		return (-1);
3438c2654abSrjs 	}
3448c2654abSrjs 	if (op_err) {
3458c2654abSrjs 		sctp_queue_op_err(stcb, op_err);
3468c2654abSrjs 		/* queuing will steal away the mbuf chain to the out queue */
3478c2654abSrjs 		op_err = NULL;
3488c2654abSrjs 	}
3498c2654abSrjs 	/* extract the cookie and queue it to "echo" it back... */
3508c2654abSrjs 	stcb->asoc.overall_error_count = 0;
3518c2654abSrjs 	net->error_count = 0;
3528c2654abSrjs 	retval = sctp_send_cookie_echo(m, offset, stcb, net);
3538c2654abSrjs 	if (retval < 0) {
3548c2654abSrjs 		/*
3558c2654abSrjs 		 * No cookie, we probably should send a op error.
3568c2654abSrjs 		 * But in any case if there is no cookie in the INIT-ACK,
3578c2654abSrjs 		 * we can abandon the peer, its broke.
3588c2654abSrjs 		 */
3598c2654abSrjs 		if (retval == -3) {
3608c2654abSrjs 			/* We abort with an error of missing mandatory param */
3618c2654abSrjs 			op_err =
3628c2654abSrjs 			    sctp_generate_invmanparam(SCTP_CAUSE_MISS_PARAM);
3638c2654abSrjs 			if (op_err) {
3648c2654abSrjs 				/*
3658c2654abSrjs 				 * Expand beyond to include the mandatory
3668c2654abSrjs 				 * param cookie
3678c2654abSrjs 				 */
3688c2654abSrjs 				struct sctp_inv_mandatory_param *mp;
3698c2654abSrjs 				op_err->m_len =
3708c2654abSrjs 				    sizeof(struct sctp_inv_mandatory_param);
3718c2654abSrjs 				mp = mtod(op_err,
3728c2654abSrjs 				    struct sctp_inv_mandatory_param *);
3738c2654abSrjs 				/* Subtract the reserved param */
3748c2654abSrjs 				mp->length =
3758c2654abSrjs 				    htons(sizeof(struct sctp_inv_mandatory_param) - 2);
3768c2654abSrjs 				mp->num_param = htonl(1);
3778c2654abSrjs 				mp->param = htons(SCTP_STATE_COOKIE);
3788c2654abSrjs 				mp->resv = 0;
3798c2654abSrjs 			}
3808c2654abSrjs 			sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
3818c2654abSrjs 			    sh, op_err);
3828c2654abSrjs 		}
3838c2654abSrjs 		return (retval);
3848c2654abSrjs 	}
3858c2654abSrjs 
3868c2654abSrjs 	/*
3878c2654abSrjs 	 * Cancel the INIT timer, We do this first before queueing
388a136e22aSandvar 	 * the cookie. We always cancel at the primary to assume that
38934908c48Sandvar 	 * we are cancelling the timer started by the INIT which always
3908c2654abSrjs 	 * goes to the primary.
3918c2654abSrjs 	 */
3928c2654abSrjs 	sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb,
3938c2654abSrjs 	    asoc->primary_destination);
3948c2654abSrjs 
3958c2654abSrjs 	/* calculate the RTO */
3968c2654abSrjs 	net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered);
3978c2654abSrjs 
3988c2654abSrjs 	return (0);
3998c2654abSrjs }
4008c2654abSrjs 
4018c2654abSrjs static void
sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)4028c2654abSrjs sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
4038c2654abSrjs     struct sctp_tcb *stcb, struct sctp_nets *net)
4048c2654abSrjs {
4058c2654abSrjs 	struct sockaddr_storage store;
4068c2654abSrjs 	struct sockaddr_in *sin;
4078c2654abSrjs 	struct sockaddr_in6 *sin6;
4088c2654abSrjs 	struct sctp_nets *r_net;
4098c2654abSrjs 	struct timeval tv;
4108c2654abSrjs 
4118c2654abSrjs 	if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) {
4128c2654abSrjs 		/* Invalid length */
4138c2654abSrjs 		return;
4148c2654abSrjs 	}
4158c2654abSrjs 
4168c2654abSrjs 	sin = (struct sockaddr_in *)&store;
4178c2654abSrjs 	sin6 = (struct sockaddr_in6 *)&store;
4188c2654abSrjs 
4198c2654abSrjs 	memset(&store, 0, sizeof(store));
4208c2654abSrjs 	if (cp->heartbeat.hb_info.addr_family == AF_INET &&
4218c2654abSrjs 	    cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) {
4228c2654abSrjs 		sin->sin_family = cp->heartbeat.hb_info.addr_family;
4238c2654abSrjs 		sin->sin_len = cp->heartbeat.hb_info.addr_len;
4248c2654abSrjs 		sin->sin_port = stcb->rport;
4258c2654abSrjs 		memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address,
4268c2654abSrjs 		    sizeof(sin->sin_addr));
4278c2654abSrjs 	} else if (cp->heartbeat.hb_info.addr_family == AF_INET6 &&
4288c2654abSrjs 	    cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) {
4298c2654abSrjs 		sin6->sin6_family = cp->heartbeat.hb_info.addr_family;
4308c2654abSrjs 		sin6->sin6_len = cp->heartbeat.hb_info.addr_len;
4318c2654abSrjs 		sin6->sin6_port = stcb->rport;
4328c2654abSrjs 		memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address,
4338c2654abSrjs 		    sizeof(sin6->sin6_addr));
4348c2654abSrjs 	} else {
4358c2654abSrjs #ifdef SCTP_DEBUG
4368c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
4378c2654abSrjs 			printf("unsupported address family");
4388c2654abSrjs 		}
4398c2654abSrjs #endif
4408c2654abSrjs 		return;
4418c2654abSrjs 	}
4428c2654abSrjs 	r_net = sctp_findnet(stcb, (struct sockaddr *)sin);
4438c2654abSrjs 	if (r_net == NULL) {
4448c2654abSrjs #ifdef SCTP_DEBUG
4458c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
4468c2654abSrjs 			printf("Huh? I can't find the address I sent it to, discard\n");
4478c2654abSrjs 		}
4488c2654abSrjs #endif
4498c2654abSrjs 		return;
4508c2654abSrjs 	}
4518c2654abSrjs 	if ((r_net && (r_net->dest_state & SCTP_ADDR_UNCONFIRMED)) &&
4528c2654abSrjs 	    (r_net->heartbeat_random1 == cp->heartbeat.hb_info.random_value1) &&
4538c2654abSrjs 	    (r_net->heartbeat_random2 == cp->heartbeat.hb_info.random_value2)) {
4548c2654abSrjs 		/*
4558c2654abSrjs 		 * If the its a HB and it's random value is correct when
4568c2654abSrjs 		 * can confirm the destination.
4578c2654abSrjs 		 */
4588c2654abSrjs 		r_net->dest_state &= ~SCTP_ADDR_UNCONFIRMED;
4598c2654abSrjs 		sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
4608c2654abSrjs 		    stcb, 0, (void *)r_net);
4618c2654abSrjs 	}
4628c2654abSrjs 	r_net->error_count = 0;
4638c2654abSrjs 	r_net->hb_responded = 1;
4648c2654abSrjs 	tv.tv_sec = cp->heartbeat.hb_info.time_value_1;
4658c2654abSrjs 	tv.tv_usec = cp->heartbeat.hb_info.time_value_2;
4668c2654abSrjs 	if (r_net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
4678c2654abSrjs 		r_net->dest_state = SCTP_ADDR_REACHABLE;
4688c2654abSrjs 		sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
4698c2654abSrjs 		    SCTP_HEARTBEAT_SUCCESS, (void *)r_net);
4708c2654abSrjs 
4718c2654abSrjs 		/* now was it the primary? if so restore */
4728c2654abSrjs 		if (r_net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
4738c2654abSrjs 			sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, r_net);
4748c2654abSrjs 		}
4758c2654abSrjs 	}
4768c2654abSrjs 	/* Now lets do a RTO with this */
4778c2654abSrjs 	r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv);
4788c2654abSrjs }
4798c2654abSrjs 
4808c2654abSrjs static void
sctp_handle_abort(struct sctp_abort_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)4818c2654abSrjs sctp_handle_abort(struct sctp_abort_chunk *cp,
4828c2654abSrjs     struct sctp_tcb *stcb, struct sctp_nets *net)
4838c2654abSrjs {
4848c2654abSrjs 
4858c2654abSrjs #ifdef SCTP_DEBUG
4868c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
4878c2654abSrjs 		printf("sctp_handle_abort: handling ABORT\n");
4888c2654abSrjs 	}
4898c2654abSrjs #endif
4908c2654abSrjs 	if (stcb == NULL)
4918c2654abSrjs 		return;
4928c2654abSrjs 	/* verify that the destination addr is in the association */
4938c2654abSrjs 	/* ignore abort for addresses being deleted */
4948c2654abSrjs 
4958c2654abSrjs 	/* stop any receive timers */
4968c2654abSrjs 	sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net);
4978c2654abSrjs 	/* notify user of the abort and clean up... */
4988c2654abSrjs 	sctp_abort_notification(stcb, 0);
4998c2654abSrjs 	/* free the tcb */
5008c2654abSrjs 	sctp_free_assoc(stcb->sctp_ep, stcb);
5018c2654abSrjs #ifdef SCTP_DEBUG
5028c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
5038c2654abSrjs 		printf("sctp_handle_abort: finished\n");
5048c2654abSrjs 	}
5058c2654abSrjs #endif
5068c2654abSrjs }
5078c2654abSrjs 
5088c2654abSrjs static void
sctp_handle_shutdown(struct sctp_shutdown_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net,int * abort_flag)5098c2654abSrjs sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
5108c2654abSrjs     struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag)
5118c2654abSrjs {
5128c2654abSrjs 	struct sctp_association *asoc;
5138c2654abSrjs 	int some_on_streamwheel;
5148c2654abSrjs 
5158c2654abSrjs #ifdef SCTP_DEBUG
5168c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
5178c2654abSrjs 		printf("sctp_handle_shutdown: handling SHUTDOWN\n");
5188c2654abSrjs 	}
5198c2654abSrjs #endif
5208c2654abSrjs 	if (stcb == NULL)
5218c2654abSrjs 		return;
5228c2654abSrjs 
5238c2654abSrjs 	if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) ||
5248c2654abSrjs 	    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
5258c2654abSrjs 	    return;
5268c2654abSrjs 	}
5278c2654abSrjs 
5288c2654abSrjs 	if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) {
5298c2654abSrjs 		/* update current data status */
5308c2654abSrjs #ifdef SCTP_DEBUG
5318c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
5328c2654abSrjs 			printf("Warning Shutdown NOT the expected size.. skipping (%d:%d)\n",
5338c2654abSrjs 			       ntohs(cp->ch.chunk_length),
5348c2654abSrjs 			       (int)sizeof(struct sctp_shutdown_chunk));
5358c2654abSrjs 		}
5368c2654abSrjs #endif
5378c2654abSrjs 		return;
5388c2654abSrjs 	} else {
5398c2654abSrjs 		sctp_update_acked(stcb, cp, net, abort_flag);
5408c2654abSrjs 	}
5418c2654abSrjs 	asoc = &stcb->asoc;
5428c2654abSrjs 	/* goto SHUTDOWN_RECEIVED state to block new requests */
5438c2654abSrjs 	if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
5448c2654abSrjs 	    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) {
5458c2654abSrjs 		asoc->state = SCTP_STATE_SHUTDOWN_RECEIVED;
5468c2654abSrjs #ifdef SCTP_DEBUG
5478c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
5488c2654abSrjs 			printf("Moving to SHUTDOWN-RECEIVED state\n");
5498c2654abSrjs 		}
5508c2654abSrjs #endif
5518c2654abSrjs 		/* notify upper layer that peer has initiated a shutdown */
5528c2654abSrjs 		sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL);
5538c2654abSrjs 
5548c2654abSrjs 		if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5558c2654abSrjs  		    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
5568c2654abSrjs 
5578c2654abSrjs 			/* Set the flag so we cannot send more, we
5588c2654abSrjs 			 * would call the function but we don't want to
5598c2654abSrjs 			 * wake up the ulp necessarily.
5608c2654abSrjs 			 */
5618c2654abSrjs #if defined(__FreeBSD__) && __FreeBSD_version >= 502115
5628c2654abSrjs 			stcb->sctp_ep->sctp_socket->so_rcv.sb_state |= SBS_CANTSENDMORE;
5638c2654abSrjs #else
5648c2654abSrjs 			stcb->sctp_ep->sctp_socket->so_state |= SS_CANTSENDMORE;
5658c2654abSrjs #endif
5668c2654abSrjs 		}
5678c2654abSrjs 		/* reset time */
5688c2654abSrjs 		SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
5698c2654abSrjs 	}
5708c2654abSrjs 	if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) {
5718c2654abSrjs 		/*
5728c2654abSrjs 		 * stop the shutdown timer, since we WILL move
5738c2654abSrjs 		 * to SHUTDOWN-ACK-SENT.
5748c2654abSrjs 		 */
5758c2654abSrjs 		sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net);
5768c2654abSrjs 	}
5778c2654abSrjs 	/* Now are we there yet? */
5788c2654abSrjs 	some_on_streamwheel = 0;
5798c2654abSrjs 	if (!TAILQ_EMPTY(&asoc->out_wheel)) {
5808c2654abSrjs 		/* Check to see if some data queued */
5818c2654abSrjs 		struct sctp_stream_out *outs;
5828c2654abSrjs 		TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
5838c2654abSrjs 			if (!TAILQ_EMPTY(&outs->outqueue)) {
5848c2654abSrjs 				some_on_streamwheel = 1;
5858c2654abSrjs 				break;
5868c2654abSrjs 			}
5878c2654abSrjs 		}
5888c2654abSrjs 	}
5898c2654abSrjs #ifdef SCTP_DEBUG
5908c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
5918c2654abSrjs 		printf("some_on_streamwheel:%d send_q_empty:%d sent_q_empty:%d\n",
5928c2654abSrjs 		       some_on_streamwheel,
5938c2654abSrjs 		       !TAILQ_EMPTY(&asoc->send_queue),
5948c2654abSrjs 		       !TAILQ_EMPTY(&asoc->sent_queue));
5958c2654abSrjs 	}
5968c2654abSrjs #endif
5978c2654abSrjs  	if (!TAILQ_EMPTY(&asoc->send_queue) ||
5988c2654abSrjs 	    !TAILQ_EMPTY(&asoc->sent_queue) ||
5998c2654abSrjs 	    some_on_streamwheel) {
6008c2654abSrjs 		/* By returning we will push more data out */
6018c2654abSrjs 		return;
6028c2654abSrjs 	} else {
6038c2654abSrjs 		/* no outstanding data to send, so move on... */
6048c2654abSrjs 		/* send SHUTDOWN-ACK */
6058c2654abSrjs 		sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
6068c2654abSrjs 		/* move to SHUTDOWN-ACK-SENT state */
6078c2654abSrjs 		asoc->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
6088c2654abSrjs #ifdef SCTP_DEBUG
6098c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
6108c2654abSrjs 			printf("moving to SHUTDOWN_ACK state\n");
6118c2654abSrjs 		}
6128c2654abSrjs #endif
6138c2654abSrjs 		/* start SHUTDOWN timer */
6148c2654abSrjs 		sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep,
6158c2654abSrjs 		    stcb, net);
6168c2654abSrjs 	}
6178c2654abSrjs }
6188c2654abSrjs 
6198c2654abSrjs static void
sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)6208c2654abSrjs sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
6218c2654abSrjs     struct sctp_tcb *stcb, struct sctp_nets *net)
6228c2654abSrjs {
6238c2654abSrjs 	struct sctp_association *asoc;
6248c2654abSrjs 
6258c2654abSrjs #ifdef SCTP_DEBUG
6268c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
6278c2654abSrjs 		printf("sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n");
6288c2654abSrjs 	}
6298c2654abSrjs #endif
6308c2654abSrjs 	if (stcb == NULL)
6318c2654abSrjs 		return;
6328c2654abSrjs 
6338c2654abSrjs 	asoc = &stcb->asoc;
6348c2654abSrjs 	/* process according to association state */
6358c2654abSrjs 	if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
6368c2654abSrjs 	    (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
6378c2654abSrjs 		/* unexpected SHUTDOWN-ACK... so ignore... */
6388c2654abSrjs 		return;
6398c2654abSrjs 	}
6408c2654abSrjs 	/* are the queues empty? */
6418c2654abSrjs 	if (!TAILQ_EMPTY(&asoc->send_queue) ||
6428c2654abSrjs 	    !TAILQ_EMPTY(&asoc->sent_queue) ||
6438c2654abSrjs 	    !TAILQ_EMPTY(&asoc->out_wheel)) {
6448c2654abSrjs 		sctp_report_all_outbound(stcb);
6458c2654abSrjs 	}
6468c2654abSrjs 	/* stop the timer */
6478c2654abSrjs 	sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net);
6488c2654abSrjs 	/* send SHUTDOWN-COMPLETE */
6498c2654abSrjs 	sctp_send_shutdown_complete(stcb, net);
6508c2654abSrjs 	/* notify upper layer protocol */
6518c2654abSrjs 	sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL);
6528c2654abSrjs 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6538c2654abSrjs 	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
6548c2654abSrjs 		stcb->sctp_ep->sctp_flags &= ~SCTP_PCB_FLAGS_CONNECTED;
6558c2654abSrjs 		/* Set the connected flag to disconnected */
6568c2654abSrjs 		stcb->sctp_ep->sctp_socket->so_snd.sb_cc = 0;
6578c2654abSrjs 		stcb->sctp_ep->sctp_socket->so_snd.sb_mbcnt = 0;
6588c2654abSrjs 		soisdisconnected(stcb->sctp_ep->sctp_socket);
6598c2654abSrjs 	}
6608c2654abSrjs 	/* free the TCB but first save off the ep */
6618c2654abSrjs 	sctp_free_assoc(stcb->sctp_ep, stcb);
6628c2654abSrjs }
6638c2654abSrjs 
6648c2654abSrjs /*
6658c2654abSrjs  * Skip past the param header and then we will find the chunk that
6668c2654abSrjs  * caused the problem. There are two possiblities ASCONF or FWD-TSN
6678c2654abSrjs  * other than that and our peer must be broken.
6688c2654abSrjs  */
6698c2654abSrjs static void
sctp_process_unrecog_chunk(struct sctp_tcb * stcb,struct sctp_paramhdr * phdr,struct sctp_nets * net)6708c2654abSrjs sctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr,
6718c2654abSrjs     struct sctp_nets *net)
6728c2654abSrjs {
6738c2654abSrjs 	struct sctp_chunkhdr *chk;
6748c2654abSrjs 
6758c2654abSrjs 	chk = (struct sctp_chunkhdr *)((vaddr_t)phdr + sizeof(*phdr));
6768c2654abSrjs 	switch (chk->chunk_type) {
6778c2654abSrjs 	case SCTP_ASCONF_ACK:
6788c2654abSrjs #ifdef SCTP_DEBUG
6798c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
6808c2654abSrjs 			printf("Strange peer, snds ASCONF but does not recongnize asconf-ack?\n");
6818c2654abSrjs 		}
6828c2654abSrjs #endif
683a14ed5aeSkamil 		/* FALLTHROUGH */
6848c2654abSrjs 	case SCTP_ASCONF:
6858c2654abSrjs #ifdef SCTP_DEBUG
6868c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
6878c2654abSrjs 			printf("Peer does not support ASCONF/ASCONF-ACK chunks\n");
6888c2654abSrjs 		}
6898c2654abSrjs #endif /* SCTP_DEBUG */
6908c2654abSrjs 		sctp_asconf_cleanup(stcb, net);
6918c2654abSrjs 		break;
6928c2654abSrjs 	case SCTP_FORWARD_CUM_TSN:
6938c2654abSrjs 		stcb->asoc.peer_supports_prsctp = 0;
6948c2654abSrjs 		break;
6958c2654abSrjs 	default:
6968c2654abSrjs #ifdef SCTP_DEBUG
6978c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
6988c2654abSrjs 			printf("Peer does not support chunk type %d(%x)??\n",
6998c2654abSrjs 			       chk->chunk_type, (u_int)chk->chunk_type);
7008c2654abSrjs 		}
7018c2654abSrjs #endif
7028c2654abSrjs 		break;
7038c2654abSrjs 	}
7048c2654abSrjs }
7058c2654abSrjs 
7068c2654abSrjs /*
7078c2654abSrjs  * Skip past the param header and then we will find the param that
7088c2654abSrjs  * caused the problem.  There are a number of param's in a ASCONF
7098c2654abSrjs  * OR the prsctp param these will turn of specific features.
7108c2654abSrjs  */
7118c2654abSrjs static void
sctp_process_unrecog_param(struct sctp_tcb * stcb,struct sctp_paramhdr * phdr)7128c2654abSrjs sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr)
7138c2654abSrjs {
7148c2654abSrjs 	struct sctp_paramhdr *pbad;
7158c2654abSrjs 
7168c2654abSrjs 	pbad = phdr + 1;
7178c2654abSrjs 	switch (ntohs(pbad->param_type)) {
7188c2654abSrjs 		/* pr-sctp draft */
7198c2654abSrjs 	case SCTP_PRSCTP_SUPPORTED:
7208c2654abSrjs 		stcb->asoc.peer_supports_prsctp = 0;
7218c2654abSrjs 		break;
7228c2654abSrjs 	case SCTP_SUPPORTED_CHUNK_EXT:
7238c2654abSrjs 		break;
7248c2654abSrjs 		/* draft-ietf-tsvwg-addip-sctp */
7258c2654abSrjs 	case SCTP_ECN_NONCE_SUPPORTED:
7268c2654abSrjs 		stcb->asoc.peer_supports_ecn_nonce = 0;
7278c2654abSrjs 		stcb->asoc.ecn_nonce_allowed = 0;
7288c2654abSrjs 		stcb->asoc.ecn_allowed = 0;
7298c2654abSrjs 		break;
7308c2654abSrjs 	case SCTP_ADD_IP_ADDRESS:
7318c2654abSrjs 	case SCTP_DEL_IP_ADDRESS:
7328c2654abSrjs 		stcb->asoc.peer_supports_asconf = 0;
7338c2654abSrjs 		break;
7348c2654abSrjs 	case SCTP_SET_PRIM_ADDR:
7358c2654abSrjs 		stcb->asoc.peer_supports_asconf_setprim = 0;
7368c2654abSrjs 		break;
7378c2654abSrjs 	case SCTP_SUCCESS_REPORT:
7388c2654abSrjs 	case SCTP_ERROR_CAUSE_IND:
7398c2654abSrjs #ifdef SCTP_DEBUG
7408c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
7418c2654abSrjs 			printf("Huh, the peer does not support success? or error cause?\n");
7428c2654abSrjs 			printf("Turning off ASCONF to this strange peer\n");
7438c2654abSrjs 		}
7448c2654abSrjs #endif
7458c2654abSrjs 		stcb->asoc.peer_supports_asconf = 0;
7468c2654abSrjs 		stcb->asoc.peer_supports_asconf_setprim = 0;
7478c2654abSrjs 		break;
7488c2654abSrjs 	default:
7498c2654abSrjs #ifdef SCTP_DEBUG
7508c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
7518c2654abSrjs 			printf("Peer does not support base param type %d(%x)??\n",
7528c2654abSrjs 			    pbad->param_type, (u_int)pbad->param_type);
7538c2654abSrjs 		}
7548c2654abSrjs #endif
7558c2654abSrjs 		break;
7568c2654abSrjs 	}
7578c2654abSrjs }
7588c2654abSrjs 
7598c2654abSrjs static int
sctp_handle_error(struct sctp_chunkhdr * ch,struct sctp_tcb * stcb,struct sctp_nets * net)7608c2654abSrjs sctp_handle_error(struct sctp_chunkhdr *ch,
7618c2654abSrjs     struct sctp_tcb *stcb, struct sctp_nets *net)
7628c2654abSrjs {
7638c2654abSrjs 	int chklen;
7648c2654abSrjs 	struct sctp_paramhdr *phdr;
7658c2654abSrjs 	uint16_t error_type;
7668c2654abSrjs 	uint16_t error_len;
7678c2654abSrjs 	struct sctp_association *asoc;
7688c2654abSrjs 
7698c2654abSrjs 	int adjust;
7708c2654abSrjs 	/* parse through all of the errors and process */
7718c2654abSrjs 	asoc = &stcb->asoc;
7728c2654abSrjs 	phdr = (struct sctp_paramhdr *)((vaddr_t)ch +
7738c2654abSrjs 	    sizeof(struct sctp_chunkhdr));
7748c2654abSrjs 	chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr);
7758c2654abSrjs 	while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) {
7768c2654abSrjs 		/* Process an Error Cause */
7778c2654abSrjs 		error_type = ntohs(phdr->param_type);
7788c2654abSrjs 		error_len = ntohs(phdr->param_length);
7798c2654abSrjs 		if ((error_len > chklen) || (error_len == 0)) {
7808c2654abSrjs 			/* invalid param length for this param */
7818c2654abSrjs #ifdef SCTP_DEBUG
7828c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
7838c2654abSrjs 				printf("Bogus length in error param- chunk left:%d errorlen:%d\n",
7848c2654abSrjs 				       chklen, error_len);
7858c2654abSrjs 			}
7868c2654abSrjs #endif /* SCTP_DEBUG */
7878c2654abSrjs 			return (0);
7888c2654abSrjs 		}
7898c2654abSrjs 		switch (error_type) {
7908c2654abSrjs 		case SCTP_CAUSE_INV_STRM:
7918c2654abSrjs 		case SCTP_CAUSE_MISS_PARAM:
7928c2654abSrjs 		case SCTP_CAUSE_INVALID_PARAM:
7938c2654abSrjs 		case SCTP_CAUSE_NOUSER_DATA:
7948c2654abSrjs #ifdef SCTP_DEBUG
7958c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
7968c2654abSrjs 				printf("Software error we got a %d back? We have a bug :/ (or do they?)\n",
7978c2654abSrjs 				       error_type);
7988c2654abSrjs 			}
7998c2654abSrjs #endif
8008c2654abSrjs 			break;
8018c2654abSrjs 		case SCTP_CAUSE_STALE_COOKIE:
8028c2654abSrjs 			/* We only act if we have echoed a cookie and are waiting. */
8038c2654abSrjs 			if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) {
8048c2654abSrjs 				int *p;
8058c2654abSrjs 				p = (int *)((vaddr_t)phdr + sizeof(*phdr));
8068c2654abSrjs 				/* Save the time doubled */
8078c2654abSrjs 				asoc->cookie_preserve_req = ntohl(*p) << 1;
8088c2654abSrjs 				asoc->stale_cookie_count++;
8098c2654abSrjs 				if (asoc->stale_cookie_count >
8108c2654abSrjs 				    asoc->max_init_times) {
8118c2654abSrjs 					sctp_abort_notification(stcb, 0);
8128c2654abSrjs 					/* now free the asoc */
8138c2654abSrjs 					sctp_free_assoc(stcb->sctp_ep, stcb);
8148c2654abSrjs 					return (-1);
8158c2654abSrjs 				}
8168c2654abSrjs 				/* blast back to INIT state */
8178c2654abSrjs 				asoc->state &= ~SCTP_STATE_COOKIE_ECHOED;
8188c2654abSrjs 				asoc->state |= SCTP_STATE_COOKIE_WAIT;
8198c2654abSrjs 				sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE,
8208c2654abSrjs 				    stcb->sctp_ep, stcb, net);
8218c2654abSrjs 				sctp_send_initiate(stcb->sctp_ep, stcb);
8228c2654abSrjs 			}
8238c2654abSrjs 			break;
8248c2654abSrjs 		case SCTP_CAUSE_UNRESOLV_ADDR:
8258c2654abSrjs 			/*
8268c2654abSrjs 			 * Nothing we can do here, we don't do hostname
8278c2654abSrjs 			 * addresses so if the peer does not like my IPv6 (or
8288c2654abSrjs 			 * IPv4 for that matter) it does not matter. If they
8298c2654abSrjs 			 * don't support that type of address, they can NOT
8308c2654abSrjs 			 * possibly get that packet type... i.e. with no IPv6
83139c3181aSmsaitoh 			 * you can't receive a IPv6 packet. so we can safely
8328c2654abSrjs 			 * ignore this one. If we ever added support for
8338c2654abSrjs 			 * HOSTNAME Addresses, then we would need to do
8348c2654abSrjs 			 * something here.
8358c2654abSrjs 			 */
8368c2654abSrjs 			break;
8378c2654abSrjs 		case SCTP_CAUSE_UNRECOG_CHUNK:
8388c2654abSrjs 			sctp_process_unrecog_chunk(stcb, phdr, net);
8398c2654abSrjs 			break;
8408c2654abSrjs 		case SCTP_CAUSE_UNRECOG_PARAM:
8418c2654abSrjs 			sctp_process_unrecog_param(stcb, phdr);
8428c2654abSrjs 			break;
8438c2654abSrjs 		case SCTP_CAUSE_COOKIE_IN_SHUTDOWN:
8448c2654abSrjs 			/*
8458c2654abSrjs 			 * We ignore this since the timer will drive out a new
8468c2654abSrjs 			 * cookie anyway and there timer will drive us to send
8478c2654abSrjs 			 * a SHUTDOWN_COMPLETE. We can't send one here since
8488c2654abSrjs 			 * we don't have their tag.
8498c2654abSrjs 			 */
8508c2654abSrjs 			break;
8518c2654abSrjs 		case SCTP_CAUSE_DELETEING_LAST_ADDR:
8528c2654abSrjs 		case SCTP_CAUSE_OPERATION_REFUSED:
8538c2654abSrjs 		case SCTP_CAUSE_DELETING_SRC_ADDR:
8548c2654abSrjs 			/* We should NOT get these here, but in a ASCONF-ACK. */
8558c2654abSrjs #ifdef SCTP_DEBUG
8568c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
8578c2654abSrjs 				printf("Peer sends ASCONF errors in a Operational Error?<%d>?\n",
8588c2654abSrjs 				       error_type);
8598c2654abSrjs 			}
8608c2654abSrjs #endif
8618c2654abSrjs 			break;
8628c2654abSrjs 		case SCTP_CAUSE_OUT_OF_RESC:
8638c2654abSrjs 			/*
8648c2654abSrjs 			 * And what, pray tell do we do with the fact
8658c2654abSrjs 			 * that the peer is out of resources? Not
8668c2654abSrjs 			 * really sure we could do anything but abort.
8678c2654abSrjs 			 * I suspect this should have came WITH an
8688c2654abSrjs 			 * abort instead of in a OP-ERROR.
8698c2654abSrjs 			 */
8708c2654abSrjs 			break;
8718c2654abSrjs 	 	default:
8728c2654abSrjs #ifdef SCTP_DEBUG
8738c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
8748c2654abSrjs 				/* don't know what this error cause is... */
8758c2654abSrjs 				printf("sctp_handle_error: unknown error type = 0x%xh\n",
8768c2654abSrjs 				       error_type);
8778c2654abSrjs 			}
8788c2654abSrjs #endif /* SCTP_DEBUG */
8798c2654abSrjs 			break;
8808c2654abSrjs 		}
8818c2654abSrjs 		adjust = SCTP_SIZE32(error_len);
8828c2654abSrjs 		chklen -= adjust;
8838c2654abSrjs 		phdr = (struct sctp_paramhdr *)((vaddr_t)phdr + adjust);
8848c2654abSrjs 	}
8858c2654abSrjs 	return (0);
8868c2654abSrjs }
8878c2654abSrjs 
8888c2654abSrjs static int
sctp_handle_init_ack(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_init_ack_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)8898c2654abSrjs sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
8908c2654abSrjs     struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
8918c2654abSrjs     struct sctp_nets *net)
8928c2654abSrjs {
8938c2654abSrjs 	struct sctp_init_ack *init_ack;
8948c2654abSrjs 	int *state;
8958c2654abSrjs 	struct mbuf *op_err;
8968c2654abSrjs 
8978c2654abSrjs #ifdef SCTP_DEBUG
8988c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
8998c2654abSrjs 		printf("sctp_handle_init_ack: handling INIT-ACK\n");
9008c2654abSrjs 	}
9018c2654abSrjs #endif
9028c2654abSrjs 	if (stcb == NULL) {
9038c2654abSrjs #ifdef SCTP_DEBUG
9048c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
9058c2654abSrjs 			printf("sctp_handle_init_ack: TCB is null\n");
9068c2654abSrjs 		}
9078c2654abSrjs #endif
9088c2654abSrjs 		return (-1);
9098c2654abSrjs 	}
9108c2654abSrjs 	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) {
9118c2654abSrjs 		/* Invalid length */
9128c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
9138c2654abSrjs 		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
9148c2654abSrjs 		    op_err);
9158c2654abSrjs 		return (-1);
9168c2654abSrjs 	}
9178c2654abSrjs 	init_ack = &cp->init;
9188c2654abSrjs 	/* validate parameters */
9198c2654abSrjs 	if (init_ack->initiate_tag == 0) {
9208c2654abSrjs 		/* protocol error... send an abort */
9218c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
9228c2654abSrjs 		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
9238c2654abSrjs 		    op_err);
9248c2654abSrjs 		return (-1);
9258c2654abSrjs 	}
9268c2654abSrjs 	if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) {
9278c2654abSrjs 		/* protocol error... send an abort */
9288c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
9298c2654abSrjs 		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
9308c2654abSrjs 		    op_err);
9318c2654abSrjs 		return (-1);
9328c2654abSrjs 	}
9338c2654abSrjs 	if (init_ack->num_inbound_streams == 0) {
9348c2654abSrjs 		/* protocol error... send an abort */
9358c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
9368c2654abSrjs 		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
9378c2654abSrjs 		    op_err);
9388c2654abSrjs 		return (-1);
9398c2654abSrjs 	}
9408c2654abSrjs 	if (init_ack->num_outbound_streams == 0) {
9418c2654abSrjs 		/* protocol error... send an abort */
9428c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
9438c2654abSrjs 		sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
9448c2654abSrjs 		    op_err);
9458c2654abSrjs 		return (-1);
9468c2654abSrjs 	}
9478c2654abSrjs 
9488c2654abSrjs 	/* process according to association state... */
9498c2654abSrjs 	state = &stcb->asoc.state;
9508c2654abSrjs 	switch (*state & SCTP_STATE_MASK) {
9518c2654abSrjs 	case SCTP_STATE_COOKIE_WAIT:
9528c2654abSrjs 		/* this is the expected state for this chunk */
9538c2654abSrjs 		/* process the INIT-ACK parameters */
9548c2654abSrjs 		if (stcb->asoc.primary_destination->dest_state &
9558c2654abSrjs 		    SCTP_ADDR_UNCONFIRMED) {
9568c2654abSrjs 			/*
9578c2654abSrjs 			 * The primary is where we sent the INIT, we can
9588c2654abSrjs 			 * always consider it confirmed when the INIT-ACK
9598c2654abSrjs 			 * is returned. Do this before we load addresses
9608c2654abSrjs 			 * though.
9618c2654abSrjs 			 */
9628c2654abSrjs 			stcb->asoc.primary_destination->dest_state &=
9638c2654abSrjs 			    ~SCTP_ADDR_UNCONFIRMED;
9648c2654abSrjs 			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
9658c2654abSrjs 			    stcb, 0, (void *)stcb->asoc.primary_destination);
9668c2654abSrjs 		}
9678c2654abSrjs 		if (sctp_process_init_ack(m, iphlen, offset, sh, cp, stcb, net
9688c2654abSrjs 		    ) < 0) {
9698c2654abSrjs 			/* error in parsing parameters */
9708c2654abSrjs #ifdef SCTP_DEBUG
9718c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
9728c2654abSrjs 				printf("sctp_process_init_ack: error in msg, discarding\n");
9738c2654abSrjs 			}
9748c2654abSrjs #endif
9758c2654abSrjs 			return (-1);
9768c2654abSrjs 		}
9778c2654abSrjs 		/* update our state */
9788c2654abSrjs #ifdef SCTP_DEBUG
9798c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
9808c2654abSrjs 			printf("moving to COOKIE-ECHOED state\n");
9818c2654abSrjs 		}
9828c2654abSrjs #endif
9838c2654abSrjs 		if (*state & SCTP_STATE_SHUTDOWN_PENDING) {
9848c2654abSrjs 			*state = SCTP_STATE_COOKIE_ECHOED |
9858c2654abSrjs 				SCTP_STATE_SHUTDOWN_PENDING;
9868c2654abSrjs 		} else {
9878c2654abSrjs 			*state = SCTP_STATE_COOKIE_ECHOED;
9888c2654abSrjs 		}
9898c2654abSrjs 
9908c2654abSrjs 		/* reset the RTO calc */
9918c2654abSrjs 		stcb->asoc.overall_error_count = 0;
9928c2654abSrjs 		SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
9938c2654abSrjs 		/*
9948c2654abSrjs 		 * collapse the init timer back in case of a exponential backoff
9958c2654abSrjs 		 */
9968c2654abSrjs 		sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep,
9978c2654abSrjs 		    stcb, net);
9988c2654abSrjs 		/*
9998c2654abSrjs 		 * the send at the end of the inbound data processing will
10008c2654abSrjs 		 * cause the cookie to be sent
10018c2654abSrjs 		 */
10028c2654abSrjs 		break;
10038c2654abSrjs 	case SCTP_STATE_SHUTDOWN_SENT:
10048c2654abSrjs 		/* incorrect state... discard */
10058c2654abSrjs 		break;
10068c2654abSrjs 	case SCTP_STATE_COOKIE_ECHOED:
10078c2654abSrjs 		/* incorrect state... discard */
10088c2654abSrjs 		break;
10098c2654abSrjs 	case SCTP_STATE_OPEN:
10108c2654abSrjs 		/* incorrect state... discard */
10118c2654abSrjs 		break;
10128c2654abSrjs 	case SCTP_STATE_EMPTY:
10138c2654abSrjs 	case SCTP_STATE_INUSE:
10148c2654abSrjs 	default:
10158c2654abSrjs 		/* incorrect state... discard */
10168c2654abSrjs #ifdef SCTP_DEBUG
10178c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
10188c2654abSrjs 			printf("Leaving handle-init-ack default\n");
10198c2654abSrjs 		}
10208c2654abSrjs #endif
10218c2654abSrjs 		return (-1);
10228c2654abSrjs 		break;
10238c2654abSrjs 	} /* end switch asoc state */
10248c2654abSrjs #ifdef SCTP_DEBUG
10258c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
10268c2654abSrjs 		printf("Leaving handle-init-ack end\n");
10278c2654abSrjs 	}
10288c2654abSrjs #endif
10298c2654abSrjs 	return (0);
10308c2654abSrjs }
10318c2654abSrjs 
10328c2654abSrjs 
10338c2654abSrjs /*
10348c2654abSrjs  * handle a state cookie for an existing association
10358c2654abSrjs  * m: input packet mbuf chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk
10368c2654abSrjs  *    note: this is a "split" mbuf and the cookie signature does not exist
10378c2654abSrjs  * offset: offset into mbuf to the cookie-echo chunk
10388c2654abSrjs  */
10398c2654abSrjs static struct sctp_tcb *
sctp_process_cookie_existing(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_state_cookie * cookie,int cookie_len,struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets * net,struct sockaddr * init_src,int * notification)10408c2654abSrjs sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
10418c2654abSrjs     struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
10428c2654abSrjs     struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets *net,
10438c2654abSrjs     struct sockaddr *init_src, int *notification)
10448c2654abSrjs {
10458c2654abSrjs 	struct sctp_association *asoc;
10468c2654abSrjs 	struct sctp_init_chunk *init_cp, init_buf;
10478c2654abSrjs 	struct sctp_init_ack_chunk *initack_cp, initack_buf;
10488c2654abSrjs 	int chk_length;
10498c2654abSrjs 	int init_offset, initack_offset;
10508c2654abSrjs 	int retval;
10518c2654abSrjs 
10528c2654abSrjs 	/* I know that the TCB is non-NULL from the caller */
10538c2654abSrjs 	asoc = &stcb->asoc;
10548c2654abSrjs 
10558c2654abSrjs 	if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
10568c2654abSrjs 		/* SHUTDOWN came in after sending INIT-ACK */
10578c2654abSrjs 		struct mbuf *op_err;
10588c2654abSrjs 		struct sctp_paramhdr *ph;
10598c2654abSrjs 
10608c2654abSrjs 		sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
10618c2654abSrjs #ifdef SCTP_DEBUG
10628c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
10638c2654abSrjs 			printf("sctp_handle_cookie: got a cookie, while shutting down!\n");
10648c2654abSrjs 		}
10658c2654abSrjs #endif
10668c2654abSrjs 		MGETHDR(op_err, M_DONTWAIT, MT_HEADER);
10678c2654abSrjs 		if (op_err == NULL) {
10688c2654abSrjs 			/* FOOBAR */
10698c2654abSrjs 			return (NULL);
10708c2654abSrjs 		}
10718c2654abSrjs 		/* pre-reserve some space */
10728c2654abSrjs 		op_err->m_data += sizeof(struct ip6_hdr);
10738c2654abSrjs 		op_err->m_data += sizeof(struct sctphdr);
10748c2654abSrjs 		op_err->m_data += sizeof(struct sctp_chunkhdr);
10758c2654abSrjs 		/* Set the len */
10768c2654abSrjs 		op_err->m_len = op_err->m_pkthdr.len = sizeof(struct sctp_paramhdr);
10778c2654abSrjs 		ph = mtod(op_err, struct sctp_paramhdr *);
10788c2654abSrjs 		ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN);
10798c2654abSrjs 		ph->param_length = htons(sizeof(struct sctp_paramhdr));
10808c2654abSrjs 		sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag);
10818c2654abSrjs 		return (NULL);
10828c2654abSrjs 	}
10838c2654abSrjs 	/*
10848c2654abSrjs 	 * find and validate the INIT chunk in the cookie (peer's info)
10858c2654abSrjs 	 * the INIT should start after the cookie-echo header struct
10868c2654abSrjs 	 * (chunk header, state cookie header struct)
10878c2654abSrjs 	 */
10888c2654abSrjs 	init_offset = offset += sizeof(struct sctp_cookie_echo_chunk);
10898c2654abSrjs 
10908c2654abSrjs 	init_cp = (struct sctp_init_chunk *)
10918c2654abSrjs 	    sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk),
10928c2654abSrjs 	    (u_int8_t *)&init_buf);
10938c2654abSrjs 	if (init_cp == NULL) {
10948c2654abSrjs 		/* could not pull a INIT chunk in cookie */
10958c2654abSrjs #ifdef SCTP_DEBUG
10968c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
10978c2654abSrjs 			printf("process_cookie_existing: could not pull INIT chunk hdr\n");
10988c2654abSrjs 		}
10998c2654abSrjs #endif /* SCTP_DEBUG */
11008c2654abSrjs 		return (NULL);
11018c2654abSrjs 	}
11028c2654abSrjs 	chk_length = ntohs(init_cp->ch.chunk_length);
11038c2654abSrjs 	if (init_cp->ch.chunk_type != SCTP_INITIATION) {
11048c2654abSrjs #ifdef SCTP_DEBUG
11058c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
11068c2654abSrjs 			printf("process_cookie_existing: could not find INIT chunk!\n");
11078c2654abSrjs 		}
11088c2654abSrjs #endif /* SCTP_DEBUG */
11098c2654abSrjs 		return (NULL);
11108c2654abSrjs 	}
11118c2654abSrjs 
11128c2654abSrjs 	/*
11138c2654abSrjs 	 * find and validate the INIT-ACK chunk in the cookie (my info)
11148c2654abSrjs 	 * the INIT-ACK follows the INIT chunk
11158c2654abSrjs 	 */
11168c2654abSrjs 	initack_offset = init_offset + SCTP_SIZE32(chk_length);
11178c2654abSrjs 	initack_cp = (struct sctp_init_ack_chunk *)
11188c2654abSrjs 	    sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk),
11198c2654abSrjs 	    (u_int8_t *)&initack_buf);
11208c2654abSrjs 	if (initack_cp == NULL) {
11218c2654abSrjs 		/* could not pull INIT-ACK chunk in cookie */
11228c2654abSrjs #ifdef SCTP_DEBUG
11238c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
11248c2654abSrjs 			printf("process_cookie_existing: could not pull INIT-ACK chunk hdr\n");
11258c2654abSrjs 		}
11268c2654abSrjs #endif /* SCTP_DEBUG */
11278c2654abSrjs 		return (NULL);
11288c2654abSrjs 	}
11298c2654abSrjs 	chk_length = ntohs(initack_cp->ch.chunk_length);
11308c2654abSrjs 	if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) {
11318c2654abSrjs #ifdef SCTP_DEBUG
11328c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
11338c2654abSrjs 			printf("process_cookie_existing: could not find INIT-ACK chunk!\n");
11348c2654abSrjs 		}
11358c2654abSrjs #endif /* SCTP_DEBUG */
11368c2654abSrjs 		return (NULL);
11378c2654abSrjs 	}
11388c2654abSrjs 	if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) &&
11398c2654abSrjs 	    (ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag)) {
11408c2654abSrjs 		/*
11418c2654abSrjs 		 * case D in Section 5.2.4 Table 2: MMAA
11428c2654abSrjs 		 * process accordingly to get into the OPEN state
11438c2654abSrjs 		 */
11448c2654abSrjs 		switch SCTP_GET_STATE(asoc) {
11458c2654abSrjs 		case SCTP_STATE_COOKIE_WAIT:
11468c2654abSrjs 			/*
11478c2654abSrjs 			 * INIT was sent, but got got a COOKIE_ECHO with
11488c2654abSrjs 			 * the correct tags... just accept it...
11498c2654abSrjs 			 */
11508c2654abSrjs 			/* First we must process the INIT !! */
11518c2654abSrjs 			retval = sctp_process_init(init_cp, stcb, net);
11528c2654abSrjs 			if (retval < 0) {
11538c2654abSrjs #ifdef SCTP_DEBUG
11548c2654abSrjs 				printf("process_cookie_existing: INIT processing failed\n");
11558c2654abSrjs #endif
11568c2654abSrjs 				return (NULL);
11578c2654abSrjs 			}
1158d642e5f9Srjs 			/* FALLTHROUGH */
11598c2654abSrjs 			/* intentional fall through to below... */
11608c2654abSrjs 
11618c2654abSrjs 		case SCTP_STATE_COOKIE_ECHOED:
11628c2654abSrjs 			/* Duplicate INIT case */
11638c2654abSrjs 			/* we have already processed the INIT so no problem */
11648c2654abSrjs 			sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb,
11658c2654abSrjs 			    net);
11668c2654abSrjs 			sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
11678c2654abSrjs 			sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, inp, stcb,
11688c2654abSrjs 			    net);
11698c2654abSrjs 			/* update current state */
11708c2654abSrjs 			if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
11718c2654abSrjs 				asoc->state = SCTP_STATE_OPEN |
11728c2654abSrjs 				    SCTP_STATE_SHUTDOWN_PENDING;
11738c2654abSrjs 			} else if ((asoc->state & SCTP_STATE_SHUTDOWN_SENT) == 0) {
11748c2654abSrjs 				/* if ok, move to OPEN state */
11758c2654abSrjs 				asoc->state = SCTP_STATE_OPEN;
11768c2654abSrjs 			}
11778c2654abSrjs 			if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
11788c2654abSrjs 			    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
11798c2654abSrjs 			    (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING))) {
11808c2654abSrjs 				/*
11818c2654abSrjs 				 * Here is where collision would go if we did a
11828c2654abSrjs 				 * connect() and instead got a
11838c2654abSrjs 				 * init/init-ack/cookie done before the
11848c2654abSrjs 				 * init-ack came back..
11858c2654abSrjs 				 */
11868c2654abSrjs 				stcb->sctp_ep->sctp_flags |=
11878c2654abSrjs 				    SCTP_PCB_FLAGS_CONNECTED;
11888c2654abSrjs 				soisconnected(stcb->sctp_ep->sctp_socket);
11898c2654abSrjs 			}
11908c2654abSrjs 			/* notify upper layer */
11918c2654abSrjs 			*notification = SCTP_NOTIFY_ASSOC_UP;
11928c2654abSrjs 			sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb,
11938c2654abSrjs 			    net);
11948c2654abSrjs 			/*
11958c2654abSrjs 			 * since we did not send a HB make sure we don't double
11968c2654abSrjs 			 * things
11978c2654abSrjs 			 */
11988c2654abSrjs 			net->hb_responded = 1;
11998c2654abSrjs 
12008c2654abSrjs 			if (stcb->asoc.sctp_autoclose_ticks &&
12018c2654abSrjs 			    (inp->sctp_flags & SCTP_PCB_FLAGS_AUTOCLOSE)) {
12028c2654abSrjs 				sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE,
12038c2654abSrjs 				    inp, stcb, NULL);
12048c2654abSrjs 			}
12058c2654abSrjs 			break;
12068c2654abSrjs 		default:
12078c2654abSrjs 			/*
12088c2654abSrjs 			 * we're in the OPEN state (or beyond), so peer
12098c2654abSrjs 			 * must have simply lost the COOKIE-ACK
12108c2654abSrjs 			 */
12118c2654abSrjs 			break;
12128c2654abSrjs 		} /* end switch */
12138c2654abSrjs 
12148c2654abSrjs 		/*
12158c2654abSrjs 		 * We ignore the return code here.. not sure if we should
12168c2654abSrjs 		 * somehow abort.. but we do have an existing asoc. This
12178c2654abSrjs 		 * really should not fail.
12188c2654abSrjs 		 */
12198c2654abSrjs 		if (sctp_load_addresses_from_init(stcb, m, iphlen,
12208c2654abSrjs 		    init_offset + sizeof(struct sctp_init_chunk),
12218c2654abSrjs 		    initack_offset, sh, init_src)) {
12228c2654abSrjs #ifdef SCTP_DEBUG
12238c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
12248c2654abSrjs 				printf("Weird cookie load_address failure on cookie existing - 1\n");
12258c2654abSrjs 			}
12268c2654abSrjs #endif
12278c2654abSrjs 			return (NULL);
12288c2654abSrjs 		}
12298c2654abSrjs 
12308c2654abSrjs 		/* respond with a COOKIE-ACK */
12318c2654abSrjs 		sctp_send_cookie_ack(stcb);
12328c2654abSrjs 		return (stcb);
12338c2654abSrjs 	} /* end if */
12348c2654abSrjs 	if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag &&
12358c2654abSrjs 	    ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag &&
12368c2654abSrjs 	    cookie->tie_tag_my_vtag == 0 &&
12378c2654abSrjs 	    cookie->tie_tag_peer_vtag == 0) {
12388c2654abSrjs 		/*
12398c2654abSrjs 		 * case C in Section 5.2.4 Table 2: XMOO
12408c2654abSrjs 		 * silently discard
12418c2654abSrjs 		 */
12428c2654abSrjs 		return (NULL);
12438c2654abSrjs 	}
12448c2654abSrjs 	if (ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag &&
12458c2654abSrjs 	    (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag ||
12468c2654abSrjs 	     init_cp->init.initiate_tag == 0)) {
12478c2654abSrjs 		/*
12488c2654abSrjs 		 * case B in Section 5.2.4 Table 2: MXAA or MOAA
12498c2654abSrjs 		 * my info should be ok, re-accept peer info
12508c2654abSrjs 		 */
12518c2654abSrjs 		sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
12528c2654abSrjs 		sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
12538c2654abSrjs 		sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, inp, stcb, net);
12548c2654abSrjs 		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
12558c2654abSrjs 		/*
12568c2654abSrjs 		 * since we did not send a HB make sure we don't double things
12578c2654abSrjs 		 */
12588c2654abSrjs 		net->hb_responded = 1;
12598c2654abSrjs 		if (stcb->asoc.sctp_autoclose_ticks &&
12608c2654abSrjs 		    (inp->sctp_flags & SCTP_PCB_FLAGS_AUTOCLOSE)) {
12618c2654abSrjs 			sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb,
12628c2654abSrjs 			    NULL);
12638c2654abSrjs 		}
12648c2654abSrjs 		asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
12658c2654abSrjs 		asoc->pre_open_streams =
12668c2654abSrjs 		    ntohs(initack_cp->init.num_outbound_streams);
12678c2654abSrjs 		asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn);
12688c2654abSrjs 		asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out =
12698c2654abSrjs 		    asoc->init_seq_number;
12708c2654abSrjs 		asoc->t3timeout_highest_marked = asoc->asconf_seq_out;
12718c2654abSrjs 		asoc->last_cwr_tsn = asoc->init_seq_number - 1;
12728c2654abSrjs 		asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
12738c2654abSrjs 		asoc->str_reset_seq_in = asoc->init_seq_number;
12748c2654abSrjs 		asoc->advanced_peer_ack_point = asoc->last_acked_seq;
12758c2654abSrjs 
12768c2654abSrjs 		/* process the INIT info (peer's info) */
12778c2654abSrjs 		retval = sctp_process_init(init_cp, stcb, net);
12788c2654abSrjs 		if (retval < 0) {
12798c2654abSrjs #ifdef SCTP_DEBUG
12808c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
12818c2654abSrjs 				printf("process_cookie_existing: INIT processing failed\n");
12828c2654abSrjs 			}
12838c2654abSrjs #endif
12848c2654abSrjs 			return (NULL);
12858c2654abSrjs 		}
12868c2654abSrjs 		if (sctp_load_addresses_from_init(stcb, m, iphlen,
12878c2654abSrjs 		    init_offset + sizeof(struct sctp_init_chunk),
12888c2654abSrjs 		    initack_offset, sh, init_src)) {
12898c2654abSrjs #ifdef SCTP_DEBUG
12908c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
12918c2654abSrjs 				printf("Weird cookie load_address failure on cookie existing - 2\n");
12928c2654abSrjs 			}
12938c2654abSrjs #endif
12948c2654abSrjs 			return (NULL);
12958c2654abSrjs 		}
12968c2654abSrjs 
12978c2654abSrjs 		if ((asoc->state & SCTP_STATE_COOKIE_WAIT) ||
12988c2654abSrjs 		    (asoc->state & SCTP_STATE_COOKIE_ECHOED)) {
12998c2654abSrjs 			*notification = SCTP_NOTIFY_ASSOC_UP;
13008c2654abSrjs 
13018c2654abSrjs 			if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
13028c2654abSrjs 			     (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
13038c2654abSrjs 			    !(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING)) {
13048c2654abSrjs 				stcb->sctp_ep->sctp_flags |=
13058c2654abSrjs 				    SCTP_PCB_FLAGS_CONNECTED;
13068c2654abSrjs 				soisconnected(stcb->sctp_ep->sctp_socket);
13078c2654abSrjs 			}
13088c2654abSrjs 		}
13098c2654abSrjs 		if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
13108c2654abSrjs 			asoc->state = SCTP_STATE_OPEN |
13118c2654abSrjs 			    SCTP_STATE_SHUTDOWN_PENDING;
13128c2654abSrjs 		} else {
13138c2654abSrjs 			asoc->state = SCTP_STATE_OPEN;
13148c2654abSrjs 		}
13158c2654abSrjs 		sctp_send_cookie_ack(stcb);
13168c2654abSrjs 		return (stcb);
13178c2654abSrjs 	}
13188c2654abSrjs 
13198c2654abSrjs 	if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag &&
13208c2654abSrjs 	     ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) &&
13218c2654abSrjs 	    cookie->tie_tag_my_vtag == asoc->my_vtag_nonce &&
13228c2654abSrjs 	    cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce &&
13238c2654abSrjs 	    cookie->tie_tag_peer_vtag != 0) {
13248c2654abSrjs 		/*
13258c2654abSrjs 		 * case A in Section 5.2.4 Table 2: XXMM (peer restarted)
13268c2654abSrjs 		 */
13278c2654abSrjs 		sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
13288c2654abSrjs 		sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, inp, stcb, net);
13298c2654abSrjs 		sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
13308c2654abSrjs 
13318c2654abSrjs 		/* notify upper layer */
13328c2654abSrjs 		*notification = SCTP_NOTIFY_ASSOC_RESTART;
13338c2654abSrjs 
13348c2654abSrjs 		/* send up all the data */
13358c2654abSrjs 		sctp_report_all_outbound(stcb);
13368c2654abSrjs 
13378c2654abSrjs 		/* process the INIT-ACK info (my info) */
13388c2654abSrjs 		asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
13398c2654abSrjs 		asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
13408c2654abSrjs 		asoc->pre_open_streams =
13418c2654abSrjs 		    ntohs(initack_cp->init.num_outbound_streams);
13428c2654abSrjs 		asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn);
13438c2654abSrjs 		asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out =
13448c2654abSrjs 		    asoc->init_seq_number;
13458c2654abSrjs 		asoc->t3timeout_highest_marked = asoc->asconf_seq_out;
13468c2654abSrjs 		asoc->last_cwr_tsn = asoc->init_seq_number - 1;
13478c2654abSrjs 		asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
13488c2654abSrjs 		asoc->str_reset_seq_in = asoc->init_seq_number;
13498c2654abSrjs 
13508c2654abSrjs 		asoc->advanced_peer_ack_point = asoc->last_acked_seq;
13518c2654abSrjs 		if (asoc->mapping_array)
13528c2654abSrjs 			memset(asoc->mapping_array, 0,
13538c2654abSrjs 			    asoc->mapping_array_size);
13548c2654abSrjs 		/* process the INIT info (peer's info) */
13558c2654abSrjs 		retval = sctp_process_init(init_cp, stcb, net);
13568c2654abSrjs 		if (retval < 0) {
13578c2654abSrjs #ifdef SCTP_DEBUG
13588c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
13598c2654abSrjs 				printf("process_cookie_existing: INIT processing failed\n");
13608c2654abSrjs 			}
13618c2654abSrjs #endif
13628c2654abSrjs 			return (NULL);
13638c2654abSrjs 		}
13648c2654abSrjs 
13658c2654abSrjs 		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
13668c2654abSrjs 		/*
13678c2654abSrjs 		 * since we did not send a HB make sure we don't double things
13688c2654abSrjs 		 */
13698c2654abSrjs 		net->hb_responded = 1;
13708c2654abSrjs 
13718c2654abSrjs 		if (sctp_load_addresses_from_init(stcb, m, iphlen,
13728c2654abSrjs 		    init_offset + sizeof(struct sctp_init_chunk),
13738c2654abSrjs 		    initack_offset, sh, init_src)) {
13748c2654abSrjs #ifdef SCTP_DEBUG
13758c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
13768c2654abSrjs 				printf("Weird cookie load_address failure on cookie existing - 3\n");
13778c2654abSrjs 			}
13788c2654abSrjs #endif
13798c2654abSrjs 			return (NULL);
13808c2654abSrjs 		}
13818c2654abSrjs 
13828c2654abSrjs 		if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
13838c2654abSrjs 			asoc->state = SCTP_STATE_OPEN |
13848c2654abSrjs 			    SCTP_STATE_SHUTDOWN_PENDING;
13858c2654abSrjs 		} else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) {
13868c2654abSrjs 			/* move to OPEN state, if not in SHUTDOWN_SENT */
13878c2654abSrjs 			asoc->state = SCTP_STATE_OPEN;
13888c2654abSrjs 		}
13898c2654abSrjs 		/* respond with a COOKIE-ACK */
13908c2654abSrjs 		sctp_send_cookie_ack(stcb);
13918c2654abSrjs 
13928c2654abSrjs 		return (stcb);
13938c2654abSrjs 	}
13948c2654abSrjs 	/* all other cases... */
13958c2654abSrjs 	return (NULL);
13968c2654abSrjs }
13978c2654abSrjs 
13988c2654abSrjs /*
13998c2654abSrjs  * handle a state cookie for a new association
14008c2654abSrjs  * m: input packet mbuf chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk
14018c2654abSrjs  *    note: this is a "split" mbuf and the cookie signature does not exist
14028c2654abSrjs  * offset: offset into mbuf to the cookie-echo chunk
14038c2654abSrjs  * length: length of the cookie chunk
14048c2654abSrjs  * to: where the init was from
14058c2654abSrjs  * returns a new TCB
14068c2654abSrjs  */
14078c2654abSrjs static struct sctp_tcb *
sctp_process_cookie_new(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_state_cookie * cookie,int cookie_len,struct sctp_inpcb * inp,struct sctp_nets ** netp,struct sockaddr * init_src,int * notification)14088c2654abSrjs sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
14098c2654abSrjs     struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
14108c2654abSrjs     struct sctp_inpcb *inp, struct sctp_nets **netp,
14118c2654abSrjs     struct sockaddr *init_src, int *notification)
14128c2654abSrjs {
14138c2654abSrjs 	struct sctp_tcb *stcb;
14148c2654abSrjs 	struct sctp_init_chunk *init_cp, init_buf;
14158c2654abSrjs 	struct sctp_init_ack_chunk *initack_cp, initack_buf;
14168c2654abSrjs 	struct sockaddr_storage sa_store;
14178c2654abSrjs 	struct sockaddr *initack_src = (struct sockaddr *)&sa_store;
14188c2654abSrjs 	struct sockaddr_in *sin;
14198c2654abSrjs 	struct sockaddr_in6 *sin6;
14208c2654abSrjs 	struct sctp_association *asoc;
14218c2654abSrjs 	int chk_length;
14228c2654abSrjs 	int init_offset, initack_offset, initack_limit;
14238c2654abSrjs 	int retval;
14248c2654abSrjs 	int error = 0;
14258c2654abSrjs 	/*
14268c2654abSrjs 	 * find and validate the INIT chunk in the cookie (peer's info)
14278c2654abSrjs 	 * the INIT should start after the cookie-echo header struct
14288c2654abSrjs 	 * (chunk header, state cookie header struct)
14298c2654abSrjs 	 */
14308c2654abSrjs 	init_offset = offset + sizeof(struct sctp_cookie_echo_chunk);
14318c2654abSrjs 	init_cp = (struct sctp_init_chunk *)
14328c2654abSrjs 	    sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk),
14338c2654abSrjs 	    (u_int8_t *)&init_buf);
14348c2654abSrjs 	if (init_cp == NULL) {
14358c2654abSrjs 		/* could not pull a INIT chunk in cookie */
14368c2654abSrjs #ifdef SCTP_DEBUG
14378c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
14388c2654abSrjs 			printf("process_cookie_new: could not pull INIT chunk hdr\n");
14398c2654abSrjs 		}
14408c2654abSrjs #endif /* SCTP_DEBUG */
14418c2654abSrjs 		return (NULL);
14428c2654abSrjs 	}
14438c2654abSrjs 	chk_length = ntohs(init_cp->ch.chunk_length);
14448c2654abSrjs 	if (init_cp->ch.chunk_type != SCTP_INITIATION) {
14458c2654abSrjs #ifdef SCTP_DEBUG
14468c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
14478c2654abSrjs 			printf("HUH? process_cookie_new: could not find INIT chunk!\n");
14488c2654abSrjs 		}
14498c2654abSrjs #endif /* SCTP_DEBUG */
14508c2654abSrjs 		return (NULL);
14518c2654abSrjs 	}
14528c2654abSrjs 
14538c2654abSrjs 	initack_offset = init_offset + SCTP_SIZE32(chk_length);
14548c2654abSrjs 	/*
14558c2654abSrjs 	 * find and validate the INIT-ACK chunk in the cookie (my info)
14568c2654abSrjs 	 * the INIT-ACK follows the INIT chunk
14578c2654abSrjs 	 */
14588c2654abSrjs 	initack_cp = (struct sctp_init_ack_chunk *)
14598c2654abSrjs 	    sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk),
14608c2654abSrjs 	    (u_int8_t *)&initack_buf);
14618c2654abSrjs 	if (initack_cp == NULL) {
14628c2654abSrjs 		/* could not pull INIT-ACK chunk in cookie */
14638c2654abSrjs #ifdef SCTP_DEBUG
14648c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
14658c2654abSrjs 			printf("process_cookie_new: could not pull INIT-ACK chunk hdr\n");
14668c2654abSrjs 		}
14678c2654abSrjs #endif /* SCTP_DEBUG */
14688c2654abSrjs 		return (NULL);
14698c2654abSrjs 	}
14708c2654abSrjs 	chk_length = ntohs(initack_cp->ch.chunk_length);
14718c2654abSrjs 	if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) {
14728c2654abSrjs #ifdef SCTP_DEBUG
14738c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
14748c2654abSrjs 			u_int8_t *pp;
14758c2654abSrjs 			pp = (u_int8_t *)initack_cp;
14768c2654abSrjs 			printf("process_cookie_new: could not find INIT-ACK chunk!\n");
1477146d03e6Sandvar 			printf("Found bytes %x %x %x %x at position %d\n",
14788c2654abSrjs 			    (u_int)pp[0], (u_int)pp[1], (u_int)pp[2],
14798c2654abSrjs 			    (u_int)pp[3], initack_offset);
14808c2654abSrjs 		}
14818c2654abSrjs #endif /* SCTP_DEBUG */
14828c2654abSrjs 		return (NULL);
14838c2654abSrjs 	}
14848c2654abSrjs 	initack_limit = initack_offset + SCTP_SIZE32(chk_length);
14858c2654abSrjs 
14868c2654abSrjs 	/*
14878c2654abSrjs 	 * now that we know the INIT/INIT-ACK are in place,
14888c2654abSrjs 	 * create a new TCB and popluate
14898c2654abSrjs 	 */
14908c2654abSrjs  	stcb = sctp_aloc_assoc(inp, init_src, 0, &error, ntohl(initack_cp->init.initiate_tag));
14918c2654abSrjs 	if (stcb == NULL) {
14928c2654abSrjs 		struct mbuf *op_err;
14938c2654abSrjs 		/* memory problem? */
14948c2654abSrjs #ifdef SCTP_DEBUG
14958c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
14968c2654abSrjs 			printf("process_cookie_new: no room for another TCB!\n");
14978c2654abSrjs 		}
14988c2654abSrjs #endif /* SCTP_DEBUG */
14998c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
15008c2654abSrjs 		sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
15018c2654abSrjs 		    sh, op_err);
15028c2654abSrjs 		return (NULL);
15038c2654abSrjs 	}
15048c2654abSrjs 
15058c2654abSrjs 	/* get the correct sctp_nets */
15068c2654abSrjs 	*netp = sctp_findnet(stcb, init_src);
15078c2654abSrjs 	asoc = &stcb->asoc;
15088c2654abSrjs 	/* get scope variables out of cookie */
15098c2654abSrjs 	asoc->ipv4_local_scope = cookie->ipv4_scope;
15108c2654abSrjs 	asoc->site_scope = cookie->site_scope;
15118c2654abSrjs 	asoc->local_scope = cookie->local_scope;
15128c2654abSrjs 	asoc->loopback_scope = cookie->loopback_scope;
15138c2654abSrjs 
15148c2654abSrjs 	if ((asoc->ipv4_addr_legal != cookie->ipv4_addr_legal) ||
15158c2654abSrjs 	    (asoc->ipv6_addr_legal != cookie->ipv6_addr_legal)) {
15168c2654abSrjs 		struct mbuf *op_err;
15178c2654abSrjs 		/*
15188c2654abSrjs 		 * Houston we have a problem. The EP changed while the cookie
15198c2654abSrjs 		 * was in flight. Only recourse is to abort the association.
15208c2654abSrjs 		 */
15218c2654abSrjs 		op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
15228c2654abSrjs 		sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
15238c2654abSrjs 		    sh, op_err);
15248c2654abSrjs 		return (NULL);
15258c2654abSrjs 	}
15268c2654abSrjs 
15278c2654abSrjs 	/* process the INIT-ACK info (my info) */
15288c2654abSrjs 	asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
15298c2654abSrjs 	asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
15308c2654abSrjs 	asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams);
15318c2654abSrjs 	asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn);
15328c2654abSrjs 	asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number;
15338c2654abSrjs 	asoc->t3timeout_highest_marked = asoc->asconf_seq_out;
15348c2654abSrjs 	asoc->last_cwr_tsn = asoc->init_seq_number - 1;
15358c2654abSrjs 	asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
15368c2654abSrjs 	asoc->str_reset_seq_in = asoc->init_seq_number;
15378c2654abSrjs 
15388c2654abSrjs 	asoc->advanced_peer_ack_point = asoc->last_acked_seq;
15398c2654abSrjs 
15408c2654abSrjs 	/* process the INIT info (peer's info) */
15418c2654abSrjs 	retval = sctp_process_init(init_cp, stcb, *netp);
15428c2654abSrjs 	if (retval < 0) {
15438c2654abSrjs #ifdef SCTP_DEBUG
15448c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
15458c2654abSrjs 			printf("process_cookie_new: INIT processing failed\n");
15468c2654abSrjs 		}
15478c2654abSrjs #endif
15488c2654abSrjs 		sctp_free_assoc(inp, stcb);
15498c2654abSrjs 		return (NULL);
15508c2654abSrjs 	}
15518c2654abSrjs 	/* load all addresses */
15528c2654abSrjs 	if (sctp_load_addresses_from_init(stcb, m, iphlen,
15538c2654abSrjs 	    init_offset + sizeof(struct sctp_init_chunk), initack_offset, sh,
15548c2654abSrjs 	    init_src)) {
15558c2654abSrjs 		sctp_free_assoc(inp, stcb);
15568c2654abSrjs 		return (NULL);
15578c2654abSrjs 	}
15588c2654abSrjs 
15598c2654abSrjs 	/* update current state */
15608c2654abSrjs #ifdef SCTP_DEBUG
15618c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
15628c2654abSrjs 		printf("moving to OPEN state\n");
15638c2654abSrjs 	}
15648c2654abSrjs #endif
15658c2654abSrjs 	if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
15668c2654abSrjs 		asoc->state = SCTP_STATE_OPEN | SCTP_STATE_SHUTDOWN_PENDING;
15678c2654abSrjs 	} else {
15688c2654abSrjs 		asoc->state = SCTP_STATE_OPEN;
15698c2654abSrjs 	}
15708c2654abSrjs 	/* calculate the RTT */
15718c2654abSrjs 	(*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp,
15728c2654abSrjs 	    &cookie->time_entered);
15738c2654abSrjs 
15748c2654abSrjs 	/*
15758c2654abSrjs 	 * if we're doing ASCONFs, check to see if we have any new
15768c2654abSrjs 	 * local addresses that need to get added to the peer (eg.
15778c2654abSrjs 	 * addresses changed while cookie echo in flight).  This needs
15788c2654abSrjs 	 * to be done after we go to the OPEN state to do the correct
15798c2654abSrjs 	 * asconf processing.
15808c2654abSrjs 	 * else, make sure we have the correct addresses in our lists
15818c2654abSrjs 	 */
15828c2654abSrjs 
15838c2654abSrjs 	/* warning, we re-use sin, sin6, sa_store here! */
15848c2654abSrjs 	/* pull in local_address (our "from" address) */
15858c2654abSrjs 	if (cookie->laddr_type == SCTP_IPV4_ADDRESS) {
15868c2654abSrjs 		/* source addr is IPv4 */
15878c2654abSrjs 		sin = (struct sockaddr_in *)initack_src;
15888c2654abSrjs 		memset(sin, 0, sizeof(*sin));
15898c2654abSrjs 		sin->sin_family = AF_INET;
15908c2654abSrjs 		sin->sin_len = sizeof(struct sockaddr_in);
15918c2654abSrjs 		sin->sin_addr.s_addr = cookie->laddress[0];
15928c2654abSrjs 	} else if (cookie->laddr_type == SCTP_IPV6_ADDRESS) {
15938c2654abSrjs 		/* source addr is IPv6 */
15948c2654abSrjs 		sin6 = (struct sockaddr_in6 *)initack_src;
15958c2654abSrjs 		memset(sin6, 0, sizeof(*sin6));
15968c2654abSrjs 		sin6->sin6_family = AF_INET6;
15978c2654abSrjs 		sin6->sin6_len = sizeof(struct sockaddr_in6);
15988c2654abSrjs 		sin6->sin6_scope_id = cookie->scope_id;
15998c2654abSrjs 		memcpy(&sin6->sin6_addr, cookie->laddress,
16008c2654abSrjs 		    sizeof(sin6->sin6_addr));
16018c2654abSrjs 	} else {
16028c2654abSrjs 		sctp_free_assoc(inp, stcb);
16038c2654abSrjs 		return (NULL);
16048c2654abSrjs 	}
16058c2654abSrjs 
16068c2654abSrjs 	sctp_check_address_list(stcb, m, initack_offset +
16078c2654abSrjs 	    sizeof(struct sctp_init_ack_chunk), initack_limit,
16088c2654abSrjs 	    initack_src, cookie->local_scope, cookie->site_scope,
16098c2654abSrjs 	    cookie->ipv4_scope, cookie->loopback_scope);
16108c2654abSrjs 
16118c2654abSrjs 
16128c2654abSrjs 	/* set up to notify upper layer */
16138c2654abSrjs 	*notification = SCTP_NOTIFY_ASSOC_UP;
16148c2654abSrjs 	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
16158c2654abSrjs 	     (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))  &&
16168c2654abSrjs 	    !(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING)) {
16178c2654abSrjs 		/*
16188c2654abSrjs 		 * This is an endpoint that called connect()
16198c2654abSrjs 		 * how it got a cookie that is NEW is a bit of
16208c2654abSrjs 		 * a mystery. It must be that the INIT was sent, but
16218c2654abSrjs 		 * before it got there.. a complete INIT/INIT-ACK/COOKIE
16228c2654abSrjs 		 * arrived. But of course then it should have went to
16238c2654abSrjs 		 * the other code.. not here.. oh well.. a bit of protection
16248c2654abSrjs 		 * is worth having..
16258c2654abSrjs 		 */
16268c2654abSrjs 		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
16278c2654abSrjs 		soisconnected(stcb->sctp_ep->sctp_socket);
16288c2654abSrjs 		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, *netp);
16298c2654abSrjs 	} else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
16308c2654abSrjs 		   (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING)) {
16318c2654abSrjs 		/*
16328c2654abSrjs 		 * We don't want to do anything with this
16338c2654abSrjs 		 * one. Since it is the listening guy. The timer will
16348c2654abSrjs 		 * get started for accepted connections in the caller.
16358c2654abSrjs 		 */
16368c2654abSrjs 		;
16378c2654abSrjs 	} else {
16388c2654abSrjs 		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, *netp);
16398c2654abSrjs 	}
16408c2654abSrjs 	/* since we did not send a HB make sure we don't double things */
16418c2654abSrjs 	(*netp)->hb_responded = 1;
16428c2654abSrjs 
16438c2654abSrjs 	if (stcb->asoc.sctp_autoclose_ticks &&
16448c2654abSrjs 	    (inp->sctp_flags & SCTP_PCB_FLAGS_AUTOCLOSE)) {
16458c2654abSrjs 		sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL);
16468c2654abSrjs 	}
16478c2654abSrjs 
16488c2654abSrjs 	/* respond with a COOKIE-ACK */
16498c2654abSrjs 	sctp_send_cookie_ack(stcb);
16508c2654abSrjs 
16518c2654abSrjs 	return (stcb);
16528c2654abSrjs }
16538c2654abSrjs 
16548c2654abSrjs 
16558c2654abSrjs /*
16568c2654abSrjs  * handles a COOKIE-ECHO message
16578c2654abSrjs  * stcb: modified to either a new or left as existing (non-NULL) TCB
16588c2654abSrjs  */
16598c2654abSrjs static struct mbuf *
sctp_handle_cookie_echo(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_cookie_echo_chunk * cp,struct sctp_inpcb ** inp_p,struct sctp_tcb ** stcb,struct sctp_nets ** netp)16608c2654abSrjs sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
16618c2654abSrjs     struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp,
16628c2654abSrjs     struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp)
16638c2654abSrjs {
16648c2654abSrjs 	struct sctp_state_cookie *cookie;
16658c2654abSrjs 	struct sockaddr_in6 sin6;
16668c2654abSrjs 	struct sockaddr_in sin;
16678c2654abSrjs 	struct sctp_tcb *l_stcb=*stcb;
16688c2654abSrjs 	struct sctp_inpcb *l_inp;
16698c2654abSrjs 	struct sockaddr *to;
16708c2654abSrjs 	struct sctp_pcb *ep;
16718c2654abSrjs 	struct mbuf *m_sig;
16728c2654abSrjs 	uint8_t calc_sig[SCTP_SIGNATURE_SIZE], tmp_sig[SCTP_SIGNATURE_SIZE];
16738c2654abSrjs 	uint8_t *sig;
16748c2654abSrjs 	uint8_t cookie_ok = 0;
16758c2654abSrjs 	unsigned int size_of_pkt, sig_offset, cookie_offset;
16768c2654abSrjs 	unsigned int cookie_len;
16778c2654abSrjs 	struct timeval now;
16788c2654abSrjs 	struct timeval time_expires;
16798c2654abSrjs 	struct sockaddr_storage dest_store;
16808c2654abSrjs 	struct sockaddr *localep_sa = (struct sockaddr *)&dest_store;
16818c2654abSrjs 	struct ip *iph;
16828c2654abSrjs 	int notification = 0;
16838c2654abSrjs 	struct sctp_nets *netl;
16848c2654abSrjs 	int had_a_existing_tcb = 0;
16858c2654abSrjs 
16868c2654abSrjs #ifdef SCTP_DEBUG
16878c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
16888c2654abSrjs 		printf("sctp_handle_cookie: handling COOKIE-ECHO\n");
16898c2654abSrjs 	}
16908c2654abSrjs #endif
16918c2654abSrjs 
16928c2654abSrjs 	if (inp_p == NULL) {
16938c2654abSrjs #ifdef SCTP_DEBUG
16948c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
16958c2654abSrjs 			printf("sctp_handle_cookie: null inp_p!\n");
16968c2654abSrjs 		}
16978c2654abSrjs #endif
16988c2654abSrjs 		return (NULL);
16998c2654abSrjs 	}
17008c2654abSrjs 	/* First get the destination address setup too. */
17018c2654abSrjs 	iph = mtod(m, struct ip *);
17028c2654abSrjs 	if (iph->ip_v == IPVERSION) {
17038c2654abSrjs 		/* its IPv4 */
17048c2654abSrjs 		struct sockaddr_in *sin_d;
17058c2654abSrjs 		sin_d = (struct sockaddr_in *)(localep_sa);
17068c2654abSrjs 		memset(sin_d, 0, sizeof(*sin_d));
17078c2654abSrjs 		sin_d->sin_family = AF_INET;
17088c2654abSrjs 		sin_d->sin_len = sizeof(*sin_d);
17098c2654abSrjs 		sin_d->sin_port = sh->dest_port;
17108c2654abSrjs 		sin_d->sin_addr.s_addr = iph->ip_dst.s_addr ;
17118c2654abSrjs 	} else if (iph->ip_v == (IPV6_VERSION >> 4)) {
17128c2654abSrjs 		/* its IPv6 */
17138c2654abSrjs 		struct ip6_hdr *ip6;
17148c2654abSrjs 		struct sockaddr_in6 *sin6_d;
17158c2654abSrjs 		sin6_d = (struct sockaddr_in6 *)(localep_sa);
17168c2654abSrjs 		memset(sin6_d, 0, sizeof(*sin6_d));
17178c2654abSrjs 		sin6_d->sin6_family = AF_INET6;
17188c2654abSrjs 		sin6_d->sin6_len = sizeof(struct sockaddr_in6);
17198c2654abSrjs 		ip6 = mtod(m, struct ip6_hdr *);
17208c2654abSrjs 		sin6_d->sin6_port = sh->dest_port;
17218c2654abSrjs 		sin6_d->sin6_addr = ip6->ip6_dst;
17228c2654abSrjs 	} else {
17238c2654abSrjs 		return (NULL);
17248c2654abSrjs 	}
17258c2654abSrjs 
17268c2654abSrjs 	cookie = &cp->cookie;
17278c2654abSrjs 	cookie_offset = offset + sizeof(struct sctp_chunkhdr);
17288c2654abSrjs 	cookie_len = ntohs(cp->ch.chunk_length);
17298c2654abSrjs 
17308c2654abSrjs 	/* compute size of packet */
17318c2654abSrjs 	if (m->m_flags & M_PKTHDR) {
17328c2654abSrjs 		size_of_pkt = m->m_pkthdr.len;
17338c2654abSrjs 	} else {
17348c2654abSrjs 		/* Should have a pkt hdr really */
17358c2654abSrjs 		struct mbuf *mat;
17368c2654abSrjs 		mat = m;
17378c2654abSrjs 		size_of_pkt = 0;
17388c2654abSrjs 		while (mat != NULL) {
17398c2654abSrjs 			size_of_pkt += mat->m_len;
17408c2654abSrjs 			mat = mat->m_next;
17418c2654abSrjs 		}
17428c2654abSrjs 	}
17438c2654abSrjs 	if (cookie_len > size_of_pkt ||
17448c2654abSrjs 	    cookie_len < sizeof(struct sctp_cookie_echo_chunk) +
17458c2654abSrjs 	    sizeof(struct sctp_init_chunk) +
17468c2654abSrjs 	    sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) {
17478c2654abSrjs 		/* cookie too long!  or too small */
17488c2654abSrjs #ifdef SCTP_DEBUG
17498c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
17508c2654abSrjs 			printf("sctp_handle_cookie: cookie_len=%u, pkt size=%u\n", cookie_len, size_of_pkt);
17518c2654abSrjs 		}
17528c2654abSrjs #endif /* SCTP_DEBUG */
17538c2654abSrjs 		return (NULL);
17548c2654abSrjs 	}
17555c08ce63Srjs 
17565c08ce63Srjs 	if ((cookie->peerport != sh->src_port) &&
17575c08ce63Srjs 	    (cookie->myport != sh->dest_port) &&
17585c08ce63Srjs 	    (cookie->my_vtag != sh->v_tag)) {
17595c08ce63Srjs 		/*
17605c08ce63Srjs 		 * invalid ports or bad tag.  Note that we always leave
17615c08ce63Srjs 		 * the v_tag in the header in network order and when we
17625c08ce63Srjs 		 * stored it in the my_vtag slot we also left it in network
17635c08ce63Srjs 		 * order. This maintians the match even though it may be in
17645c08ce63Srjs 		 * the opposite byte order of the machine :->
17655c08ce63Srjs 		 */
17665c08ce63Srjs 		return (NULL);
17675c08ce63Srjs 	}
17685c08ce63Srjs 
17698c2654abSrjs 	/*
17708c2654abSrjs 	 * split off the signature into its own mbuf (since it
17718c2654abSrjs 	 * should not be calculated in the sctp_hash_digest_m() call).
17728c2654abSrjs 	 */
17738c2654abSrjs 	sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE;
17748c2654abSrjs 	if (sig_offset > size_of_pkt) {
17758c2654abSrjs 		/* packet not correct size! */
17768c2654abSrjs 		/* XXX this may already be accounted for earlier... */
17778c2654abSrjs #ifdef SCTP_DEBUG
17788c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
17798c2654abSrjs 			printf("sctp_handle_cookie: sig offset=%u, pkt size=%u\n", sig_offset, size_of_pkt);
17808c2654abSrjs 		}
17818c2654abSrjs #endif
17828c2654abSrjs 		return (NULL);
17838c2654abSrjs 	}
17848c2654abSrjs 
17858c2654abSrjs 	m_sig = m_split(m, sig_offset, M_DONTWAIT);
17868c2654abSrjs 	if (m_sig == NULL) {
17878c2654abSrjs 		/* out of memory or ?? */
17888c2654abSrjs #ifdef SCTP_DEBUG
17898c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
17908c2654abSrjs 			printf("sctp_handle_cookie: couldn't m_split the signature\n");
17918c2654abSrjs 		}
17928c2654abSrjs #endif
17938c2654abSrjs 		return (NULL);
17948c2654abSrjs 	}
17958c2654abSrjs 	/*
17968c2654abSrjs 	 * compute the signature/digest for the cookie
17978c2654abSrjs 	 */
17988c2654abSrjs 	ep = &(*inp_p)->sctp_ep;
17998c2654abSrjs 	l_inp = *inp_p;
18008c2654abSrjs 	if (l_stcb) {
18018c2654abSrjs 		SCTP_TCB_UNLOCK(l_stcb);
18028c2654abSrjs 	}
18038c2654abSrjs 	SCTP_INP_RLOCK(l_inp);
18048c2654abSrjs 	if (l_stcb) {
18058c2654abSrjs 		SCTP_TCB_LOCK(l_stcb);
18068c2654abSrjs 	}
18078c2654abSrjs 	/* which cookie is it? */
18088c2654abSrjs 	if ((cookie->time_entered.tv_sec < (long)ep->time_of_secret_change) &&
18098c2654abSrjs 	    (ep->current_secret_number != ep->last_secret_number)) {
18108c2654abSrjs 		/* it's the old cookie */
18118c2654abSrjs #ifdef SCTP_DEBUG
18128c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
18138c2654abSrjs 			printf("sctp_handle_cookie: old cookie sig\n");
18148c2654abSrjs 		}
18158c2654abSrjs #endif
18168c2654abSrjs 		sctp_hash_digest_m((char *)ep->secret_key[(int)ep->last_secret_number],
18178c2654abSrjs 		    SCTP_SECRET_SIZE, m, cookie_offset, calc_sig);
18188c2654abSrjs 	} else {
18198c2654abSrjs 		/* it's the current cookie */
18208c2654abSrjs #ifdef SCTP_DEBUG
18218c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
18228c2654abSrjs 			printf("sctp_handle_cookie: current cookie sig\n");
18238c2654abSrjs 		}
18248c2654abSrjs #endif
18258c2654abSrjs 		sctp_hash_digest_m((char *)ep->secret_key[(int)ep->current_secret_number],
18268c2654abSrjs 		    SCTP_SECRET_SIZE, m, cookie_offset, calc_sig);
18278c2654abSrjs 	}
18288c2654abSrjs 	/* get the signature */
18298c2654abSrjs 	SCTP_INP_RUNLOCK(l_inp);
18308c2654abSrjs 	sig = (u_int8_t *)sctp_m_getptr(m_sig, 0, SCTP_SIGNATURE_SIZE, (u_int8_t *)&tmp_sig);
18318c2654abSrjs 	if (sig == NULL) {
18328c2654abSrjs 		/* couldn't find signature */
18338c2654abSrjs #ifdef SCTP_DEBUG
18348c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
18358c2654abSrjs 			printf("sctp_handle_cookie: couldn't pull the signature\n");
18368c2654abSrjs 		}
18378c2654abSrjs #endif
18388c2654abSrjs 		return (NULL);
18398c2654abSrjs 	}
18408c2654abSrjs 	/* compare the received digest with the computed digest */
18418c2654abSrjs 	if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) != 0) {
18428c2654abSrjs 		/* try the old cookie? */
18438c2654abSrjs 		if ((cookie->time_entered.tv_sec == (long)ep->time_of_secret_change) &&
18448c2654abSrjs 		    (ep->current_secret_number != ep->last_secret_number)) {
18458c2654abSrjs 			/* compute digest with old */
18468c2654abSrjs #ifdef SCTP_DEBUG
18478c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
18488c2654abSrjs 				printf("sctp_handle_cookie: old cookie sig\n");
18498c2654abSrjs 			}
18508c2654abSrjs #endif
18518c2654abSrjs 			sctp_hash_digest_m((char *)ep->secret_key[(int)ep->last_secret_number],
18528c2654abSrjs 			    SCTP_SECRET_SIZE, m, cookie_offset, calc_sig);
18538c2654abSrjs 			/* compare */
18548c2654abSrjs 			if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) == 0)
18558c2654abSrjs 				cookie_ok = 1;
18568c2654abSrjs 		}
18578c2654abSrjs 	} else {
18588c2654abSrjs 		cookie_ok = 1;
18598c2654abSrjs 	}
18608c2654abSrjs 
18618c2654abSrjs 	/*
18628c2654abSrjs 	 * Now before we continue we must reconstruct our mbuf so
18638c2654abSrjs 	 * that normal processing of any other chunks will work.
18648c2654abSrjs 	 */
18658c2654abSrjs 	{
18668c2654abSrjs 		struct mbuf *m_at;
18678c2654abSrjs 		m_at = m;
18688c2654abSrjs 		while (m_at->m_next != NULL) {
18698c2654abSrjs 			m_at = m_at->m_next;
18708c2654abSrjs 		}
18718c2654abSrjs 		m_at->m_next = m_sig;
18728c2654abSrjs 		if (m->m_flags & M_PKTHDR) {
18738c2654abSrjs 			/*
18748c2654abSrjs 			 * We should only do this if and only if the front
18758c2654abSrjs 			 * mbuf has a m_pkthdr... it should in theory.
18768c2654abSrjs 			 */
18778c2654abSrjs 			if (m_sig->m_flags & M_PKTHDR) {
18788c2654abSrjs 				/* Add back to the pkt hdr of main m chain */
18798c2654abSrjs 				m->m_pkthdr.len += m_sig->m_len;
18808c2654abSrjs 			} else {
18818c2654abSrjs 				/*
18828c2654abSrjs 				 * Got a problem, no pkthdr in split chain.
18838c2654abSrjs 				 * TSNH but we will handle it just in case
18848c2654abSrjs 				 */
18858c2654abSrjs 				int mmlen = 0;
18868c2654abSrjs 				struct mbuf *lat;
18878c2654abSrjs 				printf("Warning: Hitting m_split join TSNH code - fixed\n");
18888c2654abSrjs 				lat = m_sig;
18898c2654abSrjs 				while (lat) {
18908c2654abSrjs 					mmlen += lat->m_len;
18918c2654abSrjs 					lat = lat->m_next;
18928c2654abSrjs 				}
18938c2654abSrjs 				m->m_pkthdr.len += mmlen;
18948c2654abSrjs 			}
18958c2654abSrjs 		}
18968c2654abSrjs 	}
18978c2654abSrjs 
18988c2654abSrjs 	if (cookie_ok == 0) {
18998c2654abSrjs #ifdef SCTP_DEBUG
19008c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
19018c2654abSrjs 			printf("handle_cookie_echo: cookie signature validation failed!\n");
19028c2654abSrjs 			printf("offset = %u, cookie_offset = %u, sig_offset = %u\n",
19038c2654abSrjs 			    (u_int32_t)offset, cookie_offset, sig_offset);
19048c2654abSrjs 		}
19058c2654abSrjs #endif
19068c2654abSrjs 		return (NULL);
19078c2654abSrjs 	}
19088c2654abSrjs #ifdef SCTP_DEBUG
19098c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
19108c2654abSrjs 		printf("handle_cookie_echo: cookie signature validation passed\n");
19118c2654abSrjs 	}
19128c2654abSrjs #endif
19138c2654abSrjs 
19148c2654abSrjs 	/*
19158c2654abSrjs 	 * check the cookie timestamps to be sure it's not stale
19168c2654abSrjs 	 */
19178c2654abSrjs 	SCTP_GETTIME_TIMEVAL(&now);
19188c2654abSrjs 	/* Expire time is in Ticks, so we convert to seconds */
19198c2654abSrjs 	time_expires.tv_sec = cookie->time_entered.tv_sec + cookie->cookie_life;
19208c2654abSrjs 	time_expires.tv_usec = cookie->time_entered.tv_usec;
19218c2654abSrjs #ifndef __FreeBSD__
19228c2654abSrjs 	if (timercmp(&now, &time_expires, >))
19238c2654abSrjs #else
19248c2654abSrjs 	if (timevalcmp(&now, &time_expires, >))
19258c2654abSrjs #endif
19268c2654abSrjs 	{
19278c2654abSrjs 		/* cookie is stale! */
19288c2654abSrjs 		struct mbuf *op_err;
19298c2654abSrjs 		struct sctp_stale_cookie_msg *scm;
19308c2654abSrjs 		u_int32_t tim;
19318c2654abSrjs #ifdef SCTP_DEBUG
19328c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
19338c2654abSrjs 			printf("sctp_handle_cookie: got a STALE cookie!\n");
19348c2654abSrjs 		}
19358c2654abSrjs #endif
19368c2654abSrjs 		MGETHDR(op_err, M_DONTWAIT, MT_HEADER);
19378c2654abSrjs 		if (op_err == NULL) {
19388c2654abSrjs 			/* FOOBAR */
19398c2654abSrjs 			return (NULL);
19408c2654abSrjs 		}
19418c2654abSrjs 		/* pre-reserve some space */
19428c2654abSrjs 		op_err->m_data += sizeof(struct ip6_hdr);
19438c2654abSrjs 		op_err->m_data += sizeof(struct sctphdr);
19448c2654abSrjs 		op_err->m_data += sizeof(struct sctp_chunkhdr);
19458c2654abSrjs 
19468c2654abSrjs 		/* Set the len */
19478c2654abSrjs 		op_err->m_len = op_err->m_pkthdr.len = sizeof(struct sctp_stale_cookie_msg);
19488c2654abSrjs 		scm = mtod(op_err, struct sctp_stale_cookie_msg *);
19498c2654abSrjs 		scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE);
19508c2654abSrjs 		scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) +
19518c2654abSrjs 		    (sizeof(u_int32_t))));
19528c2654abSrjs 		/* seconds to usec */
19538c2654abSrjs 		tim = (now.tv_sec - time_expires.tv_sec) * 1000000;
19548c2654abSrjs 		/* add in usec */
19558c2654abSrjs 		if (tim == 0)
19568c2654abSrjs 			tim = now.tv_usec - cookie->time_entered.tv_usec;
19578c2654abSrjs 		scm->time_usec = htonl(tim);
19588c2654abSrjs 		sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag);
19598c2654abSrjs 		return (NULL);
19608c2654abSrjs 	}
19618c2654abSrjs 	/*
19628c2654abSrjs 	 * Now we must see with the lookup address if we have an existing
19638c2654abSrjs 	 * asoc. This will only happen if we were in the COOKIE-WAIT state
19648c2654abSrjs 	 * and a INIT collided with us and somewhere the peer sent the
19658c2654abSrjs 	 * cookie on another address besides the single address our assoc
19668c2654abSrjs 	 * had for him. In this case we will have one of the tie-tags set
19678c2654abSrjs 	 * at least AND the address field in the cookie can be used to
19688c2654abSrjs 	 * look it up.
19698c2654abSrjs 	 */
19708c2654abSrjs 	to = NULL;
19718c2654abSrjs 	if (cookie->addr_type == SCTP_IPV6_ADDRESS) {
19728c2654abSrjs 		memset(&sin6, 0, sizeof(sin6));
19738c2654abSrjs 		sin6.sin6_family = AF_INET6;
19748c2654abSrjs 		sin6.sin6_len = sizeof(sin6);
19758c2654abSrjs 		sin6.sin6_port = sh->src_port;
19768c2654abSrjs 		sin6.sin6_scope_id = cookie->scope_id;
19778c2654abSrjs 		memcpy(&sin6.sin6_addr.s6_addr, cookie->address,
19788c2654abSrjs 		       sizeof(sin6.sin6_addr.s6_addr));
19798c2654abSrjs 		to = (struct sockaddr *)&sin6;
19808c2654abSrjs 	} else if (cookie->addr_type == SCTP_IPV4_ADDRESS) {
19818c2654abSrjs 		memset(&sin, 0, sizeof(sin));
19828c2654abSrjs 		sin.sin_family = AF_INET;
19838c2654abSrjs 		sin.sin_len = sizeof(sin);
19848c2654abSrjs 		sin.sin_port = sh->src_port;
19858c2654abSrjs 		sin.sin_addr.s_addr = cookie->address[0];
19868c2654abSrjs 		to = (struct sockaddr *)&sin;
19878c2654abSrjs 	}
19888c2654abSrjs 
19898c2654abSrjs 	if ((*stcb == NULL) && to) {
19908c2654abSrjs 		/* Yep, lets check */
19918c2654abSrjs 		*stcb = sctp_findassociation_ep_addr(inp_p, to, netp, localep_sa, NULL);
19928c2654abSrjs 		if (*stcb == NULL) {
19938c2654abSrjs 			/* We should have only got back the same inp. If we
19948c2654abSrjs 			 * got back a different ep we have a problem. The original
19958c2654abSrjs 			 * findep got back l_inp and now
19968c2654abSrjs 			 */
19978c2654abSrjs 			if (l_inp != *inp_p) {
19988c2654abSrjs 				printf("Bad problem find_ep got a diff inp then special_locate?\n");
19998c2654abSrjs 			}
20008c2654abSrjs 		}
20018c2654abSrjs 	}
20028c2654abSrjs 
20038c2654abSrjs 	cookie_len -= SCTP_SIGNATURE_SIZE;
20048c2654abSrjs 	if (*stcb == NULL) {
20058c2654abSrjs 		/* this is the "normal" case... get a new TCB */
20068c2654abSrjs #ifdef SCTP_DEBUG
20078c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
20088c2654abSrjs 			printf("sctp_handle_cookie: processing NEW cookie\n");
20098c2654abSrjs 		}
20108c2654abSrjs #endif
20118c2654abSrjs 		*stcb = sctp_process_cookie_new(m, iphlen, offset, sh, cookie,
20128c2654abSrjs 		    cookie_len, *inp_p, netp, to, &notification);
20138c2654abSrjs 		/* now always decrement, since this is the normal
20148c2654abSrjs 		 * case.. we had no tcb when we entered.
20158c2654abSrjs 		 */
20168c2654abSrjs 	} else {
20178c2654abSrjs 		/* this is abnormal... cookie-echo on existing TCB */
20188c2654abSrjs #ifdef SCTP_DEBUG
20198c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
20208c2654abSrjs 			printf("sctp_handle_cookie: processing EXISTING cookie\n");
20218c2654abSrjs 		}
20228c2654abSrjs #endif
20238c2654abSrjs 		had_a_existing_tcb = 1;
20248c2654abSrjs 		*stcb = sctp_process_cookie_existing(m, iphlen, offset, sh,
20258c2654abSrjs 		    cookie, cookie_len, *inp_p, *stcb, *netp, to, &notification);
20268c2654abSrjs 	}
20278c2654abSrjs 
20288c2654abSrjs 	if (*stcb == NULL) {
20298c2654abSrjs 		/* still no TCB... must be bad cookie-echo */
20308c2654abSrjs #ifdef SCTP_DEBUG
20318c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
20328c2654abSrjs 			printf("handle_cookie_echo: ACK! don't have a TCB!\n");
20338c2654abSrjs 		}
20348c2654abSrjs #endif /* SCTP_DEBUG */
20358c2654abSrjs 		return (NULL);
20368c2654abSrjs 	}
20378c2654abSrjs 
20388c2654abSrjs 	/*
20398c2654abSrjs 	 * Ok, we built an association so confirm the address
20408c2654abSrjs 	 * we sent the INIT-ACK to.
20418c2654abSrjs 	 */
20428c2654abSrjs 	netl = sctp_findnet(*stcb, to);
20438c2654abSrjs         /* This code should in theory NOT run but
20448c2654abSrjs 	 */
20458c2654abSrjs 	if (netl == NULL) {
20468c2654abSrjs #ifdef SCTP_DEBUG
20478c2654abSrjs 		printf("TSNH! Huh, why do I need to add this address here?\n");
20488c2654abSrjs #endif
20498c2654abSrjs 		sctp_add_remote_addr(*stcb, to, 0, 100);
20508c2654abSrjs 		netl = sctp_findnet(*stcb, to);
20518c2654abSrjs 	}
20528c2654abSrjs 	if (netl) {
20538c2654abSrjs 		if (netl->dest_state &  SCTP_ADDR_UNCONFIRMED) {
20548c2654abSrjs 			netl->dest_state &= ~SCTP_ADDR_UNCONFIRMED;
20558c2654abSrjs 			sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL,
20568c2654abSrjs 					      netl);
20578c2654abSrjs 			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
20588c2654abSrjs 					(*stcb), 0, (void *)netl);
20598c2654abSrjs 		}
20608c2654abSrjs 	}
20618c2654abSrjs #ifdef SCTP_DEBUG
20628c2654abSrjs 	else {
20638c2654abSrjs 		printf("Could not add source address for some reason\n");
20648c2654abSrjs 	}
20658c2654abSrjs #endif
20668c2654abSrjs 
20678c2654abSrjs 	if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
20688c2654abSrjs 		if (!had_a_existing_tcb ||
20698c2654abSrjs 		    (((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
20708c2654abSrjs 			/*
20718c2654abSrjs 			 * If we have a NEW cookie or the connect never reached
20728c2654abSrjs 			 * the connected state during collision we must do the
20738c2654abSrjs 			 * TCP accept thing.
20748c2654abSrjs 			 */
20758c2654abSrjs 			struct socket *so, *oso;
20768c2654abSrjs 			struct sctp_inpcb *inp;
20778c2654abSrjs 			if (notification == SCTP_NOTIFY_ASSOC_RESTART) {
20788c2654abSrjs 				/*
20798c2654abSrjs 				 * For a restart we will keep the same socket,
20808c2654abSrjs 				 * no need to do anything. I THINK!!
20818c2654abSrjs 				 */
20828c2654abSrjs 				sctp_ulp_notify(notification, *stcb, 0, NULL);
20838c2654abSrjs 				return (m);
20848c2654abSrjs 			}
20858c2654abSrjs 			oso = (*inp_p)->sctp_socket;
20868c2654abSrjs 			SCTP_TCB_UNLOCK((*stcb));
20878c2654abSrjs 			so = sonewconn(oso, SS_ISCONNECTED);
20888c2654abSrjs 			SCTP_INP_WLOCK((*stcb)->sctp_ep);
20898c2654abSrjs 			SCTP_TCB_LOCK((*stcb));
20908c2654abSrjs 			SCTP_INP_WUNLOCK((*stcb)->sctp_ep);
20918c2654abSrjs 			if (so == NULL) {
20928c2654abSrjs 				struct mbuf *op_err;
20938c2654abSrjs 				/* Too many sockets */
20948c2654abSrjs #ifdef SCTP_DEBUG
20958c2654abSrjs 				if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
20968c2654abSrjs 					printf("process_cookie_new: no room for another socket!\n");
20978c2654abSrjs 				}
20988c2654abSrjs #endif /* SCTP_DEBUG */
20998c2654abSrjs 				op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
21008c2654abSrjs 				sctp_abort_association(*inp_p, NULL, m, iphlen,
21018c2654abSrjs 				    sh, op_err);
21028c2654abSrjs 				sctp_free_assoc(*inp_p, *stcb);
21038c2654abSrjs 				return (NULL);
21048c2654abSrjs 			}
21058c2654abSrjs 			inp = (struct sctp_inpcb *)so->so_pcb;
21068c2654abSrjs 			inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE |
21078c2654abSrjs 			    SCTP_PCB_FLAGS_CONNECTED |
21088c2654abSrjs 			    SCTP_PCB_FLAGS_IN_TCPPOOL |
21098c2654abSrjs 			    (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) |
21108c2654abSrjs 			    SCTP_PCB_FLAGS_DONT_WAKE);
21118c2654abSrjs 			inp->sctp_socket = so;
21128c2654abSrjs 
21138c2654abSrjs 			/*
21148c2654abSrjs 			 * Now we must move it from one hash table to another
21158c2654abSrjs 			 * and get the tcb in the right place.
21168c2654abSrjs 			 */
21178c2654abSrjs 			sctp_move_pcb_and_assoc(*inp_p, inp, *stcb);
21188c2654abSrjs 
21198c2654abSrjs 			/* Switch over to the new guy */
21208c2654abSrjs 			*inp_p = inp;
21218c2654abSrjs 
21228c2654abSrjs 			sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp,
21238c2654abSrjs 			    *stcb, *netp);
21248c2654abSrjs 
21258c2654abSrjs 			sctp_ulp_notify(notification, *stcb, 0, NULL);
21268c2654abSrjs 			return (m);
21278c2654abSrjs 		}
21288c2654abSrjs 	}
21298c2654abSrjs 	if ((notification) && ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
21308c2654abSrjs 		sctp_ulp_notify(notification, *stcb, 0, NULL);
21318c2654abSrjs 	}
21328c2654abSrjs 	return (m);
21338c2654abSrjs }
21348c2654abSrjs 
21358c2654abSrjs static void
sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)21368c2654abSrjs sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
21378c2654abSrjs     struct sctp_tcb *stcb, struct sctp_nets *net)
21388c2654abSrjs {
21398c2654abSrjs 	/* cp must not be used, others call this without a c-ack :-) */
21408c2654abSrjs 	struct sctp_association *asoc;
21418c2654abSrjs 
21428c2654abSrjs #ifdef SCTP_DEBUG
21438c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
21448c2654abSrjs 		printf("sctp_handle_cookie_ack: handling COOKIE-ACK\n");
21458c2654abSrjs 	}
21468c2654abSrjs #endif
21478c2654abSrjs 	if (stcb == NULL)
21488c2654abSrjs 		return;
21498c2654abSrjs 
21508c2654abSrjs 	asoc = &stcb->asoc;
21518c2654abSrjs 
21528c2654abSrjs 	sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep, stcb, net);
21538c2654abSrjs 
21548c2654abSrjs 	/* process according to association state */
21558c2654abSrjs 	if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) {
21568c2654abSrjs 		/* state change only needed when I am in right state */
21578c2654abSrjs #ifdef SCTP_DEBUG
21588c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
21598c2654abSrjs 			printf("moving to OPEN state\n");
21608c2654abSrjs 		}
21618c2654abSrjs #endif
21628c2654abSrjs 		if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
21638c2654abSrjs 			asoc->state = SCTP_STATE_OPEN | SCTP_STATE_SHUTDOWN_PENDING;
21648c2654abSrjs 		} else {
21658c2654abSrjs 			asoc->state = SCTP_STATE_OPEN;
21668c2654abSrjs 		}
21678c2654abSrjs 
21688c2654abSrjs 		/* update RTO */
21698c2654abSrjs 		if (asoc->overall_error_count == 0) {
21708c2654abSrjs 			net->RTO = sctp_calculate_rto(stcb, asoc, net,
21718c2654abSrjs 			    &asoc->time_entered);
21728c2654abSrjs 		}
21738c2654abSrjs 		SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
21748c2654abSrjs 		sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL);
21758c2654abSrjs 		if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
21768c2654abSrjs 		    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
21778c2654abSrjs 			stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
21788c2654abSrjs 			soisconnected(stcb->sctp_ep->sctp_socket);
21798c2654abSrjs 		}
21808c2654abSrjs 		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
21818c2654abSrjs 		    stcb, net);
21828c2654abSrjs 		/* since we did not send a HB make sure we don't double things */
21838c2654abSrjs 		net->hb_responded = 1;
21848c2654abSrjs 
21858c2654abSrjs 		if (stcb->asoc.sctp_autoclose_ticks &&
21868c2654abSrjs 		    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_AUTOCLOSE)) {
21878c2654abSrjs 			sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE,
21888c2654abSrjs 			    stcb->sctp_ep, stcb, NULL);
21898c2654abSrjs 		}
21908c2654abSrjs 
21918c2654abSrjs 		/*
21928c2654abSrjs 		 * set ASCONF timer if ASCONFs are pending and allowed
21938c2654abSrjs 		 * (eg. addresses changed when init/cookie echo in flight)
21948c2654abSrjs 		 */
21958c2654abSrjs 		if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_DO_ASCONF) &&
21968c2654abSrjs 		    (stcb->asoc.peer_supports_asconf) &&
21978c2654abSrjs 		    (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) {
21988c2654abSrjs 			sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
21998c2654abSrjs 			    stcb->sctp_ep, stcb,
22008c2654abSrjs 			    stcb->asoc.primary_destination);
22018c2654abSrjs 		}
22028c2654abSrjs 
22038c2654abSrjs 	}
22048c2654abSrjs 	/* Toss the cookie if I can */
22058c2654abSrjs 	sctp_toss_old_cookies(asoc);
22068c2654abSrjs 	if (!TAILQ_EMPTY(&asoc->sent_queue)) {
22078c2654abSrjs 		/* Restart the timer if we have pending data */
22088c2654abSrjs 		struct sctp_tmit_chunk *chk;
22098c2654abSrjs 		chk = TAILQ_FIRST(&asoc->sent_queue);
22108c2654abSrjs 		if (chk) {
22118c2654abSrjs 			sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
22128c2654abSrjs 			    stcb, chk->whoTo);
22138c2654abSrjs 		}
22148c2654abSrjs 	}
22158c2654abSrjs 
22168c2654abSrjs }
22178c2654abSrjs 
22188c2654abSrjs static void
sctp_handle_ecn_echo(struct sctp_ecne_chunk * cp,struct sctp_tcb * stcb)22198c2654abSrjs sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp,
22208c2654abSrjs     struct sctp_tcb *stcb)
22218c2654abSrjs {
22228c2654abSrjs 	struct sctp_nets *net;
22238c2654abSrjs 	struct sctp_tmit_chunk *lchk;
22248c2654abSrjs 	u_int32_t tsn;
22258c2654abSrjs 	if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_ecne_chunk)) {
22268c2654abSrjs 		return;
22278c2654abSrjs 	}
22288c2654abSrjs 	sctp_pegs[SCTP_ECNE_RCVD]++;
22298c2654abSrjs 	tsn = ntohl(cp->tsn);
22308c2654abSrjs 	/* ECN Nonce stuff: need a resync and disable the nonce sum check */
22318c2654abSrjs 	/* Also we make sure we disable the nonce_wait */
22328c2654abSrjs 	lchk = TAILQ_FIRST(&stcb->asoc.send_queue);
22338c2654abSrjs 	if (lchk == NULL) {
22348c2654abSrjs 		stcb->asoc.nonce_resync_tsn = stcb->asoc.sending_seq;
22358c2654abSrjs 	} else {
22368c2654abSrjs 		stcb->asoc.nonce_resync_tsn = lchk->rec.data.TSN_seq;
22378c2654abSrjs 	}
22388c2654abSrjs 	stcb->asoc.nonce_wait_for_ecne = 0;
22398c2654abSrjs 	stcb->asoc.nonce_sum_check = 0;
22408c2654abSrjs 
22418c2654abSrjs 	/* Find where it was sent, if possible */
22428c2654abSrjs 	net = NULL;
22438c2654abSrjs 	lchk = TAILQ_FIRST(&stcb->asoc.sent_queue);
22448c2654abSrjs 	while (lchk) {
22458c2654abSrjs 		if (lchk->rec.data.TSN_seq == tsn) {
22468c2654abSrjs 			net = lchk->whoTo;
22478c2654abSrjs 			break;
22488c2654abSrjs 		}
22498c2654abSrjs 		if (compare_with_wrap(lchk->rec.data.TSN_seq, tsn, MAX_SEQ))
22508c2654abSrjs 			break;
22518c2654abSrjs 		lchk = TAILQ_NEXT(lchk, sctp_next);
22528c2654abSrjs 	}
22538c2654abSrjs 	if (net == NULL)
22548c2654abSrjs 		/* default is we use the primary */
22558c2654abSrjs 		net = stcb->asoc.primary_destination;
22568c2654abSrjs 
22578c2654abSrjs 	if (compare_with_wrap(tsn, stcb->asoc.last_cwr_tsn, MAX_TSN)) {
22588c2654abSrjs #ifdef SCTP_CWND_LOGGING
22598c2654abSrjs 		int old_cwnd;
22608c2654abSrjs #endif
22618c2654abSrjs #ifdef SCTP_CWND_LOGGING
22628c2654abSrjs 		old_cwnd = net->cwnd;
22638c2654abSrjs #endif
22648c2654abSrjs 		sctp_pegs[SCTP_CWR_PERFO]++;
22658c2654abSrjs 		net->ssthresh = net->cwnd / 2;
22668c2654abSrjs 		if (net->ssthresh < net->mtu) {
22678c2654abSrjs 			net->ssthresh = net->mtu;
22688c2654abSrjs 			/* here back off the timer as well, to slow us down */
22698c2654abSrjs 			net->RTO <<= 2;
22708c2654abSrjs 		}
22718c2654abSrjs 		net->cwnd = net->ssthresh;
22728c2654abSrjs #ifdef SCTP_CWND_LOGGING
22738c2654abSrjs 		sctp_log_cwnd(net, (net->cwnd-old_cwnd), SCTP_CWND_LOG_FROM_SAT);
22748c2654abSrjs #endif
22758c2654abSrjs 		/* we reduce once every RTT. So we will only lower
22768c2654abSrjs 		 * cwnd at the next sending seq i.e. the resync_tsn.
22778c2654abSrjs 		 */
22788c2654abSrjs 		stcb->asoc.last_cwr_tsn = stcb->asoc.nonce_resync_tsn;
22798c2654abSrjs 	}
22808c2654abSrjs 	/*
22818c2654abSrjs 	 * We always send a CWR this way if our previous one was lost
22828c2654abSrjs 	 * our peer will get an update, or if it is not time again
22838c2654abSrjs 	 * to reduce we still get the cwr to the peer.
22848c2654abSrjs 	 */
22858c2654abSrjs 	sctp_send_cwr(stcb, net, tsn);
22868c2654abSrjs }
22878c2654abSrjs 
22888c2654abSrjs static void
sctp_handle_ecn_cwr(struct sctp_cwr_chunk * cp,struct sctp_tcb * stcb)22898c2654abSrjs sctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb)
22908c2654abSrjs {
22918c2654abSrjs 	/* Here we get a CWR from the peer. We must look in
22928c2654abSrjs 	 * the outqueue and make sure that we have a covered
22938c2654abSrjs 	 * ECNE in teh control chunk part. If so remove it.
22948c2654abSrjs 	 */
22958c2654abSrjs 	struct sctp_tmit_chunk *chk;
22968c2654abSrjs 	struct sctp_ecne_chunk *ecne;
22978c2654abSrjs 
22988c2654abSrjs 	TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
22998c2654abSrjs 		if (chk->rec.chunk_id != SCTP_ECN_ECHO) {
23008c2654abSrjs 			continue;
23018c2654abSrjs 		}
23028c2654abSrjs 		/* Look for and remove if it is the right TSN. Since
23038c2654abSrjs 		 * there is only ONE ECNE on the control queue at
23048c2654abSrjs 		 * any one time we don't need to worry about more than
23058c2654abSrjs 		 * one!
23068c2654abSrjs 		 */
23078c2654abSrjs 		ecne = mtod(chk->data, struct sctp_ecne_chunk *);
23088c2654abSrjs 		if (compare_with_wrap(ntohl(cp->tsn), ntohl(ecne->tsn),
23098c2654abSrjs 		    MAX_TSN) || (cp->tsn == ecne->tsn)) {
23108c2654abSrjs 			/* this covers this ECNE, we can remove it */
23118c2654abSrjs 			TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk,
23128c2654abSrjs 			    sctp_next);
23138c2654abSrjs 			sctp_m_freem(chk->data);
23148c2654abSrjs 			chk->data = NULL;
23158c2654abSrjs 			stcb->asoc.ctrl_queue_cnt--;
23168c2654abSrjs 			sctp_free_remote_addr(chk->whoTo);
23178c2654abSrjs 			SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
23188c2654abSrjs 			sctppcbinfo.ipi_count_chunk--;
23198c2654abSrjs 			if ((int)sctppcbinfo.ipi_count_chunk < 0) {
23208c2654abSrjs 				panic("Chunk count is negative");
23218c2654abSrjs 			}
23228c2654abSrjs 			sctppcbinfo.ipi_gencnt_chunk++;
23238c2654abSrjs 			break;
23248c2654abSrjs 		}
23258c2654abSrjs 	}
23268c2654abSrjs }
23278c2654abSrjs 
23288c2654abSrjs static void
sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)23298c2654abSrjs sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
23308c2654abSrjs     struct sctp_tcb *stcb, struct sctp_nets *net)
23318c2654abSrjs {
23328c2654abSrjs 	struct sctp_association *asoc;
23338c2654abSrjs 
23348c2654abSrjs #ifdef SCTP_DEBUG
23358c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
23368c2654abSrjs 		printf("sctp_handle_shutdown_complete: handling SHUTDOWN-COMPLETE\n");
23378c2654abSrjs 	}
23388c2654abSrjs #endif
23398c2654abSrjs 	if (stcb == NULL)
23408c2654abSrjs 		return;
23418c2654abSrjs 
23428c2654abSrjs 	asoc = &stcb->asoc;
23438c2654abSrjs 	/* process according to association state */
23448c2654abSrjs 	if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) {
23458c2654abSrjs 		/* unexpected SHUTDOWN-COMPLETE... so ignore... */
23468c2654abSrjs 		return;
23478c2654abSrjs 	}
23488c2654abSrjs 	/* notify upper layer protocol */
23498c2654abSrjs 	sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL);
23508c2654abSrjs 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
23518c2654abSrjs 	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
23528c2654abSrjs 		stcb->sctp_ep->sctp_flags &= ~SCTP_PCB_FLAGS_CONNECTED;
23538c2654abSrjs 		stcb->sctp_ep->sctp_socket->so_snd.sb_cc = 0;
23548c2654abSrjs 		stcb->sctp_ep->sctp_socket->so_snd.sb_mbcnt = 0;
23558c2654abSrjs 		soisdisconnected(stcb->sctp_ep->sctp_socket);
23568c2654abSrjs 	}
23578c2654abSrjs 	/* are the queues empty? they should be */
23588c2654abSrjs 	if (!TAILQ_EMPTY(&asoc->send_queue) ||
23598c2654abSrjs 	    !TAILQ_EMPTY(&asoc->sent_queue) ||
23608c2654abSrjs 	    !TAILQ_EMPTY(&asoc->out_wheel)) {
23618c2654abSrjs 		sctp_report_all_outbound(stcb);
23628c2654abSrjs 	}
23638c2654abSrjs 	/* stop the timer */
23648c2654abSrjs 	sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net);
23658c2654abSrjs 	/* free the TCB */
23668c2654abSrjs 	sctp_free_assoc(stcb->sctp_ep, stcb);
23678c2654abSrjs 	return;
23688c2654abSrjs }
23698c2654abSrjs 
23708c2654abSrjs static int
process_chunk_drop(struct sctp_tcb * stcb,struct sctp_chunk_desc * desc,struct sctp_nets * net,u_int8_t flg)23718c2654abSrjs process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
23728c2654abSrjs     struct sctp_nets *net, u_int8_t flg)
23738c2654abSrjs {
23748c2654abSrjs 	switch (desc->chunk_type) {
23758c2654abSrjs 	case SCTP_DATA:
23768c2654abSrjs 		/* find the tsn to resend (possibly */
23778c2654abSrjs 	{
23788c2654abSrjs 		u_int32_t tsn;
23798c2654abSrjs 		struct sctp_tmit_chunk *tp1;
23808c2654abSrjs 		tsn = ntohl(desc->tsn_ifany);
23818c2654abSrjs 		tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
23828c2654abSrjs 		while (tp1) {
23838c2654abSrjs 			if (tp1->rec.data.TSN_seq == tsn) {
23848c2654abSrjs 				/* found it */
23858c2654abSrjs 				break;
23868c2654abSrjs 			}
23878c2654abSrjs 			if (compare_with_wrap(tp1->rec.data.TSN_seq, tsn,
23888c2654abSrjs 					      MAX_TSN)) {
23898c2654abSrjs 				/* not found */
23908c2654abSrjs 				tp1 = NULL;
23918c2654abSrjs 				break;
23928c2654abSrjs 			}
23938c2654abSrjs 			tp1 = TAILQ_NEXT(tp1, sctp_next);
23948c2654abSrjs 		}
23958c2654abSrjs 		if (tp1 == NULL) {
23968c2654abSrjs 			/* Do it the other way */
23978c2654abSrjs 			sctp_pegs[SCTP_PDRP_DNFND]++;
23988c2654abSrjs 			tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
23998c2654abSrjs 			while (tp1) {
24008c2654abSrjs 				if (tp1->rec.data.TSN_seq == tsn) {
24018c2654abSrjs 					/* found it */
24028c2654abSrjs 					break;
24038c2654abSrjs 				}
24048c2654abSrjs 				tp1 = TAILQ_NEXT(tp1, sctp_next);
24058c2654abSrjs 			}
24068c2654abSrjs 		}
24078c2654abSrjs 		if (tp1 == NULL) {
24088c2654abSrjs 			sctp_pegs[SCTP_PDRP_TSNNF]++;
24098c2654abSrjs 		}
24108c2654abSrjs 		if ((tp1) && (tp1->sent < SCTP_DATAGRAM_ACKED)) {
24118c2654abSrjs 			u_int8_t *ddp;
24128c2654abSrjs 			if (((tp1->rec.data.state_flags & SCTP_WINDOW_PROBE) == SCTP_WINDOW_PROBE) &&
24138c2654abSrjs 			    ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) {
24148c2654abSrjs 				sctp_pegs[SCTP_PDRP_DIWNP]++;
24158c2654abSrjs 				return (0);
24168c2654abSrjs 			}
24178c2654abSrjs 			if (stcb->asoc.peers_rwnd == 0 &&
24188c2654abSrjs 			    (flg & SCTP_FROM_MIDDLE_BOX)) {
24198c2654abSrjs 				sctp_pegs[SCTP_PDRP_DIZRW]++;
24208c2654abSrjs 				return (0);
24218c2654abSrjs 			}
24228c2654abSrjs 			ddp = (u_int8_t *)(mtod(tp1->data, vaddr_t) +
24238c2654abSrjs 			    sizeof(struct sctp_data_chunk));
24248c2654abSrjs 			{
24258c2654abSrjs 				unsigned int iii;
24268c2654abSrjs 				for (iii = 0; iii < sizeof(desc->data_bytes);
24278c2654abSrjs 				    iii++) {
24288c2654abSrjs 					if (ddp[iii] != desc->data_bytes[iii]) {
24298c2654abSrjs 						sctp_pegs[SCTP_PDRP_BADD]++;
24308c2654abSrjs 						return (-1);
24318c2654abSrjs 					}
24328c2654abSrjs 				}
24338c2654abSrjs 			}
24348c2654abSrjs 			if (tp1->sent != SCTP_DATAGRAM_RESEND) {
24358c2654abSrjs 				stcb->asoc.sent_queue_retran_cnt++;
24368c2654abSrjs 			}
24378c2654abSrjs 			/* We zero out the nonce so resync not needed */
24388c2654abSrjs 			tp1->rec.data.ect_nonce = 0;
24398c2654abSrjs 
24408c2654abSrjs 			if (tp1->do_rtt) {
24418c2654abSrjs 				/*
24428c2654abSrjs 				 * this guy had a RTO calculation pending on it,
24438c2654abSrjs 				 * cancel it
24448c2654abSrjs 				 */
24458c2654abSrjs 				tp1->whoTo->rto_pending = 0;
24468c2654abSrjs 				tp1->do_rtt = 0;
24478c2654abSrjs 			}
24488c2654abSrjs 			sctp_pegs[SCTP_PDRP_MARK]++;
24498c2654abSrjs 			tp1->sent = SCTP_DATAGRAM_RESEND;
24508c2654abSrjs 			/*
24518c2654abSrjs 			 * mark it as if we were doing a FR, since we
24528c2654abSrjs 			 * will be getting gap ack reports behind the
24538c2654abSrjs 			 * info from the router.
24548c2654abSrjs 			 */
24558c2654abSrjs  			tp1->rec.data.doing_fast_retransmit = 1;
24568c2654abSrjs 			/*
24578c2654abSrjs 			 * mark the tsn with what sequences can cause a new FR.
24588c2654abSrjs 			 */
24598c2654abSrjs 			if (TAILQ_EMPTY(&stcb->asoc.send_queue) ) {
24608c2654abSrjs 				tp1->rec.data.fast_retran_tsn = stcb->asoc.sending_seq;
24618c2654abSrjs 			} else {
24628c2654abSrjs 				tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq;
24638c2654abSrjs 			}
24648c2654abSrjs 
24658c2654abSrjs 			/* restart the timer */
24668c2654abSrjs 			sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
24678c2654abSrjs 			    stcb, tp1->whoTo);
24688c2654abSrjs 			sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
24698c2654abSrjs 			    stcb, tp1->whoTo);
24708c2654abSrjs 
24718c2654abSrjs 			/* fix counts and things */
24728c2654abSrjs 			sctp_flight_size_decrease(tp1);
24738c2654abSrjs 			sctp_total_flight_decrease(stcb, tp1);
24748c2654abSrjs 			tp1->snd_count--;
24758c2654abSrjs 		}
24768c2654abSrjs 		{
24778c2654abSrjs 			/* audit code */
24788c2654abSrjs 			unsigned int audit;
24798c2654abSrjs 			audit = 0;
24808c2654abSrjs 			TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
24818c2654abSrjs 				if (tp1->sent == SCTP_DATAGRAM_RESEND)
24828c2654abSrjs 					audit++;
24838c2654abSrjs 			}
24848c2654abSrjs 			TAILQ_FOREACH(tp1, &stcb->asoc.control_send_queue,
24858c2654abSrjs 			    sctp_next) {
24868c2654abSrjs 				if (tp1->sent == SCTP_DATAGRAM_RESEND)
24878c2654abSrjs 					audit++;
24888c2654abSrjs 			}
24898c2654abSrjs 			if (audit != stcb->asoc.sent_queue_retran_cnt) {
24908c2654abSrjs 				printf("**Local Audit finds cnt:%d asoc cnt:%d\n",
24918c2654abSrjs 				    audit, stcb->asoc.sent_queue_retran_cnt);
24928c2654abSrjs #ifndef SCTP_AUDITING_ENABLED
24938c2654abSrjs 				stcb->asoc.sent_queue_retran_cnt = audit;
24948c2654abSrjs #endif
24958c2654abSrjs 			}
24968c2654abSrjs 		}
24978c2654abSrjs 	}
24988c2654abSrjs 	break;
24998c2654abSrjs 	case SCTP_ASCONF:
25008c2654abSrjs 	{
25018c2654abSrjs 		struct sctp_tmit_chunk *asconf;
25028c2654abSrjs 		TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue,
25038c2654abSrjs 		    sctp_next) {
25048c2654abSrjs 			if (asconf->rec.chunk_id == SCTP_ASCONF) {
25058c2654abSrjs 				break;
25068c2654abSrjs 			}
25078c2654abSrjs 		}
25088c2654abSrjs 		if (asconf) {
25098c2654abSrjs 			if (asconf->sent != SCTP_DATAGRAM_RESEND)
25108c2654abSrjs 				stcb->asoc.sent_queue_retran_cnt++;
25118c2654abSrjs 			asconf->sent = SCTP_DATAGRAM_RESEND;
25128c2654abSrjs 			asconf->snd_count--;
25138c2654abSrjs 		}
25148c2654abSrjs 	}
25158c2654abSrjs 	break;
25168c2654abSrjs 	case SCTP_INITIATION:
25178c2654abSrjs 		/* resend the INIT */
25188c2654abSrjs 		stcb->asoc.dropped_special_cnt++;
25198c2654abSrjs 		if (stcb->asoc.dropped_special_cnt < SCTP_RETRY_DROPPED_THRESH) {
25208c2654abSrjs 			/*
25218c2654abSrjs 			 * If we can get it in, in a few attempts we do this,
25228c2654abSrjs 			 * otherwise we let the timer fire.
25238c2654abSrjs 			 */
25248c2654abSrjs 			sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep,
25258c2654abSrjs 			    stcb, net);
25268c2654abSrjs 			sctp_send_initiate(stcb->sctp_ep, stcb);
25278c2654abSrjs 		}
25288c2654abSrjs 		break;
25298c2654abSrjs 	case SCTP_SELECTIVE_ACK:
25308c2654abSrjs 		/* resend the sack */
25318c2654abSrjs 		sctp_send_sack(stcb);
25328c2654abSrjs 		break;
25338c2654abSrjs 	case SCTP_HEARTBEAT_REQUEST:
25348c2654abSrjs 		/* resend a demand HB */
25358c2654abSrjs 		sctp_send_hb(stcb, 1, net);
25368c2654abSrjs 		break;
25378c2654abSrjs 	case SCTP_SHUTDOWN:
25388c2654abSrjs #ifdef SCTP_DEBUG
25398c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_OUTPUT4) {
25408c2654abSrjs 			printf("%s:%d sends a shutdown\n",
25418c2654abSrjs 			       __FILE__,
25428c2654abSrjs 			       __LINE__
25438c2654abSrjs 				);
25448c2654abSrjs 		}
25458c2654abSrjs #endif
25468c2654abSrjs 		sctp_send_shutdown(stcb, net);
25478c2654abSrjs 		break;
25488c2654abSrjs 	case SCTP_SHUTDOWN_ACK:
25498c2654abSrjs 		sctp_send_shutdown_ack(stcb, net);
25508c2654abSrjs 		break;
25518c2654abSrjs 	case SCTP_COOKIE_ECHO:
25528c2654abSrjs 	{
25538c2654abSrjs 		struct sctp_tmit_chunk *cookie;
25548c2654abSrjs 		cookie = NULL;
25558c2654abSrjs 		TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue,
25568c2654abSrjs 		    sctp_next) {
25578c2654abSrjs 			if (cookie->rec.chunk_id == SCTP_COOKIE_ECHO) {
25588c2654abSrjs 				break;
25598c2654abSrjs 			}
25608c2654abSrjs 		}
25618c2654abSrjs 		if (cookie) {
25628c2654abSrjs 			if (cookie->sent != SCTP_DATAGRAM_RESEND)
25638c2654abSrjs 				stcb->asoc.sent_queue_retran_cnt++;
25648c2654abSrjs 			cookie->sent = SCTP_DATAGRAM_RESEND;
25658c2654abSrjs 			sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep, stcb, net);
25668c2654abSrjs 		}
25678c2654abSrjs 	}
25688c2654abSrjs 	break;
25698c2654abSrjs 	case SCTP_COOKIE_ACK:
25708c2654abSrjs 		sctp_send_cookie_ack(stcb);
25718c2654abSrjs 		break;
25728c2654abSrjs 	case SCTP_ASCONF_ACK:
25738c2654abSrjs 		/* resend last asconf ack */
25748c2654abSrjs 		sctp_send_asconf_ack(stcb, 1);
25758c2654abSrjs 		break;
25768c2654abSrjs 	case SCTP_FORWARD_CUM_TSN:
25778c2654abSrjs 		send_forward_tsn(stcb, &stcb->asoc);
25788c2654abSrjs 		break;
25798c2654abSrjs 		/* can't do anything with these */
25808c2654abSrjs 	case SCTP_PACKET_DROPPED:
25818c2654abSrjs 	case SCTP_INITIATION_ACK:	/* this should not happen */
25828c2654abSrjs 	case SCTP_HEARTBEAT_ACK:
25838c2654abSrjs 	case SCTP_ABORT_ASSOCIATION:
25848c2654abSrjs 	case SCTP_OPERATION_ERROR:
25858c2654abSrjs 	case SCTP_SHUTDOWN_COMPLETE:
25868c2654abSrjs 	case SCTP_ECN_ECHO:
25878c2654abSrjs 	case SCTP_ECN_CWR:
25888c2654abSrjs 	default:
25898c2654abSrjs 		break;
25908c2654abSrjs 	}
25918c2654abSrjs 	return (0);
25928c2654abSrjs }
25938c2654abSrjs 
25948c2654abSrjs static void
sctp_reset_in_stream(struct sctp_tcb * stcb,struct sctp_stream_reset_response * resp,int number_entries)25958c2654abSrjs sctp_reset_in_stream(struct sctp_tcb *stcb,
25968c2654abSrjs     struct sctp_stream_reset_response *resp, int number_entries)
25978c2654abSrjs {
25988c2654abSrjs 	int i;
25998c2654abSrjs 	uint16_t *list, temp;
26008c2654abSrjs 
26018c2654abSrjs         /* We set things to 0xffff since this is the last delivered
26028c2654abSrjs 	 * sequence and we will be sending in 0 after the reset.
26038c2654abSrjs 	 */
26048c2654abSrjs 
26058c2654abSrjs 	if (resp->reset_flags & SCTP_RESET_PERFORMED) {
26068c2654abSrjs 		if (number_entries) {
26078c2654abSrjs 			list = resp->list_of_streams;
26088c2654abSrjs 			for (i = 0; i < number_entries; i++) {
26098c2654abSrjs 				temp = ntohs(list[i]);
26108c2654abSrjs 				list[i] = temp;
26118c2654abSrjs 				if (list[i] >= stcb->asoc.streamincnt) {
26128c2654abSrjs 					printf("Invalid stream in-stream reset %d\n", list[i]);
26138c2654abSrjs 					continue;
26148c2654abSrjs 				}
26158c2654abSrjs 				stcb->asoc.strmin[(list[i])].last_sequence_delivered = 0xffff;
26168c2654abSrjs 			}
26178c2654abSrjs 		} else {
26188c2654abSrjs 			list = NULL;
26198c2654abSrjs 			for (i = 0; i < stcb->asoc.streamincnt; i++) {
26208c2654abSrjs 				stcb->asoc.strmin[i].last_sequence_delivered = 0xffff;
26218c2654abSrjs 			}
26228c2654abSrjs 		}
26238c2654abSrjs 		sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list);
26248c2654abSrjs 	}
26258c2654abSrjs }
26268c2654abSrjs 
26278c2654abSrjs static void
sctp_clean_up_stream_reset(struct sctp_tcb * stcb)26288c2654abSrjs sctp_clean_up_stream_reset(struct sctp_tcb *stcb)
26298c2654abSrjs {
26308c2654abSrjs 	struct sctp_tmit_chunk *chk, *nchk;
26318c2654abSrjs 	struct sctp_association *asoc;
26328c2654abSrjs 
26338c2654abSrjs 	asoc = &stcb->asoc;
26348c2654abSrjs 
26358c2654abSrjs 	for (chk = TAILQ_FIRST(&asoc->control_send_queue);
26368c2654abSrjs 	    chk; chk = nchk) {
26378c2654abSrjs 		nchk = TAILQ_NEXT(chk, sctp_next);
26388c2654abSrjs 		if (chk->rec.chunk_id == SCTP_STREAM_RESET) {
26398c2654abSrjs 			struct sctp_stream_reset_req *strreq;
26408c2654abSrjs 			strreq = mtod(chk->data, struct sctp_stream_reset_req *);
26418c2654abSrjs 			if (strreq->sr_req.ph.param_type == ntohs(SCTP_STR_RESET_RESPONSE)) {
26428c2654abSrjs 				/* we only clean up the request */
26438c2654abSrjs 				continue;
26448c2654abSrjs 			} else if (strreq->sr_req.ph.param_type != ntohs(SCTP_STR_RESET_REQUEST)) {
26458c2654abSrjs 				printf("TSNH, an unknown stream reset request is in queue %x\n",
26468c2654abSrjs 				       (u_int)ntohs(strreq->sr_req.ph.param_type));
26478c2654abSrjs 				continue;
26488c2654abSrjs 			}
26498c2654abSrjs 			sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo);
26508c2654abSrjs 			TAILQ_REMOVE(&asoc->control_send_queue,
26518c2654abSrjs 				     chk,
26528c2654abSrjs 				     sctp_next);
26538c2654abSrjs 			sctp_m_freem(chk->data);
26548c2654abSrjs 			chk->data = NULL;
26558c2654abSrjs 			asoc->ctrl_queue_cnt--;
26568c2654abSrjs 			sctp_free_remote_addr(chk->whoTo);
26578c2654abSrjs 			SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
26588c2654abSrjs 			sctppcbinfo.ipi_count_chunk--;
26598c2654abSrjs 			if ((int)sctppcbinfo.ipi_count_chunk < 0) {
26608c2654abSrjs 				panic("Chunk count is negative");
26618c2654abSrjs 			}
26628c2654abSrjs 			sctppcbinfo.ipi_gencnt_chunk++;
26638c2654abSrjs 			/* we can only have one of these so we break */
26648c2654abSrjs 			break;
26658c2654abSrjs 		}
26668c2654abSrjs 	}
26678c2654abSrjs }
26688c2654abSrjs 
26698c2654abSrjs 
26708c2654abSrjs void
sctp_handle_stream_reset_response(struct sctp_tcb * stcb,struct sctp_stream_reset_response * resp)26718c2654abSrjs sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
26728c2654abSrjs 	struct sctp_stream_reset_response *resp)
26738c2654abSrjs {
26748c2654abSrjs  	uint32_t seq, tsn;
26758c2654abSrjs  	int number_entries, param_length;
26768c2654abSrjs 
26778c2654abSrjs  	param_length = ntohs(resp->ph.param_length);
26788c2654abSrjs  	seq = ntohl(resp->reset_req_seq_resp);
26798c2654abSrjs 	if (seq == stcb->asoc.str_reset_seq_out) {
26808c2654abSrjs  		sctp_clean_up_stream_reset(stcb);
26818c2654abSrjs  		stcb->asoc.str_reset_seq_out++;
26828c2654abSrjs  		stcb->asoc.stream_reset_outstanding = 0;
26838c2654abSrjs  		tsn = ntohl(resp->reset_at_tsn);
26848c2654abSrjs  		number_entries = (param_length - sizeof(struct sctp_stream_reset_response))/sizeof(uint16_t);
26858c2654abSrjs  		tsn--;
26868c2654abSrjs  		if ((tsn == stcb->asoc.cumulative_tsn) ||
26878c2654abSrjs  		    (compare_with_wrap(stcb->asoc.cumulative_tsn, tsn, MAX_TSN))) {
26888c2654abSrjs  			/* no problem we are good to go */
26898c2654abSrjs  			sctp_reset_in_stream(stcb, resp, number_entries);
26908c2654abSrjs  		} else {
26918c2654abSrjs  			/* So, we have a stream reset but there
26928c2654abSrjs  			 * is pending data. We need to copy
26938c2654abSrjs  			 * out the stream_reset and then queue
26948c2654abSrjs  			 * any data = or > resp->reset_at_tsn
26958c2654abSrjs  			 */
26968c2654abSrjs  			if (stcb->asoc.pending_reply != NULL) {
26978c2654abSrjs  				/* FIX ME FIX ME
26988c2654abSrjs  				 * This IS WRONG. We need
26998c2654abSrjs  				 * to queue each of these up
27008c2654abSrjs  				 * and only release the chunks
27018c2654abSrjs  				 * for each reset that the cum-ack
27028c2654abSrjs  				 * goes by. This is a short cut.
27038c2654abSrjs  				 */
27048c2654abSrjs  				free(stcb->asoc.pending_reply, M_PCB);
27058c2654abSrjs  			}
27068c2654abSrjs  			stcb->asoc.pending_reply = malloc(param_length,
27078c2654abSrjs  			       				M_PCB, M_NOWAIT);
27088c2654abSrjs  			memcpy(stcb->asoc.pending_reply, resp, param_length);
27098c2654abSrjs  		}
27108c2654abSrjs 
27118c2654abSrjs   	} else {
27128c2654abSrjs  		/* duplicate */
27138c2654abSrjs #ifdef SCTP_DEBUG
27148c2654abSrjs  		printf("Duplicate old stream reset resp next:%x this one:%x\n",
27158c2654abSrjs  		       stcb->asoc.str_reset_seq_out, seq);
27168c2654abSrjs #endif
27178c2654abSrjs 	}
27188c2654abSrjs }
27198c2654abSrjs 
27208c2654abSrjs 
27218c2654abSrjs static void
sctp_handle_stream_reset(struct sctp_tcb * stcb,struct sctp_stream_reset_req * sr_req)27228c2654abSrjs sctp_handle_stream_reset(struct sctp_tcb *stcb, struct sctp_stream_reset_req *sr_req)
27238c2654abSrjs {
27248c2654abSrjs  	int chk_length, param_len;
27258c2654abSrjs  	struct sctp_paramhdr *ph;
27268c2654abSrjs  	/* now it may be a reset or a reset-response */
27278c2654abSrjs  	struct sctp_stream_reset_request *req;
27288c2654abSrjs  	struct sctp_stream_reset_response *resp;
27298c2654abSrjs  	chk_length = ntohs(sr_req->ch.chunk_length);
27308c2654abSrjs 
27318c2654abSrjs  	ph = (struct sctp_paramhdr *)&sr_req->sr_req;
27328c2654abSrjs  	while ((size_t)chk_length >= sizeof(struct sctp_stream_reset_request)) {
27338c2654abSrjs  		param_len = ntohs(ph->param_length);
27348c2654abSrjs  		if (ntohs(ph->param_type) == SCTP_STR_RESET_REQUEST) {
27358c2654abSrjs  			/* this will send the ACK and do the reset if needed */
27368c2654abSrjs  			req = (struct sctp_stream_reset_request *)ph;
27378c2654abSrjs  			sctp_send_str_reset_ack(stcb, req);
27388c2654abSrjs  		} else if (ntohs(ph->param_type) == SCTP_STR_RESET_RESPONSE) {
27398c2654abSrjs  			/* Now here is a tricky one. We reset our receive side
27408c2654abSrjs  			 * of the streams. But what happens if the peers
27418c2654abSrjs  			 * next sending TSN is NOT equal to 1 minus our cumack?
27428c2654abSrjs  			 * And if his cumack is not equal to our next one out - 1
27438c2654abSrjs  			 * we have another problem if this is receprical.
27448c2654abSrjs  			 */
27458c2654abSrjs  			resp = (struct sctp_stream_reset_response *)ph;
27468c2654abSrjs  			sctp_handle_stream_reset_response(stcb, resp);
27478c2654abSrjs  		}
27488c2654abSrjs  		ph = (struct sctp_paramhdr *)((vaddr_t)ph + SCTP_SIZE32(param_len));
27498c2654abSrjs  		chk_length -= SCTP_SIZE32(param_len);
27508c2654abSrjs   	}
27518c2654abSrjs }
27528c2654abSrjs 
27538c2654abSrjs /*
27548c2654abSrjs  * Handle a router or endpoints report of a packet loss, there
27558c2654abSrjs  * are two ways to handle this, either we get the whole packet
27568c2654abSrjs  * and must disect it ourselves (possibly with truncation and
27578c2654abSrjs  * or corruption) or it is a summary from a middle box that did
27588c2654abSrjs  * the disectting for us.
27598c2654abSrjs  */
27608c2654abSrjs static void
sctp_handle_packet_dropped(struct sctp_pktdrop_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)27618c2654abSrjs sctp_handle_packet_dropped(struct sctp_pktdrop_chunk *cp,
27628c2654abSrjs     struct sctp_tcb *stcb, struct sctp_nets *net)
27638c2654abSrjs {
27648c2654abSrjs 	u_int32_t bottle_bw, on_queue;
27658c2654abSrjs 	u_int16_t trunc_len;
27668c2654abSrjs 	unsigned int chlen;
27678c2654abSrjs 	unsigned int at;
27688c2654abSrjs 	struct sctp_chunk_desc desc;
27698c2654abSrjs 	struct sctp_chunkhdr *ch;
27708c2654abSrjs 
27718c2654abSrjs 	chlen = ntohs(cp->ch.chunk_length);
27728c2654abSrjs 	chlen -= sizeof(struct sctp_pktdrop_chunk);
27738c2654abSrjs 	/* XXX possible chlen underflow */
27748c2654abSrjs 	if (chlen == 0) {
27758c2654abSrjs 		ch = NULL;
27768c2654abSrjs 		if (cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)
27778c2654abSrjs 			sctp_pegs[SCTP_PDRP_BWRPT]++;
27788c2654abSrjs 	} else {
27798c2654abSrjs 		ch = (struct sctp_chunkhdr *)(cp->data + sizeof(struct sctphdr));
27808c2654abSrjs 		chlen -= sizeof(struct sctphdr);
27818c2654abSrjs 		/* XXX possible chlen underflow */
27828c2654abSrjs 		memset(&desc, 0, sizeof(desc));
27838c2654abSrjs 	}
27848c2654abSrjs 
27858c2654abSrjs 	/* first update a rwnd possibly */
27868c2654abSrjs 	if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) == 0) {
27878c2654abSrjs 		/* From a peer, we get a rwnd report */
27888c2654abSrjs 		u_int32_t a_rwnd;
27898c2654abSrjs 
27908c2654abSrjs 		sctp_pegs[SCTP_PDRP_FEHOS]++;
27918c2654abSrjs 
27928c2654abSrjs 		bottle_bw = ntohl(cp->bottle_bw);
27938c2654abSrjs 		on_queue =  ntohl(cp->current_onq);
27948c2654abSrjs 		if (bottle_bw && on_queue) {
27958c2654abSrjs 			/* a rwnd report is in here */
27968c2654abSrjs 			if (bottle_bw > on_queue)
27978c2654abSrjs 				a_rwnd = bottle_bw - on_queue;
27988c2654abSrjs 			else
27998c2654abSrjs 				a_rwnd = 0;
28008c2654abSrjs 
28018c2654abSrjs 			if (a_rwnd <= 0)
28028c2654abSrjs 				stcb->asoc.peers_rwnd =  0;
28038c2654abSrjs 			else {
28048c2654abSrjs 				if (a_rwnd > stcb->asoc.total_flight) {
28058c2654abSrjs 					stcb->asoc.peers_rwnd =
28068c2654abSrjs 					    a_rwnd - stcb->asoc.total_flight;
28078c2654abSrjs 				} else {
28088c2654abSrjs 					stcb->asoc.peers_rwnd =  0;
28098c2654abSrjs 				}
28108c2654abSrjs 				if (stcb->asoc.peers_rwnd <
28118c2654abSrjs 				    stcb->sctp_ep->sctp_ep.sctp_sws_sender) {
28128c2654abSrjs 					/* SWS sender side engages */
28138c2654abSrjs 					stcb->asoc.peers_rwnd = 0;
28148c2654abSrjs 				}
28158c2654abSrjs 			}
28168c2654abSrjs 		}
28178c2654abSrjs 	} else {
28188c2654abSrjs 		sctp_pegs[SCTP_PDRP_FMBOX]++;
28198c2654abSrjs 	}
28208c2654abSrjs 	trunc_len = (u_int16_t)ntohs(cp->trunc_len);
28218c2654abSrjs 	/* now the chunks themselves */
28228c2654abSrjs 	while ((ch != NULL) && (chlen >= sizeof(struct sctp_chunkhdr))) {
28238c2654abSrjs 		desc.chunk_type = ch->chunk_type;
28248c2654abSrjs 		/* get amount we need to move */
28258c2654abSrjs 		at = ntohs(ch->chunk_length);
28268c2654abSrjs 		if (at < sizeof(struct sctp_chunkhdr)) {
28278c2654abSrjs 			/* corrupt chunk, maybe at the end? */
28288c2654abSrjs 			sctp_pegs[SCTP_PDRP_CRUPT]++;
28298c2654abSrjs 			break;
28308c2654abSrjs 		}
28318c2654abSrjs 		if (trunc_len == 0) {
28328c2654abSrjs 			/* we are supposed to have all of it */
28338c2654abSrjs 			if (at > chlen) {
28348c2654abSrjs 				/* corrupt skip it */
28358c2654abSrjs 				sctp_pegs[SCTP_PDRP_CRUPT]++;
28368c2654abSrjs 				break;
28378c2654abSrjs 			}
28388c2654abSrjs 		} else {
28398c2654abSrjs 			/* is there enough of it left ? */
28408c2654abSrjs 			if (desc.chunk_type == SCTP_DATA) {
28418c2654abSrjs 				if (chlen < (sizeof(struct sctp_data_chunk) +
28428c2654abSrjs 					     sizeof(desc.data_bytes))) {
28438c2654abSrjs 					break;
28448c2654abSrjs 				}
28458c2654abSrjs 			} else {
28468c2654abSrjs 				if (chlen < sizeof(struct sctp_chunkhdr)) {
28478c2654abSrjs 					break;
28488c2654abSrjs 				}
28498c2654abSrjs 			}
28508c2654abSrjs 		}
28518c2654abSrjs 		if (desc.chunk_type == SCTP_DATA) {
28528c2654abSrjs 			/* can we get out the tsn? */
28538c2654abSrjs 			if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX))
28548c2654abSrjs 				sctp_pegs[SCTP_PDRP_MB_DA]++;
28558c2654abSrjs 
28568c2654abSrjs 			if (chlen >= (sizeof(struct sctp_data_chunk) + sizeof(u_int32_t)) ) {
28578c2654abSrjs 				/* yep */
28588c2654abSrjs 				struct sctp_data_chunk *dcp;
28598c2654abSrjs 				u_int8_t  *ddp;
28608c2654abSrjs 				unsigned int iii;
28618c2654abSrjs 				dcp = (struct sctp_data_chunk *)ch;
28628c2654abSrjs 				ddp = (u_int8_t *)(dcp + 1);
28638c2654abSrjs 				for (iii = 0; iii < sizeof(desc.data_bytes); iii++) {
28648c2654abSrjs 					desc.data_bytes[iii] = ddp[iii];
28658c2654abSrjs 				}
28668c2654abSrjs 				desc.tsn_ifany = dcp->dp.tsn;
28678c2654abSrjs 			} else {
28688c2654abSrjs 				/* nope we are done. */
28698c2654abSrjs 				sctp_pegs[SCTP_PDRP_NEDAT]++;
28708c2654abSrjs 				break;
28718c2654abSrjs 			}
28728c2654abSrjs 		} else {
28738c2654abSrjs 			if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX))
28748c2654abSrjs 				sctp_pegs[SCTP_PDRP_MB_CT]++;
28758c2654abSrjs 		}
28768c2654abSrjs 
28778c2654abSrjs 		if (process_chunk_drop(stcb, &desc, net, cp->ch.chunk_flags)) {
28788c2654abSrjs 			sctp_pegs[SCTP_PDRP_PDBRK]++;
28798c2654abSrjs 			break;
28808c2654abSrjs 		}
28818c2654abSrjs 		if (SCTP_SIZE32(at) > chlen) {
28828c2654abSrjs 			break;
28838c2654abSrjs 		}
28848c2654abSrjs 		chlen -= SCTP_SIZE32(at);
28858c2654abSrjs 		if (chlen < sizeof(struct sctp_chunkhdr)) {
28868c2654abSrjs 			/* done, none left */
28878c2654abSrjs 			break;
28888c2654abSrjs 		}
28898c2654abSrjs 		ch = (struct sctp_chunkhdr *)((vaddr_t)ch + SCTP_SIZE32(at));
28908c2654abSrjs 	}
28918c2654abSrjs 
28928c2654abSrjs 	/* now middle boxes in sat networks get a cwnd bump */
28938c2654abSrjs 	if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) &&
28948c2654abSrjs 	    (stcb->asoc.sat_t3_loss_recovery == 0) &&
28958c2654abSrjs 	    (stcb->asoc.sat_network)) {
28968c2654abSrjs 		/*
28978c2654abSrjs 		 * This is debateable but for sat networks it makes sense
28988c2654abSrjs 		 * Note if a T3 timer has went off, we will prohibit any
28998c2654abSrjs 		 * changes to cwnd until we exit the t3 loss recovery.
29008c2654abSrjs 		 */
29018c2654abSrjs 		u_int32_t bw_avail;
29028c2654abSrjs 		int rtt, incr;
29038c2654abSrjs #ifdef SCTP_CWND_LOGGING
29048c2654abSrjs 		int old_cwnd=net->cwnd;
29058c2654abSrjs #endif
29068c2654abSrjs 		/* need real RTT for this calc */
29078c2654abSrjs 		rtt = ((net->lastsa >> 2) + net->lastsv) >> 1;
29088c2654abSrjs 		/* get bottle neck bw */
29098c2654abSrjs 		bottle_bw = ntohl(cp->bottle_bw);
29108c2654abSrjs 		/* and whats on queue */
29118c2654abSrjs 		on_queue =  ntohl(cp->current_onq);
29128c2654abSrjs 		/*
29138c2654abSrjs 		 * adjust the on-queue if our flight is more it could be
29148c2654abSrjs 		 * that the router has not yet gotten data "in-flight" to it
29158c2654abSrjs 		 */
29168c2654abSrjs  		if (on_queue < net->flight_size)
29178c2654abSrjs 			on_queue = net->flight_size;
29188c2654abSrjs 
29198c2654abSrjs 		/* calculate the available space */
29208c2654abSrjs 		bw_avail = (bottle_bw*rtt)/1000;
29218c2654abSrjs 		if (bw_avail > bottle_bw) {
29228c2654abSrjs 			/*
29238c2654abSrjs 			 * Cap the growth to no more than the bottle neck.
29248c2654abSrjs 			 * This can happen as RTT slides up due to queues.
29258c2654abSrjs 			 * It also means if you have more than a 1 second
29268c2654abSrjs 			 * RTT with a empty queue you will be limited to
29278c2654abSrjs 			 * the bottle_bw per second no matter if
29288c2654abSrjs 			 * other points have 1/2 the RTT and you could
29298c2654abSrjs 			 * get more out...
29308c2654abSrjs 			 */
29318c2654abSrjs 			bw_avail = bottle_bw;
29328c2654abSrjs 		}
29338c2654abSrjs 
29348c2654abSrjs 		if (on_queue > bw_avail) {
29358c2654abSrjs 			/*
29368c2654abSrjs 			 * No room for anything else don't allow anything
29378c2654abSrjs 			 * else to be "added to the fire".
29388c2654abSrjs 			 */
29398c2654abSrjs 			int seg_inflight, seg_onqueue, my_portion;
29408c2654abSrjs 			net->partial_bytes_acked = 0;
29418c2654abSrjs 
29428c2654abSrjs 			/* how much are we over queue size? */
29438c2654abSrjs 			incr = on_queue - bw_avail;
29448c2654abSrjs 			if (stcb->asoc.seen_a_sack_this_pkt) {
29458c2654abSrjs 				/* undo any cwnd adjustment that
29468c2654abSrjs 				 * the sack might have made
29478c2654abSrjs 				 */
29488c2654abSrjs 				net->cwnd = net->prev_cwnd;
29498c2654abSrjs 			}
29508c2654abSrjs 
29518c2654abSrjs 			/* Now how much of that is mine? */
29528c2654abSrjs 			seg_inflight = net->flight_size / net->mtu;
29538c2654abSrjs 			seg_onqueue = on_queue / net->mtu;
29548c2654abSrjs 			my_portion = (incr * seg_inflight)/seg_onqueue;
29558c2654abSrjs 
29568c2654abSrjs 			/* Have I made an adjustment already */
29578c2654abSrjs 			if (net->cwnd > net->flight_size) {
29588c2654abSrjs 				/* for this flight I made an adjustment
29598c2654abSrjs 				 * we need to decrease the portion by a share
29608c2654abSrjs 				 * our previous adjustment.
29618c2654abSrjs 				 */
29628c2654abSrjs 				int diff_adj;
29638c2654abSrjs 				diff_adj = net->cwnd - net->flight_size;
29648c2654abSrjs 				if (diff_adj > my_portion)
29658c2654abSrjs 					my_portion = 0;
29668c2654abSrjs 				else
29678c2654abSrjs 					my_portion -= diff_adj;
29688c2654abSrjs 			}
29698c2654abSrjs 
29708c2654abSrjs 			/* back down to the previous cwnd (assume
29718c2654abSrjs 			 * we have had a sack before this packet). minus
29728c2654abSrjs 			 * what ever portion of the overage is my fault.
29738c2654abSrjs 			 */
29748c2654abSrjs 			net->cwnd -= my_portion;
29758c2654abSrjs 
29768c2654abSrjs 			/* we will NOT back down more than 1 MTU */
29778c2654abSrjs 			if (net->cwnd <= net->mtu) {
29788c2654abSrjs 				net->cwnd = net->mtu;
29798c2654abSrjs 			}
29808c2654abSrjs 			/* force into CA */
29818c2654abSrjs 			net->ssthresh = net->cwnd - 1;
29828c2654abSrjs 		} else {
29838c2654abSrjs 			/*
29848c2654abSrjs 			 * Take 1/4 of the space left or
29858c2654abSrjs 			 * max burst up .. whichever is less.
29868c2654abSrjs 			 */
2987d1579b2dSriastradh 			incr = uimin((bw_avail - on_queue) >> 2,
29888c2654abSrjs 			    (int)stcb->asoc.max_burst * (int)net->mtu);
29898c2654abSrjs 			net->cwnd += incr;
29908c2654abSrjs 		}
29918c2654abSrjs 		if (net->cwnd > bw_avail) {
29928c2654abSrjs 			/* We can't exceed the pipe size */
29938c2654abSrjs 			net->cwnd = bw_avail;
29948c2654abSrjs 		}
29958c2654abSrjs 		if (net->cwnd < net->mtu) {
29968c2654abSrjs 			/* We always have 1 MTU */
29978c2654abSrjs 			net->cwnd = net->mtu;
29988c2654abSrjs 		}
29998c2654abSrjs #ifdef SCTP_CWND_LOGGING
30008c2654abSrjs 		if (net->cwnd - old_cwnd != 0) {
30018c2654abSrjs 			/* log only changes */
30028c2654abSrjs 			sctp_log_cwnd(net, (net->cwnd - old_cwnd),
30038c2654abSrjs 			    SCTP_CWND_LOG_FROM_SAT);
30048c2654abSrjs 		}
30058c2654abSrjs #endif
30068c2654abSrjs 	}
30078c2654abSrjs }
30088c2654abSrjs 
30098c2654abSrjs extern int sctp_strict_init;
30108c2654abSrjs 
30118c2654abSrjs /*
30128c2654abSrjs  * handles all control chunks in a packet
30138c2654abSrjs  * inputs:
30148c2654abSrjs  * - m: mbuf chain, assumed to still contain IP/SCTP header
30158c2654abSrjs  * - stcb: is the tcb found for this packet
30168c2654abSrjs  * - offset: offset into the mbuf chain to first chunkhdr
30178c2654abSrjs  * - length: is the length of the complete packet
30188c2654abSrjs  * outputs:
30198c2654abSrjs  * - length: modified to remaining length after control processing
30208c2654abSrjs  * - netp: modified to new sctp_nets after cookie-echo processing
30218c2654abSrjs  * - return NULL to discard the packet (ie. no asoc, bad packet,...)
30228c2654abSrjs  *   otherwise return the tcb for this packet
30238c2654abSrjs  */
30248c2654abSrjs static struct sctp_tcb *
sctp_process_control(struct mbuf * m,int iphlen,int * offset,int length,struct sctphdr * sh,struct sctp_chunkhdr * ch,struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets ** netp,int * fwd_tsn_seen)30258c2654abSrjs sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
30268c2654abSrjs     struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp,
30278c2654abSrjs     struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen)
30288c2654abSrjs {
30298c2654abSrjs 	struct sctp_association *asoc;
30308c2654abSrjs 	u_int32_t vtag_in;
30318c2654abSrjs 	int num_chunks = 0;	/* number of control chunks processed */
30328c2654abSrjs 	int chk_length;
30338c2654abSrjs 	int ret;
30348c2654abSrjs 
30358c2654abSrjs 	/*
30368c2654abSrjs 	 * How big should this be, and should it be alloc'd?
30378c2654abSrjs 	 * Lets try the d-mtu-ceiling for now (2k) and that should
30388c2654abSrjs 	 * hopefully work ... until we get into jumbo grams and such..
30398c2654abSrjs 	 */
30408c2654abSrjs 	u_int8_t chunk_buf[DEFAULT_CHUNK_BUFFER];
30418c2654abSrjs 	struct sctp_tcb *locked_tcb = stcb;
30428c2654abSrjs 
30438c2654abSrjs #ifdef SCTP_DEBUG
30448c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
30458c2654abSrjs 		printf("sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n",
30468c2654abSrjs 		       iphlen, *offset, length, stcb);
30478c2654abSrjs 	}
30488c2654abSrjs #endif /* SCTP_DEBUG */
30498c2654abSrjs 
30508c2654abSrjs 	/* validate chunk header length... */
30518c2654abSrjs 	if (ntohs(ch->chunk_length) < sizeof(*ch)) {
30528c2654abSrjs 		return (NULL);
30538c2654abSrjs 	}
30548c2654abSrjs 
30558c2654abSrjs 	/*
30568c2654abSrjs 	 * validate the verification tag
30578c2654abSrjs 	 */
30588c2654abSrjs #ifdef SCTP_DEBUG
30598c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
30608c2654abSrjs 		printf("sctp_process_control: validating vtags\n");
30618c2654abSrjs 	}
30628c2654abSrjs #endif /* SCTP_DEBUG */
30638c2654abSrjs 	vtag_in = ntohl(sh->v_tag);
30648c2654abSrjs 	if (ch->chunk_type == SCTP_INITIATION) {
30658c2654abSrjs 		if (vtag_in != 0) {
30668c2654abSrjs 			/* protocol error- silently discard... */
30678c2654abSrjs #ifdef SCTP_DEBUG
30688c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
30698c2654abSrjs 				printf("sctp_process_control: INIT with vtag != 0\n");
30708c2654abSrjs 			}
30718c2654abSrjs #endif /* SCTP_DEBUG */
30728c2654abSrjs 			sctp_pegs[SCTP_BAD_VTAGS]++;
30738c2654abSrjs 			if (locked_tcb) {
30748c2654abSrjs 				SCTP_TCB_UNLOCK(locked_tcb);
30758c2654abSrjs 			}
30768c2654abSrjs 			return (NULL);
30778c2654abSrjs 		}
30788c2654abSrjs 	} else if (ch->chunk_type != SCTP_COOKIE_ECHO) {
30798c2654abSrjs 		/*
30808c2654abSrjs 		 * first check if it's an ASCONF with an unknown src addr
30818c2654abSrjs 		 * we need to look inside to find the association
30828c2654abSrjs 		 */
30838c2654abSrjs 		if (ch->chunk_type == SCTP_ASCONF && stcb == NULL) {
30848c2654abSrjs 			stcb = sctp_findassociation_ep_asconf(m, iphlen,
30858c2654abSrjs 			    *offset, sh, &inp, netp);
30868c2654abSrjs 		}
30878c2654abSrjs 		if (stcb == NULL) {
30888c2654abSrjs 			/* no association, so it's out of the blue... */
30898c2654abSrjs 			sctp_handle_ootb(m, iphlen, *offset, sh, inp, NULL);
30908c2654abSrjs #ifdef SCTP_DEBUG
30918c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
30928c2654abSrjs 				printf("sctp_process_control: handling OOTB packet, chunk type=%xh\n",
30938c2654abSrjs 				       ch->chunk_type);
30948c2654abSrjs 			}
30958c2654abSrjs #endif /* SCTP_DEBUG */
30968c2654abSrjs 			*offset = length;
30978c2654abSrjs 			if (locked_tcb) {
30988c2654abSrjs 				SCTP_TCB_UNLOCK(locked_tcb);
30998c2654abSrjs 			}
31008c2654abSrjs 			return (NULL);
31018c2654abSrjs 		}
31028c2654abSrjs 		asoc = &stcb->asoc;
31038c2654abSrjs 		/* ABORT and SHUTDOWN can use either v_tag... */
31048c2654abSrjs 		if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) ||
31058c2654abSrjs 		    (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) ||
31068c2654abSrjs 		    (ch->chunk_type == SCTP_PACKET_DROPPED)) {
31078c2654abSrjs 			if ((vtag_in == asoc->my_vtag) ||
31088c2654abSrjs 			    ((ch->chunk_flags & SCTP_HAD_NO_TCB) &&
31098c2654abSrjs 			     (vtag_in == asoc->peer_vtag))) {
31108c2654abSrjs 				/* this is valid */
31118c2654abSrjs 			} else {
31128c2654abSrjs 				/* drop this packet... */
31138c2654abSrjs 				sctp_pegs[SCTP_BAD_VTAGS]++;
31148c2654abSrjs 				if (locked_tcb) {
31158c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
31168c2654abSrjs 				}
31178c2654abSrjs 				return (NULL);
31188c2654abSrjs 			}
31198c2654abSrjs 		} else if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
31208c2654abSrjs 			if (vtag_in != asoc->my_vtag) {
31218c2654abSrjs 				/*
31228c2654abSrjs 				 * this could be a stale SHUTDOWN-ACK or the
31238c2654abSrjs 				 * peer never got the SHUTDOWN-COMPLETE and
31248c2654abSrjs 				 * is still hung; we have started a new asoc
31258c2654abSrjs 				 * but it won't complete until the shutdown is
31268c2654abSrjs 				 * completed
31278c2654abSrjs 				 */
31288c2654abSrjs 				if (locked_tcb) {
31298c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
31308c2654abSrjs 				}
31318c2654abSrjs 				sctp_handle_ootb(m, iphlen, *offset, sh, inp,
31328c2654abSrjs 				    NULL);
31338c2654abSrjs 				return (NULL);
31348c2654abSrjs 			}
31358c2654abSrjs 		} else {
31368c2654abSrjs 			/* for all other chunks, vtag must match */
31378c2654abSrjs 
31388c2654abSrjs 			if (vtag_in != asoc->my_vtag) {
31398c2654abSrjs 				/* invalid vtag... */
31408c2654abSrjs #ifdef SCTP_DEBUG
31418c2654abSrjs 				if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
31428c2654abSrjs 					printf("invalid vtag: %xh, expect %xh\n", vtag_in, asoc->my_vtag);
31438c2654abSrjs 				}
31448c2654abSrjs #endif /* SCTP_DEBUG */
31458c2654abSrjs 				sctp_pegs[SCTP_BAD_VTAGS]++;
31468c2654abSrjs 				if (locked_tcb) {
31478c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
31488c2654abSrjs 				}
31498c2654abSrjs 				*offset = length;
31508c2654abSrjs 				return (NULL);
31518c2654abSrjs 			}
31528c2654abSrjs 		}
31538c2654abSrjs 	}  /* end if !SCTP_COOKIE_ECHO */
31548c2654abSrjs 
31558c2654abSrjs #ifdef SCTP_DEBUG
31568c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
31578c2654abSrjs 		printf("sctp_process_control: vtags ok, processing ctrl chunks\n");
31588c2654abSrjs 	}
31598c2654abSrjs #endif /* SCTP_DEBUG */
31608c2654abSrjs 
31618c2654abSrjs 	/*
31628c2654abSrjs 	 * process all control chunks...
31638c2654abSrjs 	 */
31648c2654abSrjs 	if (((ch->chunk_type == SCTP_SELECTIVE_ACK) ||
31658c2654abSrjs 	    (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) &&
31668c2654abSrjs 	    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
31678c2654abSrjs 	    /* implied cookie-ack.. we must have lost the ack */
31688c2654abSrjs 	    stcb->asoc.overall_error_count = 0;
31698c2654abSrjs 	    sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, *netp);
31708c2654abSrjs 	}
31718c2654abSrjs 
31728c2654abSrjs 	while (IS_SCTP_CONTROL(ch)) {
31738c2654abSrjs 		/* validate chunk length */
31748c2654abSrjs 		chk_length = ntohs(ch->chunk_length);
31758c2654abSrjs #ifdef SCTP_DEBUG
31768c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
31778c2654abSrjs 			printf("sctp_process_control: processing a chunk type=%u, len=%u\n", ch->chunk_type, chk_length);
31788c2654abSrjs 		}
31798c2654abSrjs #endif /* SCTP_DEBUG */
31808c2654abSrjs 		if ((size_t)chk_length < sizeof(*ch) ||
31818c2654abSrjs 		    (*offset + chk_length) > length) {
31828c2654abSrjs #ifdef SCTP_DEBUG
31838c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
31848c2654abSrjs 				printf("sctp_process_control: chunk length invalid! *offset:%u, chk_length:%u > length:%u\n",
3185753b0e65Srjs 				    *offset, chk_length, length);
31868c2654abSrjs 			}
31878c2654abSrjs #endif /* SCTP_DEBUG */
31888c2654abSrjs 			*offset = length;
31898c2654abSrjs 			if (locked_tcb) {
31908c2654abSrjs 				SCTP_TCB_UNLOCK(locked_tcb);
31918c2654abSrjs 			}
31928c2654abSrjs 			return (NULL);
31938c2654abSrjs 		}
31948c2654abSrjs 
31958c2654abSrjs 		/*
31968c2654abSrjs 		 * INIT-ACK only gets the init ack "header" portion only
31978c2654abSrjs 		 * because we don't have to process the peer's COOKIE.
31988c2654abSrjs 		 * All others get a complete chunk.
31998c2654abSrjs 		 */
32008c2654abSrjs 		if (ch->chunk_type == SCTP_INITIATION_ACK) {
32018c2654abSrjs 			/* get an init-ack chunk */
32028c2654abSrjs 			ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
32038c2654abSrjs 			    sizeof(struct sctp_init_ack), chunk_buf);
32048c2654abSrjs 			if (ch == NULL) {
32058c2654abSrjs 				*offset = length;
32068c2654abSrjs 				if (locked_tcb) {
32078c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
32088c2654abSrjs 				}
32098c2654abSrjs 				return (NULL);
32108c2654abSrjs 			}
32118c2654abSrjs 		} else {
32128c2654abSrjs 			/* get a complete chunk... */
32138c2654abSrjs 			if ((size_t)chk_length > sizeof(chunk_buf)) {
32148c2654abSrjs 				struct mbuf *oper;
32158c2654abSrjs 				struct sctp_paramhdr *phdr;
32168c2654abSrjs 				oper = NULL;
32178c2654abSrjs 				MGETHDR(oper, M_DONTWAIT, MT_HEADER);
32188c2654abSrjs 				if (oper) {
32198c2654abSrjs 					/* pre-reserve some space */
32208c2654abSrjs 					oper->m_data +=
32218c2654abSrjs 					    sizeof(struct sctp_chunkhdr);
32228c2654abSrjs 					phdr =
32238c2654abSrjs 					    mtod(oper, struct sctp_paramhdr *);
32248c2654abSrjs 					phdr->param_type =
32258c2654abSrjs 					    htons(SCTP_CAUSE_OUT_OF_RESC);
32268c2654abSrjs 					phdr->param_length =
32278c2654abSrjs 					    htons(sizeof(struct sctp_paramhdr));
32288c2654abSrjs 					sctp_queue_op_err(stcb, oper);
32298c2654abSrjs 				}
32308c2654abSrjs 				if (locked_tcb) {
32318c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
32328c2654abSrjs 				}
32338c2654abSrjs 				return (NULL);
32348c2654abSrjs 			}
32358c2654abSrjs 			ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
32368c2654abSrjs 			    chk_length, chunk_buf);
32378c2654abSrjs 			if (ch == NULL) {
32388c2654abSrjs 				printf("sctp_process_control: Can't get the all data....\n");
32398c2654abSrjs 				*offset = length;
32408c2654abSrjs 				if (locked_tcb) {
32418c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
32428c2654abSrjs 				}
32438c2654abSrjs 				return (NULL);
32448c2654abSrjs 			}
32458c2654abSrjs 
32468c2654abSrjs 		}
32478c2654abSrjs 		num_chunks++;
32488c2654abSrjs 		/* Save off the last place we got a control from */
32498c2654abSrjs 		if ((*netp) && stcb) {
32508c2654abSrjs 			stcb->asoc.last_control_chunk_from = *netp;
32518c2654abSrjs 		}
32528c2654abSrjs #ifdef SCTP_AUDITING_ENABLED
32538c2654abSrjs 		sctp_audit_log(0xB0, ch->chunk_type);
32548c2654abSrjs #endif
32558c2654abSrjs 		switch (ch->chunk_type) {
32568c2654abSrjs 		case SCTP_INITIATION:
32578c2654abSrjs 			/* must be first and only chunk */
32588c2654abSrjs #ifdef SCTP_DEBUG
32598c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
32608c2654abSrjs 				printf("SCTP_INIT\n");
32618c2654abSrjs 			}
32628c2654abSrjs #endif /* SCTP_DEBUG */
32638c2654abSrjs 			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
32648c2654abSrjs 				/* We are not interested anymore */
32658c2654abSrjs 				if (locked_tcb) {
32668c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
32678c2654abSrjs 				}
32688c2654abSrjs 				if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
32698c2654abSrjs 					/* finish the job now */
32708c2654abSrjs 					sctp_inpcb_free(inp, 1);
32718c2654abSrjs 				}
32728c2654abSrjs 				*offset = length;
32738c2654abSrjs 				return (NULL);
32748c2654abSrjs 			}
32758c2654abSrjs 			if ((num_chunks > 1) ||
32768c2654abSrjs 			    (sctp_strict_init && (length - *offset > SCTP_SIZE32(chk_length)))) {
32778c2654abSrjs 				*offset = length;
32788c2654abSrjs 				if (locked_tcb) {
32798c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
32808c2654abSrjs 				}
32818c2654abSrjs 				return (NULL);
32828c2654abSrjs 			}
32838c2654abSrjs 			if ((stcb != NULL) &&
32848c2654abSrjs 			    (SCTP_GET_STATE(&stcb->asoc) ==
32858c2654abSrjs 			    SCTP_STATE_SHUTDOWN_ACK_SENT)) {
32868c2654abSrjs 				sctp_send_shutdown_ack(stcb,
32878c2654abSrjs 				    stcb->asoc.primary_destination);
32888c2654abSrjs 				*offset = length;
32898c2654abSrjs 				if (locked_tcb) {
32908c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
32918c2654abSrjs 				}
32928c2654abSrjs 				return (NULL);
32938c2654abSrjs 			}
32948c2654abSrjs 			sctp_handle_init(m, iphlen, *offset, sh,
32958c2654abSrjs 			    (struct sctp_init_chunk *)ch, inp, stcb, *netp);
32968c2654abSrjs 			*offset = length;
32978c2654abSrjs 			if (locked_tcb) {
32988c2654abSrjs 				SCTP_TCB_UNLOCK(locked_tcb);
32998c2654abSrjs 			}
33008c2654abSrjs 			return (NULL);
33018c2654abSrjs 			break;
33028c2654abSrjs 		case SCTP_INITIATION_ACK:
33038c2654abSrjs 			/* must be first and only chunk */
33048c2654abSrjs #ifdef SCTP_DEBUG
33058c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33068c2654abSrjs 				printf("SCTP_INIT-ACK\n");
33078c2654abSrjs 			}
33088c2654abSrjs #endif /* SCTP_DEBUG */
33098c2654abSrjs 			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
33108c2654abSrjs 				/* We are not interested anymore */
33118c2654abSrjs 				if (locked_tcb) {
33128c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
33138c2654abSrjs 				}
33148c2654abSrjs 				*offset = length;
33158c2654abSrjs 				if (stcb) {
33168c2654abSrjs 					sctp_free_assoc(inp, stcb);
33178c2654abSrjs 				} else {
33188c2654abSrjs 					if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
33198c2654abSrjs 						/* finish the job now */
33208c2654abSrjs 						sctp_inpcb_free(inp, 1);
33218c2654abSrjs 					}
33228c2654abSrjs 				}
33238c2654abSrjs 				return (NULL);
33248c2654abSrjs 			}
33258c2654abSrjs 			if ((num_chunks > 1) ||
33268c2654abSrjs 			    (sctp_strict_init && (length - *offset > SCTP_SIZE32(chk_length)))) {
33278c2654abSrjs #ifdef SCTP_DEBUG
33288c2654abSrjs 				if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33298c2654abSrjs 					printf("Length is %d rounded chk_length:%d .. dropping\n",
33308c2654abSrjs 					    length - *offset,
33318c2654abSrjs 					    SCTP_SIZE32(chk_length));
33328c2654abSrjs 				}
33338c2654abSrjs #endif
33348c2654abSrjs 				*offset = length;
33358c2654abSrjs 				if (locked_tcb) {
33368c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
33378c2654abSrjs 				}
33388c2654abSrjs 				return (NULL);
33398c2654abSrjs 			}
33408c2654abSrjs 			ret = sctp_handle_init_ack(m, iphlen, *offset, sh,
33418c2654abSrjs 			    (struct sctp_init_ack_chunk *)ch, stcb, *netp);
33428c2654abSrjs 			/*
33438c2654abSrjs 			 * Special case, I must call the output routine
33448c2654abSrjs 			 * to get the cookie echoed
33458c2654abSrjs 			 */
33468c2654abSrjs 			if ((stcb) && ret == 0)
33478c2654abSrjs 				sctp_chunk_output(stcb->sctp_ep, stcb, 2);
33488c2654abSrjs 			*offset = length;
33498c2654abSrjs #ifdef SCTP_DEBUG
33508c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33518c2654abSrjs 				printf("All done INIT-ACK processing\n");
33528c2654abSrjs 			}
33538c2654abSrjs #endif
33548c2654abSrjs 			if (locked_tcb) {
33558c2654abSrjs 				SCTP_TCB_UNLOCK(locked_tcb);
33568c2654abSrjs 			}
33578c2654abSrjs 			return (NULL);
33588c2654abSrjs 			break;
33598c2654abSrjs 		case SCTP_SELECTIVE_ACK:
33608c2654abSrjs #ifdef SCTP_DEBUG
33618c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33628c2654abSrjs 				printf("SCTP_SACK\n");
33638c2654abSrjs 			}
33648c2654abSrjs #endif /* SCTP_DEBUG */
33658c2654abSrjs 			sctp_pegs[SCTP_PEG_SACKS_SEEN]++;
33668c2654abSrjs 			{
33678c2654abSrjs 				int abort_now = 0;
33688c2654abSrjs 				stcb->asoc.seen_a_sack_this_pkt = 1;
33698c2654abSrjs 				sctp_handle_sack((struct sctp_sack_chunk *)ch,
33708c2654abSrjs 				    stcb, *netp, &abort_now);
33718c2654abSrjs 				if (abort_now) {
33728c2654abSrjs 					/* ABORT signal from sack processing */
33738c2654abSrjs 					*offset = length;
33748c2654abSrjs 					return (NULL);
33758c2654abSrjs 				}
33768c2654abSrjs 			}
33778c2654abSrjs 			break;
33788c2654abSrjs 		case SCTP_HEARTBEAT_REQUEST:
33798c2654abSrjs #ifdef SCTP_DEBUG
33808c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33818c2654abSrjs 				printf("SCTP_HEARTBEAT\n");
33828c2654abSrjs 			}
33838c2654abSrjs #endif /* SCTP_DEBUG */
33848c2654abSrjs 			sctp_pegs[SCTP_HB_RECV]++;
33858c2654abSrjs 			sctp_send_heartbeat_ack(stcb, m, *offset, chk_length,
33868c2654abSrjs 			    *netp);
33878c2654abSrjs 
33888c2654abSrjs 			/* He's alive so give him credit */
33898c2654abSrjs 			stcb->asoc.overall_error_count = 0;
33908c2654abSrjs 			break;
33918c2654abSrjs 		case SCTP_HEARTBEAT_ACK:
33928c2654abSrjs #ifdef SCTP_DEBUG
33938c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33948c2654abSrjs 				printf("SCTP_HEARTBEAT-ACK\n");
33958c2654abSrjs 			}
33968c2654abSrjs #endif /* SCTP_DEBUG */
33978c2654abSrjs 
33988c2654abSrjs 			/* He's alive so give him credit */
33998c2654abSrjs 			stcb->asoc.overall_error_count = 0;
34008c2654abSrjs 
34018c2654abSrjs 			sctp_pegs[SCTP_HB_ACK_RECV]++;
34028c2654abSrjs 			sctp_handle_heartbeat_ack((struct sctp_heartbeat_chunk *)ch,
34038c2654abSrjs 			    stcb, *netp);
34048c2654abSrjs 			break;
34058c2654abSrjs 		case SCTP_ABORT_ASSOCIATION:
34068c2654abSrjs #ifdef SCTP_DEBUG
34078c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
34088c2654abSrjs 				printf("SCTP_ABORT\n");
34098c2654abSrjs 			}
34108c2654abSrjs #endif /* SCTP_DEBUG */
34118c2654abSrjs 			sctp_handle_abort((struct sctp_abort_chunk *)ch,
34128c2654abSrjs 			    stcb, *netp);
34138c2654abSrjs 			*offset = length;
34148c2654abSrjs 			return (NULL);
34158c2654abSrjs 			break;
34168c2654abSrjs 		case SCTP_SHUTDOWN:
34178c2654abSrjs #ifdef SCTP_DEBUG
34188c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
34198c2654abSrjs 				printf("SCTP_SHUTDOWN\n");
34208c2654abSrjs 			}
34218c2654abSrjs #endif /* SCTP_DEBUG */
34228c2654abSrjs                        {
34238c2654abSrjs 			       int abort_flag = 0;
34248c2654abSrjs 			       sctp_handle_shutdown((struct sctp_shutdown_chunk *)ch,
34258c2654abSrjs 				   stcb, *netp, &abort_flag);
34268c2654abSrjs 			       if (abort_flag) {
34278c2654abSrjs 				       *offset = length;
34288c2654abSrjs 				       return (NULL);
34298c2654abSrjs 			       }
34308c2654abSrjs 		       }
34318c2654abSrjs 			break;
34328c2654abSrjs 		case SCTP_SHUTDOWN_ACK:
34338c2654abSrjs #ifdef SCTP_DEBUG
34348c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
34358c2654abSrjs 				printf("SCTP_SHUTDOWN-ACK\n");
34368c2654abSrjs 			}
34378c2654abSrjs #endif /* SCTP_DEBUG */
34388c2654abSrjs 			sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp);
34398c2654abSrjs 			*offset = length;
34408c2654abSrjs 			return (NULL);
34418c2654abSrjs 			break;
34428c2654abSrjs 		case SCTP_OPERATION_ERROR:
34438c2654abSrjs #ifdef SCTP_DEBUG
34448c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
34458c2654abSrjs 				printf("SCTP_OP-ERR\n");
34468c2654abSrjs 			}
34478c2654abSrjs #endif /* SCTP_DEBUG */
34488c2654abSrjs 			if (sctp_handle_error(ch, stcb, *netp) < 0) {
34498c2654abSrjs 				*offset = length;
34508c2654abSrjs 				return (NULL);
34518c2654abSrjs 			}
34528c2654abSrjs 			break;
34538c2654abSrjs 		case SCTP_COOKIE_ECHO:
34548c2654abSrjs #ifdef SCTP_DEBUG
34558c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
34568c2654abSrjs 				printf("SCTP_COOKIE-ECHO stcb is %p\n", stcb);
34578c2654abSrjs 			}
34588c2654abSrjs #endif /* SCTP_DEBUG */
34598c2654abSrjs 			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
34608c2654abSrjs 				/* We are not interested anymore */
34618c2654abSrjs 				*offset = length;
34628c2654abSrjs 				if (stcb) {
34638c2654abSrjs 					sctp_free_assoc(inp, stcb);
34648c2654abSrjs 				} else {
34658c2654abSrjs 					if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
34668c2654abSrjs 						/* finish the job now */
34678c2654abSrjs 						sctp_inpcb_free(inp, 1);
34688c2654abSrjs 					}
34698c2654abSrjs 				}
34708c2654abSrjs 				return (NULL);
34718c2654abSrjs 			}
34728c2654abSrjs 			/*
34738c2654abSrjs 			 * First are we accepting?
34748c2654abSrjs 			 * We do this again here since it is possible
34758c2654abSrjs 			 * that a previous endpoint WAS listening responded to
34768c2654abSrjs 			 * a INIT-ACK and then closed. We opened and bound..
34778c2654abSrjs 			 * and are now no longer listening.
34788c2654abSrjs 			 */
34798c2654abSrjs 			if (((inp->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING) == 0) ||
34808c2654abSrjs 			    (inp->sctp_socket->so_qlimit == 0)) {
34818c2654abSrjs 				sctp_abort_association(inp, stcb, m, iphlen, sh,
34828c2654abSrjs 				    NULL);
34838c2654abSrjs 				*offset = length;
34848c2654abSrjs 				return (NULL);
34858c2654abSrjs 			} else if (inp->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING) {
34868c2654abSrjs 				/* we are accepting so check limits like TCP */
34878c2654abSrjs 				if (inp->sctp_socket->so_qlen >
34888c2654abSrjs 				    inp->sctp_socket->so_qlimit) {
34898c2654abSrjs 					/* no space */
34908c2654abSrjs 					struct mbuf *oper;
34918c2654abSrjs 					struct sctp_paramhdr *phdr;
34928c2654abSrjs 					oper = NULL;
34938c2654abSrjs 					MGETHDR(oper, M_DONTWAIT, MT_HEADER);
34948c2654abSrjs 					if (oper) {
34958c2654abSrjs 						oper->m_len =
34968c2654abSrjs 						    oper->m_pkthdr.len =
34978c2654abSrjs 						    sizeof(struct sctp_paramhdr);
34988c2654abSrjs 						phdr = mtod(oper,
34998c2654abSrjs 						    struct sctp_paramhdr *);
35008c2654abSrjs 						phdr->param_type =
35018c2654abSrjs 						    htons(SCTP_CAUSE_OUT_OF_RESC);
35028c2654abSrjs 						phdr->param_length =
35038c2654abSrjs 						    htons(sizeof(struct sctp_paramhdr));
35048c2654abSrjs 					}
35058c2654abSrjs 					sctp_abort_association(inp, stcb, m,
35068c2654abSrjs 					    iphlen, sh, oper);
35078c2654abSrjs 					*offset = length;
35088c2654abSrjs 					return (NULL);
35098c2654abSrjs 				}
35108c2654abSrjs 			}
35118c2654abSrjs 			{
35128c2654abSrjs 				struct mbuf *ret_buf;
35138c2654abSrjs 				ret_buf = sctp_handle_cookie_echo(m, iphlen,
35148c2654abSrjs 				    *offset, sh,
35158c2654abSrjs 				    (struct sctp_cookie_echo_chunk *)ch, &inp,
35168c2654abSrjs 				    &stcb, netp);
35178c2654abSrjs #ifdef SCTP_DEBUG
35188c2654abSrjs 				if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35198c2654abSrjs 					printf("ret_buf:%p length:%d off:%d\n",
35208c2654abSrjs 					    ret_buf, length, *offset);
35218c2654abSrjs 				}
35228c2654abSrjs #endif /* SCTP_DEBUG */
35238c2654abSrjs 
35248c2654abSrjs 				if (ret_buf == NULL) {
35258c2654abSrjs 					if (locked_tcb) {
35268c2654abSrjs 						SCTP_TCB_UNLOCK(locked_tcb);
35278c2654abSrjs 					}
35288c2654abSrjs #ifdef SCTP_DEBUG
35298c2654abSrjs 					if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35308c2654abSrjs 						printf("GAK, null buffer\n");
35318c2654abSrjs 					}
35328c2654abSrjs #endif /* SCTP_DEBUG */
35338c2654abSrjs 					*offset = length;
35348c2654abSrjs 					return (NULL);
35358c2654abSrjs 				}
35368c2654abSrjs 				if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
35378c2654abSrjs 					/*
35388c2654abSrjs 					 * Restart the timer if we have pending
35398c2654abSrjs 					 * data
35408c2654abSrjs 					 */
35418c2654abSrjs 					struct sctp_tmit_chunk *chk;
35428c2654abSrjs 					chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
35438c2654abSrjs 					if (chk) {
35448c2654abSrjs 						sctp_timer_start(SCTP_TIMER_TYPE_SEND,
35458c2654abSrjs 						    stcb->sctp_ep, stcb,
35468c2654abSrjs 						    chk->whoTo);
35478c2654abSrjs 					}
35488c2654abSrjs 				}
35498c2654abSrjs 			}
35508c2654abSrjs 			break;
35518c2654abSrjs 		case SCTP_COOKIE_ACK:
35528c2654abSrjs #ifdef SCTP_DEBUG
35538c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35548c2654abSrjs 				printf("SCTP_COOKIE-ACK\n");
35558c2654abSrjs 			}
35568c2654abSrjs #endif /* SCTP_DEBUG */
35578c2654abSrjs 
35588c2654abSrjs 			if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
35598c2654abSrjs 				/* We are not interested anymore */
35608c2654abSrjs 				sctp_free_assoc(inp, stcb);
35618c2654abSrjs 				*offset = length;
35628c2654abSrjs 				return (NULL);
35638c2654abSrjs 			}
35648c2654abSrjs 			/* He's alive so give him credit */
35658c2654abSrjs 			stcb->asoc.overall_error_count = 0;
35668c2654abSrjs 			sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch,
35678c2654abSrjs 			    stcb, *netp);
35688c2654abSrjs 			break;
35698c2654abSrjs 		case SCTP_ECN_ECHO:
35708c2654abSrjs #ifdef SCTP_DEBUG
35718c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35728c2654abSrjs 				printf("SCTP_ECN-ECHO\n");
35738c2654abSrjs 			}
35748c2654abSrjs #endif /* SCTP_DEBUG */
35758c2654abSrjs 			/* He's alive so give him credit */
35768c2654abSrjs 			stcb->asoc.overall_error_count = 0;
35778c2654abSrjs 			sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch,
35788c2654abSrjs 			    stcb);
35798c2654abSrjs 			break;
35808c2654abSrjs 		case SCTP_ECN_CWR:
35818c2654abSrjs #ifdef SCTP_DEBUG
35828c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35838c2654abSrjs 				printf("SCTP_ECN-CWR\n");
35848c2654abSrjs 			}
35858c2654abSrjs #endif /* SCTP_DEBUG */
35868c2654abSrjs 			/* He's alive so give him credit */
35878c2654abSrjs 			stcb->asoc.overall_error_count = 0;
35888c2654abSrjs 
35898c2654abSrjs 			sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb);
35908c2654abSrjs 			break;
35918c2654abSrjs 		case SCTP_SHUTDOWN_COMPLETE:
35928c2654abSrjs #ifdef SCTP_DEBUG
35938c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35948c2654abSrjs 				printf("SCTP_SHUTDOWN-COMPLETE\n");
35958c2654abSrjs 			}
35968c2654abSrjs #endif /* SCTP_DEBUG */
35978c2654abSrjs 			/* must be first and only chunk */
35988c2654abSrjs 			if ((num_chunks > 1) ||
35998c2654abSrjs 			    (length - *offset > SCTP_SIZE32(chk_length))) {
36008c2654abSrjs 				*offset = length;
36018c2654abSrjs 				if (locked_tcb) {
36028c2654abSrjs 					SCTP_TCB_UNLOCK(locked_tcb);
36038c2654abSrjs 				}
36048c2654abSrjs 				return (NULL);
36058c2654abSrjs 			}
36068c2654abSrjs 			sctp_handle_shutdown_complete((struct sctp_shutdown_complete_chunk *)ch,
36078c2654abSrjs 			    stcb, *netp);
36088c2654abSrjs 			*offset = length;
36098c2654abSrjs 			return (NULL);
36108c2654abSrjs 			break;
36118c2654abSrjs 		case SCTP_ASCONF:
36128c2654abSrjs #ifdef SCTP_DEBUG
36138c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
36148c2654abSrjs 				printf("SCTP_ASCONF\n");
36158c2654abSrjs 			}
36168c2654abSrjs #endif /* SCTP_DEBUG */
36178c2654abSrjs 			/* He's alive so give him credit */
36188c2654abSrjs 			stcb->asoc.overall_error_count = 0;
36198c2654abSrjs 
36208c2654abSrjs 			sctp_handle_asconf(m, *offset,
36218c2654abSrjs 			    (struct sctp_asconf_chunk *)ch, stcb, *netp);
36228c2654abSrjs 			break;
36238c2654abSrjs 		case SCTP_ASCONF_ACK:
36248c2654abSrjs #ifdef SCTP_DEBUG
36258c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
36268c2654abSrjs 				printf("SCTP_ASCONF-ACK\n");
36278c2654abSrjs 			}
36288c2654abSrjs #endif /* SCTP_DEBUG */
36298c2654abSrjs 			/* He's alive so give him credit */
36308c2654abSrjs 			stcb->asoc.overall_error_count = 0;
36318c2654abSrjs 
36328c2654abSrjs 			sctp_handle_asconf_ack(m, *offset,
36338c2654abSrjs 			    (struct sctp_asconf_ack_chunk *)ch, stcb, *netp);
36348c2654abSrjs 			break;
36358c2654abSrjs 		case SCTP_FORWARD_CUM_TSN:
36368c2654abSrjs #ifdef SCTP_DEBUG
36378c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
36388c2654abSrjs 				printf("SCTP_FWD-TSN\n");
36398c2654abSrjs 			}
36408c2654abSrjs #endif /* SCTP_DEBUG */
36418c2654abSrjs 			/* He's alive so give him credit */
36428c2654abSrjs                         {
36438c2654abSrjs 				int abort_flag = 0;
36448c2654abSrjs 				stcb->asoc.overall_error_count = 0;
36458c2654abSrjs 				*fwd_tsn_seen = 1;
36468c2654abSrjs 				sctp_handle_forward_tsn(stcb,
36478c2654abSrjs 				    (struct sctp_forward_tsn_chunk *)ch, &abort_flag);
36488c2654abSrjs 				if (abort_flag) {
36498c2654abSrjs 					*offset = length;
36508c2654abSrjs 					return (NULL);
36518c2654abSrjs 				} else {
36528c2654abSrjs 					stcb->asoc.overall_error_count = 0;
36538c2654abSrjs 				}
36548c2654abSrjs 
36558c2654abSrjs                         }
36568c2654abSrjs 			break;
36578c2654abSrjs 		case SCTP_STREAM_RESET:
36588c2654abSrjs #ifdef SCTP_DEBUG
36598c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
36608c2654abSrjs 				printf("SCTP_STREAM_RESET\n");
36618c2654abSrjs 			}
36628c2654abSrjs #endif /* SCTP_DEBUG */
36638c2654abSrjs 			ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
36648c2654abSrjs 			    chk_length, chunk_buf);
36658c2654abSrjs 			if (stcb->asoc.peer_supports_strreset == 0) {
36668c2654abSrjs 				/* hmm, peer should have annonced this, but
36678c2654abSrjs 				 * we will turn it on since he is sending us
36688c2654abSrjs 				 * a stream reset.
36698c2654abSrjs 				 */
36708c2654abSrjs 				stcb->asoc.peer_supports_strreset = 1;
36718c2654abSrjs  			}
36728c2654abSrjs 			sctp_handle_stream_reset(stcb, (struct sctp_stream_reset_req *)ch);
36738c2654abSrjs 			break;
36748c2654abSrjs 		case SCTP_PACKET_DROPPED:
36758c2654abSrjs #ifdef SCTP_DEBUG
36768c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
36778c2654abSrjs 				printf("SCTP_PACKET_DROPPED\n");
36788c2654abSrjs 			}
36798c2654abSrjs #endif /* SCTP_DEBUG */
36808c2654abSrjs 			/* re-get it all please */
36818c2654abSrjs 			ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
36828c2654abSrjs 			    chk_length, chunk_buf);
36838c2654abSrjs 
36848c2654abSrjs 			sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch,
36858c2654abSrjs 			    stcb, *netp);
36868c2654abSrjs 
36878c2654abSrjs 
36888c2654abSrjs 			break;
36898c2654abSrjs 		default:
36908c2654abSrjs 			/* it's an unknown chunk! */
36918c2654abSrjs 			if ((ch->chunk_type & 0x40) && (stcb != NULL)) {
36928c2654abSrjs 				struct mbuf *mm;
36938c2654abSrjs 				struct sctp_paramhdr *phd;
36948c2654abSrjs 				MGETHDR(mm, M_DONTWAIT, MT_HEADER);
36958c2654abSrjs 				if (mm) {
36968c2654abSrjs 					phd = mtod(mm, struct sctp_paramhdr *);
36978c2654abSrjs 					/* We cheat and use param type since we
36988c2654abSrjs 					 * did not bother to define a error
36998c2654abSrjs 					 * cause struct.
37008c2654abSrjs 					 * They are the same basic format with
37018c2654abSrjs 					 * different names.
37028c2654abSrjs 					 */
37038c2654abSrjs 					phd->param_type =
37048c2654abSrjs 					    htons(SCTP_CAUSE_UNRECOG_CHUNK);
37058c2654abSrjs 					phd->param_length =
37068c2654abSrjs 					    htons(chk_length + sizeof(*phd));
37078c2654abSrjs 					mm->m_len = sizeof(*phd);
37088c2654abSrjs 					mm->m_next = sctp_m_copym(m, *offset,
37098c2654abSrjs 					    SCTP_SIZE32(chk_length),
37108c2654abSrjs 					    M_DONTWAIT);
37118c2654abSrjs 					if (mm->m_next) {
37128c2654abSrjs 						mm->m_pkthdr.len =
37138c2654abSrjs 						    SCTP_SIZE32(chk_length) +
37148c2654abSrjs 						    sizeof(*phd);
37158c2654abSrjs 						sctp_queue_op_err(stcb, mm);
37168c2654abSrjs 					} else {
37178c2654abSrjs 						sctp_m_freem(mm);
37188c2654abSrjs #ifdef SCTP_DEBUG
37198c2654abSrjs 						if (sctp_debug_on &
37208c2654abSrjs 						    SCTP_DEBUG_INPUT1) {
37218c2654abSrjs 							printf("Gak can't copy the chunk into operr %d bytes\n",
37228c2654abSrjs 							    chk_length);
37238c2654abSrjs 						}
37248c2654abSrjs #endif
37258c2654abSrjs 					}
37268c2654abSrjs 				}
37278c2654abSrjs #ifdef SCTP_DEBUG
37288c2654abSrjs 				else {
37298c2654abSrjs 					if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
37308c2654abSrjs 						printf("Gak can't mgethdr for op-err of unrec chunk\n");
37318c2654abSrjs 					}
37328c2654abSrjs 				}
37338c2654abSrjs #endif
37348c2654abSrjs 			}
37358c2654abSrjs 			if ((ch->chunk_type & 0x80) == 0) {
37368c2654abSrjs 				/* discard this packet */
37378c2654abSrjs 				*offset = length;
37388c2654abSrjs 				return (stcb);
37398c2654abSrjs 			} /* else skip this bad chunk and continue... */
37408c2654abSrjs 			break;
37418c2654abSrjs 		} /* switch (ch->chunk_type) */
37428c2654abSrjs 		/* get the next chunk */
37438c2654abSrjs 		*offset += SCTP_SIZE32(chk_length);
37448c2654abSrjs 		if (*offset >= length) {
37458c2654abSrjs 			/* no more data left in the mbuf chain */
37468c2654abSrjs 			break;
37478c2654abSrjs 		}
37488c2654abSrjs 		ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
37498c2654abSrjs 		    sizeof(struct sctp_chunkhdr), chunk_buf);
37508c2654abSrjs 		if (ch == NULL) {
37518c2654abSrjs 			if (locked_tcb) {
37528c2654abSrjs 				SCTP_TCB_UNLOCK(locked_tcb);
37538c2654abSrjs 			}
37548c2654abSrjs 			*offset = length;
37558c2654abSrjs 			return (NULL);
37568c2654abSrjs 		}
37578c2654abSrjs 	} /* while */
37588c2654abSrjs 	return (stcb);
37598c2654abSrjs }
37608c2654abSrjs 
37618c2654abSrjs 
37628c2654abSrjs /*
37638c2654abSrjs  * Process the ECN bits we have something set so
37648c2654abSrjs  * we must look to see if it is ECN(0) or ECN(1) or CE
37658c2654abSrjs  */
37668c2654abSrjs static void
sctp_process_ecn_marked_a(struct sctp_tcb * stcb,struct sctp_nets * net,u_int8_t ecn_bits)37678c2654abSrjs sctp_process_ecn_marked_a(struct sctp_tcb *stcb, struct sctp_nets *net,
37688c2654abSrjs     u_int8_t ecn_bits)
37698c2654abSrjs {
37708c2654abSrjs 	if ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS) {
37718c2654abSrjs 		;
37728c2654abSrjs 	} else if ((ecn_bits & SCTP_ECT1_BIT) == SCTP_ECT1_BIT) {
37738c2654abSrjs 		/*
37748c2654abSrjs 		 * we only add to the nonce sum for ECT1, ECT0
37758c2654abSrjs 		 * does not change the NS bit (that we have
37768c2654abSrjs 		 * yet to find a way to send it yet).
37778c2654abSrjs 		 */
37788c2654abSrjs 
37798c2654abSrjs 		/* ECN Nonce stuff */
37808c2654abSrjs 		stcb->asoc.receiver_nonce_sum++;
37818c2654abSrjs 		stcb->asoc.receiver_nonce_sum &= SCTP_SACK_NONCE_SUM;
37828c2654abSrjs 
37838c2654abSrjs 		/*
37848c2654abSrjs 		 * Drag up the last_echo point if cumack is larger since we
37858c2654abSrjs 		 * don't want the point falling way behind by more than 2^^31
37868c2654abSrjs 		 * and then having it be incorrect.
37878c2654abSrjs 		 */
37888c2654abSrjs 		if (compare_with_wrap(stcb->asoc.cumulative_tsn,
37898c2654abSrjs 		    stcb->asoc.last_echo_tsn, MAX_TSN)) {
37908c2654abSrjs 			stcb->asoc.last_echo_tsn = stcb->asoc.cumulative_tsn;
37918c2654abSrjs 		}
37928c2654abSrjs 	} else if ((ecn_bits & SCTP_ECT0_BIT) == SCTP_ECT0_BIT) {
37938c2654abSrjs 		/*
37948c2654abSrjs 		 * Drag up the last_echo point if cumack is larger since we
37958c2654abSrjs 		 * don't want the point falling way behind by more than 2^^31
37968c2654abSrjs 		 * and then having it be incorrect.
37978c2654abSrjs 		 */
37988c2654abSrjs 		if (compare_with_wrap(stcb->asoc.cumulative_tsn,
37998c2654abSrjs 		    stcb->asoc.last_echo_tsn, MAX_TSN)) {
38008c2654abSrjs 			stcb->asoc.last_echo_tsn = stcb->asoc.cumulative_tsn;
38018c2654abSrjs 		}
38028c2654abSrjs 	}
38038c2654abSrjs }
38048c2654abSrjs 
38058c2654abSrjs static void
sctp_process_ecn_marked_b(struct sctp_tcb * stcb,struct sctp_nets * net,u_int32_t high_tsn,u_int8_t ecn_bits)38068c2654abSrjs sctp_process_ecn_marked_b(struct sctp_tcb *stcb, struct sctp_nets *net,
38078c2654abSrjs     u_int32_t high_tsn, u_int8_t ecn_bits)
38088c2654abSrjs {
38098c2654abSrjs 	if ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS) {
38108c2654abSrjs 		/*
38118c2654abSrjs 		 * we possibly must notify the sender that a congestion
38128c2654abSrjs 		 * window reduction is in order. We do this
38138c2654abSrjs 		 * by adding a ECNE chunk to the output chunk
38148c2654abSrjs 		 * queue. The incoming CWR will remove this chunk.
38158c2654abSrjs 		 */
38168c2654abSrjs 		if (compare_with_wrap(high_tsn, stcb->asoc.last_echo_tsn,
38178c2654abSrjs 		    MAX_TSN)) {
38188c2654abSrjs 			/* Yep, we need to add a ECNE */
38198c2654abSrjs 			sctp_send_ecn_echo(stcb, net, high_tsn);
38208c2654abSrjs 			stcb->asoc.last_echo_tsn = high_tsn;
38218c2654abSrjs 		}
38228c2654abSrjs 	}
38238c2654abSrjs }
38248c2654abSrjs 
38258c2654abSrjs /*
38268c2654abSrjs  * common input chunk processing (v4 and v6)
38278c2654abSrjs  */
38288c2654abSrjs int
sctp_common_input_processing(struct mbuf ** mm,int iphlen,int offset,int length,struct sctphdr * sh,struct sctp_chunkhdr * ch,struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets * net,u_int8_t ecn_bits)38298c2654abSrjs sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
38308c2654abSrjs     int length, struct sctphdr *sh, struct sctp_chunkhdr *ch,
38318c2654abSrjs     struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets *net,
38328c2654abSrjs     u_int8_t ecn_bits)
38338c2654abSrjs {
38348c2654abSrjs 	/*
38358c2654abSrjs 	 * Control chunk processing
38368c2654abSrjs 	 */
38378c2654abSrjs 	u_int32_t high_tsn;
38388c2654abSrjs 	int fwd_tsn_seen = 0, data_processed = 0;
38398c2654abSrjs 	struct mbuf *m = *mm;
38408c2654abSrjs 	int abort_flag = 0;
38418c2654abSrjs 
38428c2654abSrjs 	sctp_pegs[SCTP_DATAGRAMS_RCVD]++;
38438c2654abSrjs #ifdef SCTP_AUDITING_ENABLED
38448c2654abSrjs 	sctp_audit_log(0xE0, 1);
38458c2654abSrjs 	sctp_auditing(0, inp, stcb, net);
38468c2654abSrjs #endif
38478c2654abSrjs 
38488c2654abSrjs #ifdef SCTP_DEBUG
38498c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
38508c2654abSrjs 		printf("Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d\n",
38518c2654abSrjs 		       m, iphlen, offset, length);
38528c2654abSrjs 	}
38538c2654abSrjs #endif /* SCTP_DEBUG */
38548c2654abSrjs 	if (IS_SCTP_CONTROL(ch)) {
38558c2654abSrjs 		/* process the control portion of the SCTP packet */
38568c2654abSrjs #ifdef SCTP_DEBUG
38578c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
38588c2654abSrjs 			printf("Processing control\n");
38598c2654abSrjs 		}
38608c2654abSrjs #endif /* SCTP_DEBUG */
38618c2654abSrjs 
38628c2654abSrjs 		stcb = sctp_process_control(m, iphlen, &offset, length, sh, ch,
38638c2654abSrjs 		    inp, stcb, &net, &fwd_tsn_seen);
38648c2654abSrjs 	} else {
38658c2654abSrjs 		/*
38668c2654abSrjs 		 * no control chunks, so pre-process DATA chunks
38678c2654abSrjs 		 * (these checks are taken care of by control processing)
38688c2654abSrjs 		 */
38698c2654abSrjs #ifdef SCTP_DEBUG
38708c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
38718c2654abSrjs 			printf("No control present\n");
38728c2654abSrjs 		}
38738c2654abSrjs #endif /* SCTP_DEBUG */
38748c2654abSrjs 
38758c2654abSrjs 		if (stcb == NULL) {
38768c2654abSrjs 			/* out of the blue DATA chunk */
38778c2654abSrjs 			sctp_handle_ootb(m, iphlen, offset, sh, inp, NULL);
38788c2654abSrjs 			return (1);
38798c2654abSrjs 		}
38808c2654abSrjs 		if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) {
38818c2654abSrjs 			/* v_tag mismatch! */
38828c2654abSrjs 			sctp_pegs[SCTP_BAD_VTAGS]++;
38838c2654abSrjs 			SCTP_TCB_UNLOCK(stcb);
38848c2654abSrjs 			return (1);
38858c2654abSrjs 		}
38868c2654abSrjs 	}
38878c2654abSrjs 	if (stcb == NULL) {
38888c2654abSrjs 		/*
38898c2654abSrjs 		 * no valid TCB for this packet,
38908c2654abSrjs 		 * or we found it's a bad packet while processing control,
38918c2654abSrjs 		 * or we're done with this packet (done or skip rest of data),
38928c2654abSrjs 		 * so we drop it...
38938c2654abSrjs 		 */
38948c2654abSrjs 		return (1);
38958c2654abSrjs 	}
38968c2654abSrjs #ifdef SCTP_DEBUG
38978c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
38988c2654abSrjs 		printf("Ok, control finished time to look for data (%d) offset:%d\n",
38998c2654abSrjs 		       length, offset);
39008c2654abSrjs 	}
39018c2654abSrjs #endif /* SCTP_DEBUG */
39028c2654abSrjs 	/*
39038c2654abSrjs 	 * DATA chunk processing
39048c2654abSrjs 	 */
39058c2654abSrjs 	/* plow through the data chunks while length > offset */
39068c2654abSrjs 	stcb->asoc.seen_a_sack_this_pkt = 0;
39078c2654abSrjs 
39088c2654abSrjs 	if (length > offset) {
39098c2654abSrjs 		int retval;
39108c2654abSrjs 		/*
39118c2654abSrjs 		 * First check to make sure our state is correct.
39128c2654abSrjs 		 * We would not get here unless we really did have a
39138c2654abSrjs 		 * tag, so we don't abort if this happens, just
39148c2654abSrjs 		 * dump the chunk silently.
39158c2654abSrjs 		 */
39168c2654abSrjs 		switch (SCTP_GET_STATE(&stcb->asoc)) {
39178c2654abSrjs 		case SCTP_STATE_COOKIE_ECHOED:
39188c2654abSrjs 			/*
39198c2654abSrjs 			 * we consider data with valid tags in
39208c2654abSrjs 			 * this state shows us the cookie-ack was lost.
39218c2654abSrjs 			 * Imply it was there.
39228c2654abSrjs 			 */
39238c2654abSrjs 			stcb->asoc.overall_error_count = 0;
39248c2654abSrjs 			sctp_handle_cookie_ack(
39258c2654abSrjs 			    (struct sctp_cookie_ack_chunk *)ch, stcb, net);
39268c2654abSrjs 			break;
39278c2654abSrjs 		case SCTP_STATE_COOKIE_WAIT:
39288c2654abSrjs 			/*
39298c2654abSrjs 			 * We consider OOTB any data sent during asoc setup.
39308c2654abSrjs 			 */
39318c2654abSrjs 			sctp_handle_ootb(m, iphlen, offset, sh, inp, NULL);
39328c2654abSrjs 			SCTP_TCB_UNLOCK(stcb);
39338c2654abSrjs 			return (1);
39348c2654abSrjs 		        break;
39358c2654abSrjs 		case SCTP_STATE_EMPTY:	/* should not happen */
39368c2654abSrjs 		case SCTP_STATE_INUSE:	/* should not happen */
39378c2654abSrjs 		case SCTP_STATE_SHUTDOWN_RECEIVED:  /* This is a peer error */
39388c2654abSrjs 		case SCTP_STATE_SHUTDOWN_ACK_SENT:
39398c2654abSrjs 		default:
39408c2654abSrjs #ifdef SCTP_DEBUG
39418c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
39428c2654abSrjs 				printf("Got data in invalid state %d.. dropping\n", stcb->asoc.state);
39438c2654abSrjs 			}
39448c2654abSrjs #endif
39458c2654abSrjs 			SCTP_TCB_UNLOCK(stcb);
39468c2654abSrjs 			return (1);
39478c2654abSrjs 			break;
39488c2654abSrjs 		case SCTP_STATE_OPEN:
39498c2654abSrjs 		case SCTP_STATE_SHUTDOWN_SENT:
39508c2654abSrjs 			break;
39518c2654abSrjs 		}
39528c2654abSrjs 		/* take care of ECN, part 1. */
39538c2654abSrjs 		if (stcb->asoc.ecn_allowed &&
39548c2654abSrjs 		    (ecn_bits & (SCTP_ECT0_BIT|SCTP_ECT1_BIT)) ) {
39558c2654abSrjs 			sctp_process_ecn_marked_a(stcb, net, ecn_bits);
39568c2654abSrjs 		}
39578c2654abSrjs 		/* plow through the data chunks while length > offset */
39588c2654abSrjs 		retval = sctp_process_data(mm, iphlen, &offset, length, sh,
39598c2654abSrjs 		    inp, stcb, net, &high_tsn);
39608c2654abSrjs 		if (retval == 2) {
39618c2654abSrjs 			/* The association aborted, NO UNLOCK needed
39628c2654abSrjs 			 * since the association is destroyed.
39638c2654abSrjs 			 */
39648c2654abSrjs 			return (0);
39658c2654abSrjs 		}
39668c2654abSrjs 
39678c2654abSrjs 		data_processed = 1;
39688c2654abSrjs 		if (retval == 0) {
39698c2654abSrjs 			/* take care of ecn part 2. */
39708c2654abSrjs 			if (stcb->asoc.ecn_allowed && (ecn_bits & (SCTP_ECT0_BIT|SCTP_ECT1_BIT)) ) {
39718c2654abSrjs 				sctp_process_ecn_marked_b(stcb, net, high_tsn, ecn_bits);
39728c2654abSrjs 
39738c2654abSrjs 			}
39748c2654abSrjs 		}
39758c2654abSrjs 
39768c2654abSrjs 		/*
39778c2654abSrjs 		 * Anything important needs to have been m_copy'ed in
39788c2654abSrjs 		 * process_data
39798c2654abSrjs 		 */
39808c2654abSrjs 	}
39818c2654abSrjs 	if ((data_processed == 0) && (fwd_tsn_seen)) {
39828c2654abSrjs 		int was_a_gap = 0;
39838c2654abSrjs 		if (compare_with_wrap(stcb->asoc.highest_tsn_inside_map,
39848c2654abSrjs 				      stcb->asoc.cumulative_tsn, MAX_TSN)) {
39858c2654abSrjs 			/* there was a gap before this data was processed */
39868c2654abSrjs 			was_a_gap = 1;
39878c2654abSrjs 		}
39888c2654abSrjs 		sctp_sack_check(stcb, 1, was_a_gap, &abort_flag);
39898c2654abSrjs 		if (abort_flag) {
39908c2654abSrjs 			/* Again, we aborted so NO UNLOCK needed */
39918c2654abSrjs 			return (0);
39928c2654abSrjs 		}
39938c2654abSrjs 	}
39948c2654abSrjs 	/* trigger send of any chunks in queue... */
39958c2654abSrjs #ifdef SCTP_AUDITING_ENABLED
39968c2654abSrjs 	sctp_audit_log(0xE0, 2);
39978c2654abSrjs 	sctp_auditing(1, inp, stcb, net);
39988c2654abSrjs #endif
39998c2654abSrjs #ifdef SCTP_DEBUG
40008c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
40018c2654abSrjs 		printf("Check for chunk output prw:%d tqe:%d tf=%d\n",
40028c2654abSrjs 		       stcb->asoc.peers_rwnd,
40038c2654abSrjs 		       TAILQ_EMPTY(&stcb->asoc.control_send_queue),
40048c2654abSrjs 		       stcb->asoc.total_flight);
40058c2654abSrjs 	}
40068c2654abSrjs #endif
40078c2654abSrjs 	if (stcb->asoc.peers_rwnd > 0 ||
40088c2654abSrjs 	    !TAILQ_EMPTY(&stcb->asoc.control_send_queue) ||
40098c2654abSrjs 	    (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)) {
40108c2654abSrjs #ifdef SCTP_DEBUG
40118c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
40128c2654abSrjs 			printf("Calling chunk OUTPUT\n");
40138c2654abSrjs 		}
40148c2654abSrjs #endif
40158c2654abSrjs 		sctp_chunk_output(inp, stcb, 3);
40168c2654abSrjs #ifdef SCTP_DEBUG
40178c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
40188c2654abSrjs 			printf("chunk OUTPUT returns\n");
40198c2654abSrjs 		}
40208c2654abSrjs #endif
40218c2654abSrjs 	}
40228c2654abSrjs 
40238c2654abSrjs #ifdef SCTP_AUDITING_ENABLED
40248c2654abSrjs 	sctp_audit_log(0xE0, 3);
40258c2654abSrjs 	sctp_auditing(2, inp, stcb, net);
40268c2654abSrjs #endif
40278c2654abSrjs 	SCTP_TCB_UNLOCK(stcb);
40288c2654abSrjs 	return (0);
40298c2654abSrjs }
40308c2654abSrjs 
40318c2654abSrjs #if defined(__OpenBSD__)
40328c2654abSrjs static void
sctp_saveopt(struct sctp_inpcb * inp,struct mbuf ** mp,struct ip * ip,struct mbuf * m)40338c2654abSrjs sctp_saveopt(struct sctp_inpcb *inp, struct mbuf **mp, struct ip *ip,
40348c2654abSrjs     struct mbuf *m)
40358c2654abSrjs {
40368c2654abSrjs 	if (inp->ip_inp.inp.inp_flags & INP_RECVDSTADDR) {
40378c2654abSrjs 		*mp = sbcreatecontrol((vaddr_t) &ip->ip_dst,
40388c2654abSrjs 		    sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
40398c2654abSrjs 		if (*mp)
40408c2654abSrjs 			mp = &(*mp)->m_next;
40418c2654abSrjs 	}
40428c2654abSrjs }
40438c2654abSrjs #endif
40448c2654abSrjs 
40458c2654abSrjs extern int sctp_no_csum_on_loopback;
40468c2654abSrjs 
40478c2654abSrjs void
sctp_input(struct mbuf * m,int off,int proto)404815652348Smaxv sctp_input(struct mbuf *m, int off, int proto)
40498c2654abSrjs {
40508c2654abSrjs 	int iphlen;
40518c2654abSrjs 	u_int8_t ecn_bits;
40528c2654abSrjs 	struct ip *ip;
40538c2654abSrjs 	struct sctphdr *sh;
40548c2654abSrjs 	struct sctp_inpcb *inp = NULL;
40558c2654abSrjs 	struct mbuf *opts = 0;
40568c2654abSrjs /*#ifdef INET6*/
40578c2654abSrjs /* Don't think this is needed */
40588c2654abSrjs /*	struct ip6_recvpktopts opts6;*/
40598c2654abSrjs /*#endif INET6 */
40608c2654abSrjs 
40618c2654abSrjs 	u_int32_t check, calc_check;
40628c2654abSrjs 	struct sctp_nets *net;
40638c2654abSrjs 	struct sctp_tcb *stcb = NULL;
40648c2654abSrjs 	struct sctp_chunkhdr *ch;
40658c2654abSrjs 	int refcount_up = 0;
40668c2654abSrjs 	int length, mlen, offset;
40678c2654abSrjs 
406815652348Smaxv 	iphlen = off;
40698c2654abSrjs 
40708c2654abSrjs 	net = NULL;
40718c2654abSrjs 	sctp_pegs[SCTP_INPKTS]++;
40728c2654abSrjs #ifdef SCTP_DEBUG
40738c2654abSrjs 	/*if (sctp_debug_on & SCTP_DEBUG_INPUT1) {*/
40748c2654abSrjs 		printf("V4 input gets a packet iphlen:%d pktlen:%d\n", iphlen, m->m_pkthdr.len);
40758c2654abSrjs 	/*}*/
40768c2654abSrjs #endif
40778c2654abSrjs /*#ifdef INET6*/
40788c2654abSrjs /* Don't think this is needed */
40798c2654abSrjs /*	bzero(&opts6, sizeof(opts6));*/
40808c2654abSrjs /*#endif INET6 */
40818c2654abSrjs 
40828c2654abSrjs 	/*
40838c2654abSrjs 	 * Strip IP options, we don't allow any in or out.
40848c2654abSrjs 	 */
40858c2654abSrjs 	if ((size_t)iphlen > sizeof(struct ip)) {
40868c2654abSrjs 		printf("sctp_input: got options\n");
40878c2654abSrjs #if 0				/* XXX */
40888c2654abSrjs 		ip_stripoptions(m, (struct mbuf *)0);
40898c2654abSrjs #endif
40908c2654abSrjs 		iphlen = sizeof(struct ip);
40918c2654abSrjs 	}
40928c2654abSrjs 
40938c2654abSrjs 	/*
40948c2654abSrjs 	 * Get IP, SCTP, and first chunk header together in first mbuf.
40958c2654abSrjs 	 */
40968c2654abSrjs 	ip = mtod(m, struct ip *);
40978c2654abSrjs 	offset = iphlen + sizeof(*sh) + sizeof(*ch);
40988c2654abSrjs 	if (m->m_len < offset) {
40998c2654abSrjs 		if ((m = m_pullup(m, offset)) == 0) {
41008c2654abSrjs 			sctp_pegs[SCTP_HDR_DROPS]++;
41018c2654abSrjs 			return;
41028c2654abSrjs 		}
41038c2654abSrjs 		ip = mtod(m, struct ip *);
41048c2654abSrjs 	}
41058c2654abSrjs 	sh = (struct sctphdr *)((vaddr_t)ip + iphlen);
41068c2654abSrjs 	ch = (struct sctp_chunkhdr *)((vaddr_t)sh + sizeof(*sh));
41078c2654abSrjs 
41088c2654abSrjs 	/* SCTP does not allow broadcasts or multicasts */
41098c2654abSrjs 	if (IN_MULTICAST(ip->ip_dst.s_addr))
41108c2654abSrjs 	{
41118c2654abSrjs 		sctp_pegs[SCTP_IN_MCAST]++;
41128c2654abSrjs 		goto bad;
41138c2654abSrjs 	}
4114fe6d4275Sozaki-r 	if (in_broadcast(ip->ip_dst, m_get_rcvif_NOMPSAFE(m))) {
41158c2654abSrjs 		sctp_pegs[SCTP_IN_MCAST]++;
41168c2654abSrjs 		goto bad;
41178c2654abSrjs 	}
41188c2654abSrjs 
41198c2654abSrjs 	/* destination port of 0 is illegal, based on RFC2960. */
41208c2654abSrjs 	if (sh->dest_port == 0) {
41218c2654abSrjs 	        sctp_pegs[SCTP_HDR_DROPS]++;
41228c2654abSrjs 		goto bad;
41238c2654abSrjs 	}
41248c2654abSrjs 
41258c2654abSrjs 	/* validate SCTP checksum */
41268c2654abSrjs 	if ((sctp_no_csum_on_loopback == 0) ||
4127fe6d4275Sozaki-r 	    (m_get_rcvif_NOMPSAFE(m) == NULL) ||
4128fe6d4275Sozaki-r 	    (m_get_rcvif_NOMPSAFE(m)->if_type != IFT_LOOP)) {
41298c2654abSrjs 		/* we do NOT validate things from the loopback if the
41308c2654abSrjs 		 * sysctl is set to 1.
41318c2654abSrjs 		 */
41328c2654abSrjs 		check = sh->checksum;	/* save incoming checksum */
41338c2654abSrjs 		if ((check == 0) && (sctp_no_csum_on_loopback)) {
41348c2654abSrjs 			/* special hook for where we got a local address
41358c2654abSrjs 			 * somehow routed across a non IFT_LOOP type interface
41368c2654abSrjs 			 */
41378c2654abSrjs 			if (ip->ip_src.s_addr == ip->ip_dst.s_addr)
41388c2654abSrjs 				goto sctp_skip_csum_4;
41398c2654abSrjs 		}
41408c2654abSrjs 		sh->checksum = 0;		/* prepare for calc */
41418c2654abSrjs 		calc_check = sctp_calculate_sum(m, &mlen, iphlen);
41428c2654abSrjs 		if (calc_check != check) {
41438c2654abSrjs #ifdef SCTP_DEBUG
41448c2654abSrjs 			if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
41458c2654abSrjs 				printf("Bad CSUM on SCTP packet calc_check:%x check:%x  m:%p mlen:%d iphlen:%d\n",
41468c2654abSrjs 				       calc_check, check, m, mlen, iphlen);
41478c2654abSrjs 			}
41488c2654abSrjs #endif
41498c2654abSrjs 
41508c2654abSrjs 			stcb = sctp_findassociation_addr(m, iphlen,
41518c2654abSrjs 							 offset - sizeof(*ch),
41528c2654abSrjs 							 sh, ch, &inp, &net);
41538c2654abSrjs 			if ((inp) && (stcb)) {
41548c2654abSrjs 				sctp_send_packet_dropped(stcb, net, m, iphlen,
41558c2654abSrjs 							 1);
41568c2654abSrjs 				sctp_chunk_output(inp, stcb, 2);
41578c2654abSrjs 			} else if ((inp != NULL) && (stcb == NULL)) {
41588c2654abSrjs 				refcount_up = 1;
41598c2654abSrjs 			}
41608c2654abSrjs 			sctp_pegs[SCTP_BAD_CSUM]++;
41618c2654abSrjs 			goto bad;
41628c2654abSrjs 		}
41638c2654abSrjs 		sh->checksum = calc_check;
41648c2654abSrjs 	} else {
41658c2654abSrjs 	sctp_skip_csum_4:
41668c2654abSrjs 		mlen = m->m_pkthdr.len;
41678c2654abSrjs 	}
41688c2654abSrjs 	/* validate mbuf chain length with IP payload length */
41698c2654abSrjs #if defined(__NetBSD__) || defined(__OpenBSD__)
41708c2654abSrjs 	/* Open BSD gives us the len in network order, fix it */
41718c2654abSrjs 	NTOHS(ip->ip_len);
41728c2654abSrjs #endif
41738c2654abSrjs 	if (mlen < (ip->ip_len - iphlen)) {
41748c2654abSrjs 	        sctp_pegs[SCTP_HDR_DROPS]++;
41758c2654abSrjs 		goto bad;
41768c2654abSrjs 	}
41778c2654abSrjs 
41788c2654abSrjs 	/*
41798c2654abSrjs 	 * Locate pcb and tcb for datagram
41808c2654abSrjs 	 * sctp_findassociation_addr() wants IP/SCTP/first chunk header...
41818c2654abSrjs 	 */
41828c2654abSrjs #ifdef SCTP_DEBUG
41838c2654abSrjs 	if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
41848c2654abSrjs 		printf("V4 find association\n");
41858c2654abSrjs 	}
41868c2654abSrjs #endif
41878c2654abSrjs 
41888c2654abSrjs 	stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
41898c2654abSrjs 	    sh, ch, &inp, &net);
41908c2654abSrjs 	/* inp's ref-count increased && stcb locked */
41918c2654abSrjs 	if (inp == NULL) {
41928c2654abSrjs 		struct sctp_init_chunk *init_chk, chunk_buf;
41938c2654abSrjs 
41948c2654abSrjs 		sctp_pegs[SCTP_NOPORTS]++;
41958c2654abSrjs #ifdef ICMP_BANDLIM
41968c2654abSrjs 		/*
41978c2654abSrjs 		 * we use the bandwidth limiting to protect against
41988c2654abSrjs 		 * sending too many ABORTS all at once. In this case
41998c2654abSrjs 		 * these count the same as an ICMP message.
42008c2654abSrjs 		 */
42018c2654abSrjs 		if (badport_bandlim(0) < 0)
42028c2654abSrjs 			goto bad;
42038c2654abSrjs #endif /* ICMP_BANDLIM */
42048c2654abSrjs #ifdef SCTP_DEBUG
42058c2654abSrjs 		if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
42068c2654abSrjs 			printf("Sending a ABORT from packet entry!\n");
42078c2654abSrjs 		}
42088c2654abSrjs #endif
42098c2654abSrjs 		if (ch->chunk_type == SCTP_INITIATION) {
42108c2654abSrjs 			/* we do a trick here to get the INIT tag,
42118c2654abSrjs 			 * dig in and get the tag from the INIT and
42128c2654abSrjs 			 * put it in the common header.
42138c2654abSrjs 			 */
42148c2654abSrjs 			init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
42158c2654abSrjs 			    iphlen + sizeof(*sh), sizeof(*init_chk),
42168c2654abSrjs 			    (u_int8_t *)&chunk_buf);
42178c2654abSrjs 			if (init_chk != NULL)
42188c2654abSrjs 				sh->v_tag = init_chk->init.initiate_tag;
42198c2654abSrjs 		}
42208c2654abSrjs 		sctp_send_abort(m, iphlen, sh, 0, NULL);
42218c2654abSrjs 		goto bad;
42228c2654abSrjs 	} else if (stcb == NULL) {
42238c2654abSrjs 		refcount_up = 1;
42248c2654abSrjs 	}
42258c2654abSrjs #ifdef IPSEC
42268c2654abSrjs 	/*
42278c2654abSrjs 	 * I very much doubt any of the IPSEC stuff will work but I have
42288c2654abSrjs 	 * no idea, so I will leave it in place.
42298c2654abSrjs 	 */
4230b39a0dd1Smaxv 	if (ipsec_used && ipsec_in_reject(m, (struct inpcb *)inp)) {
4231505ea976Srjs #if 0
42328c2654abSrjs 		ipsecstat.in_polvio++;
4233505ea976Srjs #endif
42348c2654abSrjs 		sctp_pegs[SCTP_HDR_DROPS]++;
42358c2654abSrjs 		goto bad;
42368c2654abSrjs 	}
42378c2654abSrjs #endif /* IPSEC */
42388c2654abSrjs 
42398c2654abSrjs 	/*
42408c2654abSrjs 	 * Construct sockaddr format source address.
42418c2654abSrjs 	 * Stuff source address and datagram in user buffer.
42428c2654abSrjs 	 */
42438c2654abSrjs 	if ((inp->ip_inp.inp.inp_flags & INP_CONTROLOPTS)
42448c2654abSrjs 	    || (inp->sctp_socket->so_options & SO_TIMESTAMP)
42458c2654abSrjs 		) {
42468c2654abSrjs 		ip_savecontrol((struct inpcb *)inp, &opts, ip, m);
42478c2654abSrjs 	}
42488c2654abSrjs 
42498c2654abSrjs 	/*
42508c2654abSrjs 	 * common chunk processing
42518c2654abSrjs 	 */
42528c2654abSrjs 	length = ip->ip_len - (ip->ip_hl << 2) + iphlen;
42538c2654abSrjs 	offset -= sizeof(struct sctp_chunkhdr);
42548c2654abSrjs 
42558c2654abSrjs 	ecn_bits = ip->ip_tos;
42568c2654abSrjs 	sctp_common_input_processing(&m, iphlen, offset, length, sh, ch,
42578c2654abSrjs 	    inp, stcb, net, ecn_bits);
42588c2654abSrjs 	/* inp's ref-count reduced && stcb unlocked */
42598c2654abSrjs 	sctp_m_freem(m);
42608c2654abSrjs 	sctp_m_freem(opts);
42618c2654abSrjs 
42628c2654abSrjs 	if ((inp) && (refcount_up)) {
42638c2654abSrjs 		/* reduce ref-count */
42648c2654abSrjs 		SCTP_INP_WLOCK(inp);
42658c2654abSrjs 		SCTP_INP_DECR_REF(inp);
42668c2654abSrjs 		SCTP_INP_WUNLOCK(inp);
42678c2654abSrjs 	}
42688c2654abSrjs 
42698c2654abSrjs 	return;
42708c2654abSrjs bad:
42718c2654abSrjs 	if (stcb) {
42728c2654abSrjs 		SCTP_TCB_UNLOCK(stcb);
42738c2654abSrjs 	}
42748c2654abSrjs 
42758c2654abSrjs 	if ((inp) && (refcount_up)) {
42768c2654abSrjs 		/* reduce ref-count */
42778c2654abSrjs 		SCTP_INP_WLOCK(inp);
42788c2654abSrjs 		SCTP_INP_DECR_REF(inp);
42798c2654abSrjs 		SCTP_INP_WUNLOCK(inp);
42808c2654abSrjs 	}
42818c2654abSrjs 
42828c2654abSrjs 	sctp_m_freem(m);
42838c2654abSrjs 	sctp_m_freem(opts);
42848c2654abSrjs 	return;
42858c2654abSrjs }
4286