18c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
28c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
3ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
58c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
68c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Redistribution and use in source and binary forms, with or without
78c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * modification, are permitted provided that the following conditions are met:
88c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
98c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * a) Redistributions of source code must retain the above copyright notice,
100ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    this list of conditions and the following disclaimer.
118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * b) Redistributions in binary form must reproduce the above copyright
138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    notice, this list of conditions and the following disclaimer in
140ac02f34d6041cd0018437596a5a9a94685e6919tuexen *    the documentation and/or other materials provided with the distribution.
158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * c) Neither the name of Cisco Systems, Inc. nor the names of its
178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    contributors may be used to endorse or promote products derived
188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *    from this software without specific prior written permission.
198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * THE POSSIBILITY OF SUCH DAMAGE.
318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef __FreeBSD__
348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <sys/cdefs.h>
351b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 271228 2014-09-07 17:07:19Z tuexen $");
368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
37ecc6b8c25a7e8d9d2b78889e88224354a1cc3160tuexen
388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_os.h>
398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_var.h>
408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_sysctl.h>
418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_pcb.h>
428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_header.h>
438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctputil.h>
448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_output.h>
458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_asconf.h>
468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#include <netinet/sctp_timer.h>
478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * debug flags:
508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SCTP_DEBUG_ASCONF1: protocol info, general info and errors
518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * SCTP_DEBUG_ASCONF2: detailed info
528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__APPLE__)
558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#define APPLE_FILE_NO 1
568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
59e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen * RFC 5061
608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * An ASCONF parameter queue exists per asoc which holds the pending address
628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * operations.  Lists are updated upon receipt of ASCONF-ACK.
638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * A restricted_addrs list exists per assoc to hold local addresses that are
658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * not (yet) usable by the assoc as a source address.  These addresses are
668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * either pending an ASCONF operation (and exist on the ASCONF parameter
678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queue), or they are permanently restricted (the peer has returned an
688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ERROR indication to an ASCONF(ADD), or the peer does not support ASCONF).
698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen *
708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Deleted addresses are always immediately removed from the lists as they will
718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (shortly) no longer exist in the kernel.  We send ASCONFs as a courtesy,
728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * only if allowed.
738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ASCONF parameter processing.
778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * response_required: set if a reply is required (eg. SUCCESS_REPORT).
788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns a mbuf to an "error" response parameter or NULL/"success" if ok.
798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * FIX: allocating this many mbufs on the fly is pretty inefficient...
808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf *
828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_success_response(uint32_t id)
838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_reply = NULL;
858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_paramhdr *aph;
868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m_reply = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_paramhdr),
8868beeca578347438d9c434680197647ed551935ft					0, M_NOWAIT, 1, MT_DATA);
898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_reply == NULL) {
908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"asconf_success_response: couldn't get mbuf!\n");
92b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (NULL);
938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aph->correlation_id = id;
968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aph->ph.param_type = htons(SCTP_SUCCESS_REPORT);
978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr);
988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aph->ph.param_length = htons(aph->ph.param_length);
1008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
101b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (m_reply);
1028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf *
1058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t *error_tlv,
1068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			   uint16_t tlv_length)
1078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_reply = NULL;
1098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_paramhdr *aph;
1108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_error_cause *error;
1118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t *tlv;
1128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m_reply = sctp_get_mbuf_for_msg((sizeof(struct sctp_asconf_paramhdr) +
1148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 tlv_length +
1158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 sizeof(struct sctp_error_cause)),
11668beeca578347438d9c434680197647ed551935ft					0, M_NOWAIT, 1, MT_DATA);
1178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_reply == NULL) {
1188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
1198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"asconf_error_response: couldn't get mbuf!\n");
120b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (NULL);
1218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
1238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error = (struct sctp_error_cause *)(aph + 1);
1248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aph->correlation_id = id;
1268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aph->ph.param_type = htons(SCTP_ERROR_CAUSE_IND);
1278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error->code = htons(cause);
1288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error->length = tlv_length + sizeof(struct sctp_error_cause);
1298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aph->ph.param_length = error->length +
1308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sizeof(struct sctp_asconf_paramhdr);
1318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (aph->ph.param_length > MLEN) {
1338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
1348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"asconf_error_response: tlv_length (%xh) too big\n",
1358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			tlv_length);
1368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_reply);	/* discard */
137b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (NULL);
1388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (error_tlv != NULL) {
1408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		tlv = (uint8_t *) (error + 1);
1418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(tlv, error_tlv, tlv_length);
1428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
1438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
1448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error->length = htons(error->length);
1458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aph->ph.param_length = htons(aph->ph.param_length);
1468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
147b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (m_reply);
1488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
1498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf *
151e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_process_asconf_add_ip(struct sockaddr *src, struct sctp_asconf_paramhdr *aph,
1528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen                           struct sctp_tcb *stcb, int send_hb, int response_required)
1538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
1548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
1558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_reply = NULL;
156bfb1bf7e665a02b48026482bf33d05c83dfad73bt	union sctp_sockstore store;
1578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_paramhdr *ph;
158facb9a509f7ae3621b7d2771319811985d9c46b7t	uint16_t param_type, aparam_length;
159facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6)
160facb9a509f7ae3621b7d2771319811985d9c46b7t	uint16_t param_length;
161facb9a509f7ae3621b7d2771319811985d9c46b7t#endif
1628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *sa;
1638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int zero_address = 0;
1648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int bad_address = 0;
1658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
1668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin;
1678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ipv4addr_param *v4addr;
1688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
1708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in6 *sin6;
1718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ipv6addr_param *v6addr;
1728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aparam_length = ntohs(aph->ph.param_length);
1758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ph = (struct sctp_paramhdr *)(aph + 1);
1768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	param_type = ntohs(ph->param_type);
177facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6)
1788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	param_length = ntohs(ph->param_length);
179facb9a509f7ae3621b7d2771319811985d9c46b7t#endif
180bfb1bf7e665a02b48026482bf33d05c83dfad73bt	sa = &store.sa;
1818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (param_type) {
1828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
1838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_IPV4_ADDRESS:
1848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (param_length != sizeof(struct sctp_ipv4addr_param)) {
1858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid param size */
186b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			return (NULL);
1878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
1888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		v4addr = (struct sctp_ipv4addr_param *)ph;
189bfb1bf7e665a02b48026482bf33d05c83dfad73bt		sin = &store.sin;
1908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero(sin, sizeof(*sin));
1918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_family = AF_INET;
1927b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN
1938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_len = sizeof(struct sockaddr_in);
1948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
1958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_port = stcb->rport;
1968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_addr.s_addr = v4addr->addr;
1978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((sin->sin_addr.s_addr == INADDR_BROADCAST) ||
1988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
1998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bad_address = 1;
2008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sin->sin_addr.s_addr == INADDR_ANY)
2028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			zero_address = 1;
2038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
2048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
2058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
2068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
2078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
2088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_IPV6_ADDRESS:
2098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (param_length != sizeof(struct sctp_ipv6addr_param)) {
2108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid param size */
211b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			return (NULL);
2128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		v6addr = (struct sctp_ipv6addr_param *)ph;
214bfb1bf7e665a02b48026482bf33d05c83dfad73bt		sin6 = &store.sin6;
2158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero(sin6, sizeof(*sin6));
2168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_family = AF_INET6;
2177b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
2188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_len = sizeof(struct sockaddr_in6);
2198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
2208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_port = stcb->rport;
2218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
2228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct in6_addr));
2238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
2248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bad_address = 1;
2258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
2278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			zero_address = 1;
2288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
2298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
2308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
2318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
2328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
2338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_reply = sctp_asconf_error_response(aph->correlation_id,
2348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
2358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    aparam_length);
236b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (m_reply);
2378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}			/* end switch */
2388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* if 0.0.0.0/::0, add the source address instead */
2408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
241e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen		sa = src;
2428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
2438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        "process_asconf_add_ip: using source addr ");
244e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src);
2458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* add the address */
2478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (bad_address) {
2488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_reply = sctp_asconf_error_response(aph->correlation_id,
2498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph,
250000a5bac556b28e74e4e98c540f66b1743e9312dtuexen		    aparam_length);
2518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (sctp_add_remote_addr(stcb, sa, &net, SCTP_DONOT_SETSCOPE,
2528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                         SCTP_ADDR_DYNAMIC_ADDED) != 0) {
2538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
2548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"process_asconf_add_ip: error adding address\n");
2558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_reply = sctp_asconf_error_response(aph->correlation_id,
2568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_CAUSE_RESOURCE_SHORTAGE, (uint8_t *) aph,
2578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    aparam_length);
2588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
2598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* notify upper layer */
2608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
2618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (response_required) {
2628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m_reply =
2638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    sctp_asconf_success_response(aph->correlation_id);
2648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, stcb->sctp_ep, stcb, net);
2668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
2678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		                 stcb, net);
2688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (send_hb) {
2698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_send_hb(stcb, net, SCTP_SO_NOT_LOCKED);
2708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
2718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
272b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (m_reply);
2738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
2748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
2768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src)
2778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
2788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *src_net, *net;
2798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* make sure the source address exists as a destination net */
2818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	src_net = sctp_findnet(stcb, src);
2828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (src_net == NULL) {
2838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* not found */
284b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (-1);
2858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* delete all destination addresses except the source */
2888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net != src_net) {
2908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* delete this address */
2918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_remove_net(stcb, net);
2928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1,
2938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				"asconf_del_remote_addrs_except: deleting ");
2948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1,
2958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     (struct sockaddr *)&net->ro._l_addr);
2968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* notify upper layer */
2978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0,
2988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (struct sockaddr *)&net->ro._l_addr, SCTP_SO_NOT_LOCKED);
2998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
301b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (0);
3028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf *
305e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_process_asconf_delete_ip(struct sockaddr *src,
306e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen                              struct sctp_asconf_paramhdr *aph,
3078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			      struct sctp_tcb *stcb, int response_required)
3088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
3098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_reply = NULL;
310bfb1bf7e665a02b48026482bf33d05c83dfad73bt	union sctp_sockstore store;
3118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_paramhdr *ph;
312facb9a509f7ae3621b7d2771319811985d9c46b7t	uint16_t param_type, aparam_length;
313facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6)
314facb9a509f7ae3621b7d2771319811985d9c46b7t	uint16_t param_length;
315facb9a509f7ae3621b7d2771319811985d9c46b7t#endif
3168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *sa;
3178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int zero_address = 0;
3188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int result;
3198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
3208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin;
3218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ipv4addr_param *v4addr;
3228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
3248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in6 *sin6;
3258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ipv6addr_param *v6addr;
3268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aparam_length = ntohs(aph->ph.param_length);
3298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ph = (struct sctp_paramhdr *)(aph + 1);
3308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	param_type = ntohs(ph->param_type);
331facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6)
3328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	param_length = ntohs(ph->param_length);
333facb9a509f7ae3621b7d2771319811985d9c46b7t#endif
334bfb1bf7e665a02b48026482bf33d05c83dfad73bt	sa = &store.sa;
3358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (param_type) {
3368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
3378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_IPV4_ADDRESS:
3388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (param_length != sizeof(struct sctp_ipv4addr_param)) {
3398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid param size */
340b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			return (NULL);
3418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		v4addr = (struct sctp_ipv4addr_param *)ph;
343bfb1bf7e665a02b48026482bf33d05c83dfad73bt		sin = &store.sin;
3448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero(sin, sizeof(*sin));
3458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_family = AF_INET;
3467b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN
3478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_len = sizeof(struct sockaddr_in);
3488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_port = stcb->rport;
3508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_addr.s_addr = v4addr->addr;
3518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sin->sin_addr.s_addr == INADDR_ANY)
3528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			zero_address = 1;
3538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
3548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"process_asconf_delete_ip: deleting ");
3558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
3568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
3578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
3598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_IPV6_ADDRESS:
3608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (param_length != sizeof(struct sctp_ipv6addr_param)) {
3618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid param size */
362b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			return (NULL);
3638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
3648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		v6addr = (struct sctp_ipv6addr_param *)ph;
365bfb1bf7e665a02b48026482bf33d05c83dfad73bt		sin6 = &store.sin6;
3668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero(sin6, sizeof(*sin6));
3678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_family = AF_INET6;
3687b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
3698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_len = sizeof(struct sockaddr_in6);
3708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_port = stcb->rport;
3728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(&sin6->sin6_addr, v6addr->addr,
3738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct in6_addr));
3748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
3758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			zero_address = 1;
3768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
3778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"process_asconf_delete_ip: deleting ");
3788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
3798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
3808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
3818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
3828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_reply = sctp_asconf_error_response(aph->correlation_id,
3838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
3848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    aparam_length);
385b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (m_reply);
3868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* make sure the source address is not being deleted */
389e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen	if (sctp_cmpaddr(sa, src)) {
3908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* trying to delete the source address! */
3918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete source addr\n");
3928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_reply = sctp_asconf_error_response(aph->correlation_id,
3938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_CAUSE_DELETING_SRC_ADDR, (uint8_t *) aph,
3948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    aparam_length);
395b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (m_reply);
3968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
3978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* if deleting 0.0.0.0/::0, delete all addresses except src addr */
3998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
400e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen		result = sctp_asconf_del_remote_addrs_except(stcb, src);
4018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (result) {
4038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* src address did not exist? */
4048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: src addr does not exist?\n");
4058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* what error to reply with?? */
4068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m_reply =
4078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    sctp_asconf_error_response(aph->correlation_id,
4088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_CAUSE_REQUEST_REFUSED, (uint8_t *) aph,
4098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    aparam_length);
4108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (response_required) {
4118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m_reply =
4128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    sctp_asconf_success_response(aph->correlation_id);
4138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
414b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (m_reply);
4158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
4168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* delete the address */
4188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	result = sctp_del_remote_addr(stcb, sa);
4198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
4208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * note if result == -2, the address doesn't exist in the asoc but
4218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * since it's being deleted anyways, we just ack the delete -- but
4228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * this probably means something has already gone awry
4238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
4248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (result == -1) {
4258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* only one address in the asoc */
4268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete last IP addr!\n");
4278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_reply = sctp_asconf_error_response(aph->correlation_id,
4288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_CAUSE_DELETING_LAST_ADDR, (uint8_t *) aph,
4298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    aparam_length);
4308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
4318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (response_required) {
432e2828360ea9cf8951730d46f5c14626c9425cb30t			m_reply = sctp_asconf_success_response(aph->correlation_id);
4338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* notify upper layer */
4358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
4368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
437b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (m_reply);
4388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
4398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct mbuf *
441e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexensctp_process_asconf_set_primary(struct sockaddr *src,
4428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_asconf_paramhdr *aph,
4438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				struct sctp_tcb *stcb, int response_required)
4448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
4458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_reply = NULL;
446bfb1bf7e665a02b48026482bf33d05c83dfad73bt	union sctp_sockstore store;
4478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_paramhdr *ph;
448facb9a509f7ae3621b7d2771319811985d9c46b7t	uint16_t param_type, aparam_length;
449facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6)
450facb9a509f7ae3621b7d2771319811985d9c46b7t	uint16_t param_length;
451facb9a509f7ae3621b7d2771319811985d9c46b7t#endif
4528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr *sa;
4538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int zero_address = 0;
4548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
4558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin;
4568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ipv4addr_param *v4addr;
4578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
4598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in6 *sin6;
4608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ipv6addr_param *v6addr;
4618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
4638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aparam_length = ntohs(aph->ph.param_length);
4648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ph = (struct sctp_paramhdr *)(aph + 1);
4658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	param_type = ntohs(ph->param_type);
466facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6)
4678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	param_length = ntohs(ph->param_length);
468facb9a509f7ae3621b7d2771319811985d9c46b7t#endif
469bfb1bf7e665a02b48026482bf33d05c83dfad73bt	sa = &store.sa;
4708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (param_type) {
4718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
4728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_IPV4_ADDRESS:
4738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (param_length != sizeof(struct sctp_ipv4addr_param)) {
4748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid param size */
475b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			return (NULL);
4768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		v4addr = (struct sctp_ipv4addr_param *)ph;
478bfb1bf7e665a02b48026482bf33d05c83dfad73bt		sin = &store.sin;
4798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero(sin, sizeof(*sin));
4808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_family = AF_INET;
4817b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN_LEN
4828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_len = sizeof(struct sockaddr_in);
4838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin->sin_addr.s_addr = v4addr->addr;
4858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sin->sin_addr.s_addr == INADDR_ANY)
4868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			zero_address = 1;
4878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: ");
4888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
4898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
4908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
4918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
4928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_IPV6_ADDRESS:
4938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (param_length != sizeof(struct sctp_ipv6addr_param)) {
4948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid param size */
495b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			return (NULL);
4968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
4978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		v6addr = (struct sctp_ipv6addr_param *)ph;
498bfb1bf7e665a02b48026482bf33d05c83dfad73bt		sin6 = &store.sin6;
4998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		bzero(sin6, sizeof(*sin6));
5008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_family = AF_INET6;
5017b0ab5c1c85787647428afafeff9491e9b6a60c7t#ifdef HAVE_SIN6_LEN
5028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6->sin6_len = sizeof(struct sockaddr_in6);
5038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
5048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
5058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct in6_addr));
5068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
5078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			zero_address = 1;
5088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: ");
5098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
5108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
5118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
5128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
5138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_reply = sctp_asconf_error_response(aph->correlation_id,
5148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
5158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    aparam_length);
516b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (m_reply);
5178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* if 0.0.0.0/::0, use the source address instead */
5208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
521e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen		sa = src;
5228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
5238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"process_asconf_set_primary: using source addr ");
524e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src);
5258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* set the primary address */
5278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_set_primary_addr(stcb, sa, NULL) == 0) {
5288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
5298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"process_asconf_set_primary: primary address set\n");
5308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* notify upper layer */
5318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
5328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb->asoc.primary_destination->dest_state & SCTP_ADDR_REACHABLE) &&
5338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (!(stcb->asoc.primary_destination->dest_state & SCTP_ADDR_PF)) &&
5348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (stcb->asoc.alternate)) {
5358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_remote_addr(stcb->asoc.alternate);
5368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.alternate = NULL;
5378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (response_required) {
5398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m_reply = sctp_asconf_success_response(aph->correlation_id);
5408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Mobility adaptation.
5428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   Ideally, when the reception of SET PRIMARY with DELETE IP
5438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   ADDRESS of the previous primary destination, unacknowledged
5448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   DATA are retransmitted immediately to the new primary
5458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   destination for seamless handover.
5468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   If the destination is UNCONFIRMED and marked to REQ_PRIM,
5478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   The retransmission occur when reception of the
5488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   HEARTBEAT-ACK.  (See sctp_handle_heartbeat_ack in
5498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   sctp_input.c)
5508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   Also, when change of the primary destination, it is better
5518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   that all subsequent new DATA containing already queued DATA
5528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   are transmitted to the new primary destination. (by micchie)
5538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
5548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
555e2828360ea9cf8951730d46f5c14626c9425cb30t		                                 SCTP_MOBILITY_BASE) ||
5568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sctp_is_mobility_feature_on(stcb->sctp_ep,
557e2828360ea9cf8951730d46f5c14626c9425cb30t		                                SCTP_MOBILITY_FASTHANDOFF)) &&
5588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sctp_is_mobility_feature_on(stcb->sctp_ep,
559e2828360ea9cf8951730d46f5c14626c9425cb30t		                                SCTP_MOBILITY_PRIM_DELETED) &&
5608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (stcb->asoc.primary_destination->dest_state &
5618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     SCTP_ADDR_UNCONFIRMED) == 0) {
5628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER+SCTP_LOC_7);
5648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
5658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_MOBILITY_FASTHANDOFF)) {
5668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_assoc_immediate_retrans(stcb,
5678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.primary_destination);
5688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
5708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					SCTP_MOBILITY_BASE)) {
5718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_move_chunks_from_net(stcb,
5728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.deleted_primary);
5738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
5748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_delete_prim_timer(stcb->sctp_ep, stcb,
5758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						stcb->asoc.deleted_primary);
5768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
5778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
5788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* couldn't set the requested primary address! */
5798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
5808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"process_asconf_set_primary: set primary failed!\n");
5818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* must have been an invalid address, so report */
5828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_reply = sctp_asconf_error_response(aph->correlation_id,
5838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
5848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    aparam_length);
5858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
5868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
587b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (m_reply);
5888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
5898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
5908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
5918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * handles an ASCONF chunk.
5928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * if all parameters are processed ok, send a plain (empty) ASCONF-ACK
5938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
5948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
5958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_asconf(struct mbuf *m, unsigned int offset,
596e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen                   struct sockaddr *src,
5978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   struct sctp_asconf_chunk *cp, struct sctp_tcb *stcb,
5988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   int first)
5998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
6008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
6018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t serial_num;
6028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *n, *m_ack, *m_result, *m_tail;
6038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_ack_chunk *ack_cp;
6048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_paramhdr *aph, *ack_aph;
6058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ipv6addr_param *p_addr;
6068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	unsigned int asconf_limit, cnt;
6078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error = 0;		/* did an error occur? */
6088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* asconf param buffer */
6108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
6118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_ack *ack, *ack_next;
6128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* verify minimum length */
6148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) {
6158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
6168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"handle_asconf: chunk too small = %xh\n",
6178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ntohs(cp->ch.chunk_length));
6188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
6198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
6218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	serial_num = ntohl(cp->serial_number);
6228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_TSN_GE(asoc->asconf_seq_in, serial_num)) {
6248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* got a duplicate ASCONF */
6258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
6268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"handle_asconf: got duplicate serial number = %xh\n",
6278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			serial_num);
6288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
6298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (serial_num != (asoc->asconf_seq_in + 1)) {
6308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: incorrect serial number = %xh (expected next = %xh)\n",
6318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			serial_num, asoc->asconf_seq_in + 1);
6328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
6338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* it's the expected "next" sequence number, so process it */
6368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->asconf_seq_in = serial_num;	/* update sequence */
6378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* get length of all the param's in the ASCONF */
6388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asconf_limit = offset + ntohs(cp->ch.chunk_length);
6398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_ASCONF1,
6408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		"handle_asconf: asconf_limit=%u, sequence=%xh\n",
6418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asconf_limit, serial_num);
6428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (first) {
6448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* delete old cache */
6458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,"handle_asconf: Now processing first ASCONF. Try to delete old cache\n");
6468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH_SAFE(ack, &asoc->asconf_ack_sent, next, ack_next) {
6488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (ack->serial_number == serial_num)
6498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
6508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1,"handle_asconf: delete old(%u) < first(%u)\n",
6518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    ack->serial_number, serial_num);
6528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&asoc->asconf_ack_sent, ack, next);
6538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (ack->data != NULL) {
6548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_m_freem(ack->data);
6558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
6568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), ack);
6578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
6588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0,
66168beeca578347438d9c434680197647ed551935ft				      M_NOWAIT, 1, MT_DATA);
6628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_ack == NULL) {
6638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
6648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"handle_asconf: couldn't get mbuf!\n");
6658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
6668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	m_tail = m_ack;		/* current reply chain's tail */
6688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* fill in ASCONF-ACK header */
6708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack_cp = mtod(m_ack, struct sctp_asconf_ack_chunk *);
6718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack_cp->ch.chunk_type = SCTP_ASCONF_ACK;
6728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack_cp->ch.chunk_flags = 0;
6738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack_cp->serial_number = htonl(serial_num);
6748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */
6758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_ack) = sizeof(struct sctp_asconf_ack_chunk);
6768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk);
6778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* skip the lookup address parameter */
6798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	offset += sizeof(struct sctp_asconf_chunk);
6808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *)&aparam_buf);
6818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (p_addr == NULL) {
6828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
6838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"handle_asconf: couldn't get lookup addr!\n");
6848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* respond with a missing/invalid mandatory parameter error */
6858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
6868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* param_length is already validated in process_control... */
6888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	offset += ntohs(p_addr->ph.param_length);	/* skip lookup addr */
6898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
6908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* get pointer to first asconf param in ASCONF-ACK */
691b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, caddr_t) + sizeof(struct sctp_asconf_ack_chunk));
6928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ack_aph == NULL) {
6938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "Gak in asconf2\n");
6948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
6958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
6968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* get pointer to first asconf param in ASCONF */
6978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *)&aparam_buf);
6988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (aph == NULL) {
6998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "Empty ASCONF received?\n");
7008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		goto send_reply;
7018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
7028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* process through all parameters */
7038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	cnt = 0;
7048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (aph != NULL) {
7058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		unsigned int param_length, param_type;
7068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		param_type = ntohs(aph->ph.param_type);
7088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		param_length = ntohs(aph->ph.param_length);
7098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (offset + param_length > asconf_limit) {
7108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* parameter goes beyond end of chunk! */
7118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(m_ack);
7128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
7138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		m_result = NULL;
7158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (param_length > sizeof(aparam_buf)) {
7178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) larger than buffer size!\n", param_length);
7188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(m_ack);
7198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
7208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (param_length <= sizeof(struct sctp_paramhdr)) {
7228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) too short\n", param_length);
7238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(m_ack);
7248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* get the entire parameter */
7268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
7278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aph == NULL) {
7288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: couldn't get entire param\n");
7298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_m_freem(m_ack);
7308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
7318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (param_type) {
7338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ADD_IP_ADDRESS:
734e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen			m_result = sctp_process_asconf_add_ip(src, aph, stcb,
7358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    (cnt < SCTP_BASE_SYSCTL(sctp_hb_maxburst)), error);
7368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cnt++;
7378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
7388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_DEL_IP_ADDRESS:
739e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen			m_result = sctp_process_asconf_delete_ip(src, aph, stcb,
7408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    error);
7418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
7428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ERROR_CAUSE_IND:
7438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* not valid in an ASCONF chunk */
7448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
7458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SET_PRIM_ADDR:
746e056c2b95d882d42490e3cc86c7fbd6134c79b32tuexen			m_result = sctp_process_asconf_set_primary(src, aph,
7478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    stcb, error);
7488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
7498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_NAT_VTAGS:
7508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: sees a NAT VTAG state parameter\n");
7518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        break;
7528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SUCCESS_REPORT:
7538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* not valid in an ASCONF chunk */
7548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
7558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ULP_ADAPTATION:
7568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* FIX */
7578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
7588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
7598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((param_type & 0x8000) == 0) {
7608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Been told to STOP at this param */
7618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				asconf_limit = offset;
7628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
7638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * FIX FIX - We need to call
7648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * sctp_arethere_unrecognized_parameters()
7658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * to get a operr and send it for any
7668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * param's with the 0x4000 bit set OR do it
7678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * here ourselves... note we still must STOP
7688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * if the 0x8000 bit is clear.
7698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
7708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
7718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* unknown/invalid param type */
7728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
7738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} /* switch */
7748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
7758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* add any (error) result to the reply mbuf chain */
7768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (m_result != NULL) {
7778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_NEXT(m_tail) = m_result;
7788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			m_tail = m_result;
7798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* update lengths, make sure it's aligned too */
7808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_LEN(m_result) = SCTP_SIZE32(SCTP_BUF_LEN(m_result));
7818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ack_cp->ch.chunk_length += SCTP_BUF_LEN(m_result);
7828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* set flag to force success reports */
7838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			error = 1;
7848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset += SCTP_SIZE32(param_length);
7868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* update remaining ASCONF message length to process */
7878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (offset >= asconf_limit) {
7888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no more data in the mbuf chain */
7898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
7908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
7918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* get pointer to next asconf param */
7928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
7938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct sctp_asconf_paramhdr),
7948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (uint8_t *)&aparam_buf);
7958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aph == NULL) {
7968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* can't get an asconf paramhdr */
7978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: can't get asconf param hdr!\n");
7988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* FIX ME - add error here... */
7998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
8008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen send_reply:
8038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack_cp->ch.chunk_length = htons(ack_cp->ch.chunk_length);
8048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* save the ASCONF-ACK reply */
8058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_asconf_ack),
8068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    struct sctp_asconf_ack);
8078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ack == NULL) {
8088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_ack);
8098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
8108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack->serial_number = serial_num;
8128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack->last_sent_to = NULL;
8138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack->data = m_ack;
8148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack->len = 0;
8158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	for (n = m_ack; n != NULL; n = SCTP_BUF_NEXT(n)) {
8168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ack->len += SCTP_BUF_LEN(n);
8178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_ack_sent, ack, next);
8198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* see if last_control_chunk_from is set properly (use IP src addr) */
8218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.last_control_chunk_from == NULL) {
8228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
8238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * this could happen if the source address was just newly
8248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * added
8258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
8268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: looking up net for IP source address\n");
8270c9710564cb3e091ff51af93a22257aa33f2e6catuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "Looking for IP source: ");
8280c9710564cb3e091ff51af93a22257aa33f2e6catuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, src);
8290c9710564cb3e091ff51af93a22257aa33f2e6catuexen		/* look up the from address */
8300c9710564cb3e091ff51af93a22257aa33f2e6catuexen		stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, src);
8318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG
8320c9710564cb3e091ff51af93a22257aa33f2e6catuexen		if (stcb->asoc.last_control_chunk_from == NULL) {
8330c9710564cb3e091ff51af93a22257aa33f2e6catuexen			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: IP source address not found?!\n");
8348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
8350c9710564cb3e091ff51af93a22257aa33f2e6catuexen#endif
8368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
8408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * does the address match? returns 0 if not, 1 if so
8418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
8428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t
8438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
8448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
8458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (sa->sa_family) {
8468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
8478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
8488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
8498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* XXX scopeid */
8508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
8518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) &&
8538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr,
8548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct in6_addr)) == 0)) {
8558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
8568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
8578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
8588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
8608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
8618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
8628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
8638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
8648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) &&
8668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (memcmp(&aa->ap.addrp.addr, &sin->sin_addr,
8678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct in_addr)) == 0)) {
8688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
8698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
8708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
8718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
8738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
8748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
8758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
8768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
8778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
8788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
8808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * does the address match? returns 0 if not, 1 if so
8818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
8828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t
8838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_addr_match(struct sctp_paramhdr *ph, struct sockaddr *sa)
8848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
885facb9a509f7ae3621b7d2771319811985d9c46b7t#if defined(INET) || defined(INET6)
8868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t param_type, param_length;
8878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	param_type = ntohs(ph->param_type);
8898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	param_length = ntohs(ph->param_length);
890facb9a509f7ae3621b7d2771319811985d9c46b7t#endif
8918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (sa->sa_family) {
8928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
8938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
8948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
8958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* XXX scopeid */
8968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
8978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_ipv6addr_param *v6addr;
8988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
8998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		v6addr = (struct sctp_ipv6addr_param *)ph;
9008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((param_type == SCTP_IPV6_ADDRESS) &&
901facb9a509f7ae3621b7d2771319811985d9c46b7t		    (param_length == sizeof(struct sctp_ipv6addr_param)) &&
9028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (memcmp(&v6addr->addr, &sin6->sin6_addr,
9038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct in6_addr)) == 0)) {
9048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
9058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
9068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
9078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
9108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
9118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
9128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
9138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_ipv4addr_param *v4addr;
9148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		v4addr = (struct sctp_ipv4addr_param *)ph;
9168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((param_type == SCTP_IPV4_ADDRESS) &&
917facb9a509f7ae3621b7d2771319811985d9c46b7t		    (param_length == sizeof(struct sctp_ipv4addr_param)) &&
9188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (memcmp(&v4addr->addr, &sin->sin_addr,
9198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct in_addr)) == 0)) {
9208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
9218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
9228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
9238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
9258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
9268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
9278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
9298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
9308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
9318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * Cleanup for non-responded/OP ERR'd ASCONF
9328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
9338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
9348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
9358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
9368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
9378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * clear out any existing asconfs going out
9388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
9398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
940b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen			SCTP_FROM_SCTP_ASCONF+SCTP_LOC_2);
9418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.asconf_seq_out_acked = stcb->asoc.asconf_seq_out;
9428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* remove the old ASCONF on our outbound queue */
9438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_toss_old_asconf(stcb);
9448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
9458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
9478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cleanup any cached source addresses that may be topologically
9488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * incorrect after a new address has been added to this interface.
9498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
9508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
9518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn)
9528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
9538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
9548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
9568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Ideally, we want to only clear cached routes and source addresses
9578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * that are topologically incorrect.  But since there is no easy way
9588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * to know whether the newly added address on the ifn would cause a
9598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * routing change (i.e. a new egress interface would be chosen)
9608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * without doing a new routing lookup and source address selection,
9618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * we will (for now) just flush any cached route using a different
9628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * ifn (and cached source addrs) and let output re-choose them during
9638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * the next send on that net.
9648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
9658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
9668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
9678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * clear any cached route (and cached source address) if the
9688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * route's interface is NOT the same as the address change.
9698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * If it's the same interface, just clear the cached source
9708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * address.
9718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
9728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) &&
9738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    ((ifn == NULL) ||
9748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     (SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index))) {
9758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* clear any cached route */
9768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			RTFREE(net->ro.ro_rt);
9778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ro.ro_rt = NULL;
9788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
9798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* clear any cached source address */
9808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->src_addr_selected) {
9818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_ifa(net->ro._s_addr);
9828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ro._s_addr = NULL;
9838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->src_addr_selected = 0;
9848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
9858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
9878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
9908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet)
9918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
9928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int error;
9938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
9948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (dstnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
9958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
9968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
9978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->asoc.deleted_primary == NULL) {
9988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
9998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
10028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: Deleted primary is ");
10038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa);
10048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "Current Primary is ");
10058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa);
10068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb,
10078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.deleted_primary,
10088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_FROM_SCTP_TIMER+SCTP_LOC_8);
10098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.num_send_timers_up--;
10108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->asoc.num_send_timers_up < 0) {
10118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.num_send_timers_up = 0;
10128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK_ASSERT(stcb);
10148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		error = sctp_t3rxt_timer(stcb->sctp_ep, stcb,
10158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.deleted_primary);
10168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (error) {
10178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INP_DECR_REF(stcb->sctp_ep);
10188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
10198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_TCB_LOCK_ASSERT(stcb);
10218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_AUDITING_ENABLED
10228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_auditing(4, stcb->sctp_ep, stcb, stcb->asoc.deleted_primary);
10238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
10248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
10258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((stcb->asoc.num_send_timers_up == 0) &&
10268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (stcb->asoc.sent_queue_cnt > 0)) {
10278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_tmit_chunk *chk;
1028000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
10298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
10308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
10318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 stcb, chk->whoTo);
10328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return;
10358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
10368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__)
10388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
10398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_queue_mgmt(struct sctp_tcb *, struct sctp_ifa *, uint16_t);
10408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
10428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net)
10438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
10448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk;
10458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans: RTO is %d\n", net->RTO);
10478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net,
10488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    SCTP_FROM_SCTP_TIMER+SCTP_LOC_5);
10498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
10508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	net->error_count = 0;
10518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
10528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->whoTo == net) {
10538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (chk->sent < SCTP_DATAGRAM_RESEND) {
10548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				chk->sent = SCTP_DATAGRAM_RESEND;
10558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
10568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_flight_size_decrease(chk);
10578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_total_flight_decrease(stcb, chk);
10588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->marked_retrans++;
10598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				stcb->asoc.marked_retrans++;
10608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
10618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
10628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net->marked_retrans) {
10648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
10658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
10668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
10678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
10698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
10708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
10718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
10728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int addrnum, changed;
10738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
10748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*   If number of local valid addresses is 1, the valid address is
10758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     probably newly added address.
10768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     Several valid addresses in this association.  A source address
10778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     may not be changed.  Additionally, they can be configured on a
10788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     same interface as "alias" addresses.  (by micchie)
10798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
10808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	addrnum = sctp_local_addr_count(stcb);
10818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_ASCONF1, "p_check_react(): %d local addresses\n",
10828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		addrnum);
10838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (addrnum == 1) {
10848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
10858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* clear any cached route and source address */
10868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->ro.ro_rt) {
10878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				RTFREE(net->ro.ro_rt);
10888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->ro.ro_rt = NULL;
10898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
10908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (net->src_addr_selected) {
10918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_free_ifa(net->ro._s_addr);
10928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->ro._s_addr = NULL;
10938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				net->src_addr_selected = 0;
10948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
10958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Retransmit unacknowledged DATA chunks immediately */
10968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
1097e2828360ea9cf8951730d46f5c14626c9425cb30t			                                SCTP_MOBILITY_FASTHANDOFF)) {
10988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_net_immediate_retrans(stcb, net);
10998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
11008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* also, SET PRIMARY is maybe already sent */
11018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
11038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Multiple local addresses exsist in the association.  */
11068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
11078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* clear any cached route and source address */
11088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->ro.ro_rt) {
11098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			RTFREE(net->ro.ro_rt);
11108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ro.ro_rt = NULL;
11118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->src_addr_selected) {
11138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_ifa(net->ro._s_addr);
11148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->ro._s_addr = NULL;
11158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->src_addr_selected = 0;
11168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Check if the nexthop is corresponding to the new address.
11188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   If the new address is corresponding to the current nexthop,
11198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   the path will be changed.
11208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   If the new address is NOT corresponding to the current
11218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   nexthop, the path will not be changed.
11228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
11238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_RTALLOC((sctp_route_t *)&net->ro,
11248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			     stcb->sctp_ep->def_vrf_id);
11258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net->ro.ro_rt == NULL)
11268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
11278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		changed = 0;
11298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (net->ro._l_addr.sa.sa_family) {
11308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
11318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case AF_INET:
11328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *)&net->ro)) {
11338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				changed = 1;
11348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
11358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
11368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
11378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
11388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case AF_INET6:
11398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_v6src_match_nexthop(
11408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    &newifa->address.sin6, (sctp_route_t *)&net->ro)) {
11418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				changed = 1;
11428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
11438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
11448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
11458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
11468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
11478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* if the newly added address does not relate routing
11498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		   information, we skip.
11508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
11518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (changed == 0)
11528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
11538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Retransmit unacknowledged DATA chunks immediately */
11548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_mobility_feature_on(stcb->sctp_ep,
1155e2828360ea9cf8951730d46f5c14626c9425cb30t		                                SCTP_MOBILITY_FASTHANDOFF)) {
11568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_net_immediate_retrans(stcb, net);
11578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Send SET PRIMARY for this new address */
11598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (net == stcb->asoc.primary_destination) {
11608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(void)sctp_asconf_queue_mgmt(stcb, newifa,
11618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						     SCTP_SET_PRIM_ADDR);
11628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
11648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
11658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* __FreeBSD__  __APPLE__  __Userspace__ */
11668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
11688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process an ADD/DELETE IP ack from peer.
11698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * addr: corresponding sctp_ifa to the address being added/deleted.
11708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS.
11718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * flag: 1=success, 0=failure.
11728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
11738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
11740ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr, uint32_t flag)
11758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
11768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
11778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * do the necessary asoc list work- if we get a failure indication,
11788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * leave the address on the assoc's restricted list.  If we get a
11798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * success indication, remove the address from the restricted list.
11808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
11818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
11828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * Note: this will only occur for ADD_IP_ADDRESS, since
11838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * DEL_IP_ADDRESS is never actually added to the list...
11848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
11858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (flag) {
11868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* success case, so remove from the restricted list */
11878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_del_local_addr_restricted(stcb, addr);
11888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
11898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__Userspace__)
11908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_mobility_feature_on(stcb->sctp_ep,
1191e2828360ea9cf8951730d46f5c14626c9425cb30t		                                SCTP_MOBILITY_BASE) ||
11928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sctp_is_mobility_feature_on(stcb->sctp_ep,
1193e2828360ea9cf8951730d46f5c14626c9425cb30t		                                SCTP_MOBILITY_FASTHANDOFF)) {
11948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_path_check_and_react(stcb, addr);
11958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
11968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
11978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* __FreeBSD__ __APPLE__ __Userspace__ */
11988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* clear any cached/topologically incorrect source addresses */
11998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_asconf_nets_cleanup(stcb, addr->ifn_p);
12008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* else, leave it on the list */
12028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
12038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
12058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * add an asconf add/delete/set primary IP address parameter to the queue.
12068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
12078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns 0 if queued, -1 if not queued/removed.
12088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: if adding, but a delete for the same address is already scheduled
12098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * (and not yet sent out), simply remove it from queue.  Same for deleting
12108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * an address already scheduled for add.  If a duplicate operation is found,
12118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * ignore the new one.
12128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
12138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
12148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
12158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       uint16_t type)
12168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
12178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_addr *aa, *aa_next;
12188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* make sure the request isn't already in the queue */
12208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
12218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* address match? */
12228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0)
12238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
12248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* is the request already in queue but not sent?
12258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * pass the request already sent in order to resolve the following case:
12268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 *  1. arrival of ADD, then sent
12278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 *  2. arrival of DEL. we can't remove the ADD request already sent
12288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 *  3. arrival of ADD
12298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
12308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aa->ap.aph.ph.param_type == type && aa->sent == 0) {
12318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (-1);
12328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* is the negative request already in queue, and not sent */
12348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((aa->sent == 0) && (type == SCTP_ADD_IP_ADDRESS) &&
12358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS)) {
12368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* add requested, delete already queued */
12378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
12388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* remove the ifa from the restricted list */
12398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_del_local_addr_restricted(stcb, ifa);
12408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* free the asconf param */
12418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE(aa, SCTP_M_ASC_ADDR);
12428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: add removes queued entry\n");
12438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (-1);
12448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((aa->sent == 0) && (type == SCTP_DEL_IP_ADDRESS) &&
12468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS)) {
12478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* delete requested, add already queued */
12488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
12498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* remove the aa->ifa from the restricted list */
12508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_del_local_addr_restricted(stcb, aa->ifa);
12518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* free the asconf param */
12528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE(aa, SCTP_M_ASC_ADDR);
12538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: delete removes queued entry\n");
12548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (-1);
12558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
12568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* for each aa */
12578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
12588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* adding new request to the queue */
12598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
12608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_M_ASC_ADDR);
12618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (aa == NULL) {
12628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* didn't get memory */
12638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n");
12648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
12658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aa->special_del = 0;
12678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* fill in asconf address parameter fields */
12688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* top level elements are "networked" during send */
12698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aa->ap.aph.ph.param_type = type;
12708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aa->ifa = ifa;
12718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	atomic_add_int(&ifa->refcount, 1);
12728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* correlation_id filled in during send routine later... */
12738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (ifa->address.sa.sa_family) {
12748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
12758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
12768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
12778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6;
12788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1279bfb1bf7e665a02b48026482bf33d05c83dfad73bt		sin6 = &ifa->address.sin6;
12808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
12818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
12828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
12838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct sctp_ipv6addr_param);
12848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
12858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       sizeof(struct in6_addr));
12868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
12878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
12888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
12898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
12908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
12918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
12928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sin;
12938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1294bfb1bf7e665a02b48026482bf33d05c83dfad73bt		sin = &ifa->address.sin;
12958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
12968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
12978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
12988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct sctp_ipv4addr_param);
12998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
13008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       sizeof(struct in_addr));
13018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
13028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
13048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
13058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* invalid family! */
13068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(aa, SCTP_M_ASC_ADDR);
13078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_ifa(ifa);
13088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
13098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aa->sent = 0;		/* clear sent flag */
13118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
13138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_DEBUG
13148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) {
13158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (type == SCTP_ADD_IP_ADDRESS) {
13168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: ");
13176377430fc6bf9f87402ccef28103c25a684dce20t			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
13188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (type == SCTP_DEL_IP_ADDRESS) {
13198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: ");
13206377430fc6bf9f87402ccef28103c25a684dce20t			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
13218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
13228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: ");
13236377430fc6bf9f87402ccef28103c25a684dce20t			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, &ifa->address.sa);
13248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
13278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
13298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
13308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
13338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * add an asconf operation for the given ifa and type.
13348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
13358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns 0 if completed, -1 if not completed, 1 if immediate send is
13368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * advisable.
13378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
13388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
13398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
13408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		      uint16_t type)
13418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
13428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t status;
13438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int pending_delete_queued = 0;
13448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* see if peer supports ASCONF */
1346fb3816eaffe5878bb1286adb120fd160da178a05t	if (stcb->asoc.asconf_supported == 0) {
13478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
13488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
13518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * if this is deleting the last address from the assoc, mark it as
13528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * pending.
13538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
13548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending &&
13558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (sctp_local_addr_count(stcb) < 2)) {
13568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* set the pending delete info only */
13578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.asconf_del_pending = 1;
13588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.asconf_addr_del_pending = ifa;
13598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&ifa->refcount, 1);
13608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF2,
13618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"asconf_queue_add: mark delete last address pending\n");
13628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
13638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* queue an asconf parameter */
13668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	status = sctp_asconf_queue_mgmt(stcb, ifa, type);
13678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
13698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * if this is an add, and there is a delete also pending (i.e. the
13708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * last local address is being changed), queue the pending delete too.
13718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
13728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending && (status == 0)) {
13738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* queue in the pending delete */
13748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_asconf_queue_mgmt(stcb,
13758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					   stcb->asoc.asconf_addr_del_pending,
13768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					   SCTP_DEL_IP_ADDRESS) == 0) {
13778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queing pending delete\n");
13788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			pending_delete_queued = 1;
13798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* clear out the pending delete info */
13808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.asconf_del_pending = 0;
13818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_ifa(stcb->asoc.asconf_addr_del_pending);
13828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.asconf_addr_del_pending = NULL;
13838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
13848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
13858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
13868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (pending_delete_queued) {
13878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_nets *net;
13888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
13898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * since we know that the only/last address is now being
13908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * changed in this case, reset the cwnd/rto on all nets to
13918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * start as a new address and path.  Also clear the error
13928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * counts to give the assoc the best chance to complete the
13938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * address change.
13948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
13958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
13968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb,
13978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									  net);
13988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->RTO = 0;
13998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			net->error_count = 0;
14008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		stcb->asoc.overall_error_count = 0;
14028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
14038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
14048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       stcb->asoc.overall_error_count,
14058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       0,
14068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       SCTP_FROM_SCTP_ASCONF,
14078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				       __LINE__);
14088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* queue in an advisory set primary too */
14118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		(void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR);
14128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* let caller know we should send this out immediately */
14138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		status = 1;
14148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (status);
14168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
14178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*-
14198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * add an asconf delete IP address parameter to the queue by sockaddr and
14208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * possibly with no sctp_ifa available.  This is only called by the routine
14218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * that checks the addresses in an INIT-ACK against the current address list.
14228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns 0 if completed, non-zero if not completed.
14238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * NOTE: if an add is already scheduled (and not yet sent out), simply
14248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * remove it from queue.  If a duplicate operation is found, ignore the
14258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * new one.
14268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
14278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
14288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
14298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
14308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *ifa;
14318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_addr *aa, *aa_next;
14328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
14338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
14358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
14368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* see if peer supports ASCONF */
1438fb3816eaffe5878bb1286adb120fd160da178a05t	if (stcb->asoc.asconf_supported == 0) {
14398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
14408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* make sure the request isn't already in the queue */
14428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
14438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* address match? */
14448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_asconf_addr_match(aa, sa) == 0)
14458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
14468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* is the request already in queue (sent or not) */
14478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
14488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (-1);
14498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* is the negative request already in queue, and not sent */
14518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aa->sent == 1)
14528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
14538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) {
14548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* add already queued, so remove existing entry */
14558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
14568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_del_local_addr_restricted(stcb, aa->ifa);
14578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* free the entry */
14588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_FREE(aa, SCTP_M_ASC_ADDR);
14598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (-1);
14608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
14618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* for each aa */
14628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */
14648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
14658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		vrf_id = stcb->asoc.vrf_id;
14668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
14678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		vrf_id = SCTP_DEFAULT_VRFID;
14688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
14708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* adding new request to the queue */
14728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
14738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_M_ASC_ADDR);
14748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (aa == NULL) {
14758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* didn't get memory */
14768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
14778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"sctp_asconf_queue_sa_delete: failed to get memory!\n");
14788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
14798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
14808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aa->special_del = 0;
14818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* fill in asconf address parameter fields */
14828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* top level elements are "networked" during send */
14838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
14848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aa->ifa = ifa;
14858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ifa)
14868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		atomic_add_int(&ifa->refcount, 1);
14878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* correlation_id filled in during send routine later... */
14888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (sa->sa_family) {
14898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
14908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
14918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
14928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* IPv6 address */
14938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6;
14948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
14958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sin6 = (struct sockaddr_in6 *)sa;
14968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
14978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
14988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param);
14998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
15008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct in6_addr));
15018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
15028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
15058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
15068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
15078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* IPv4 address */
15088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
15098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
15118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
15128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param);
15138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
15148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct in_addr));
15158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
15168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
15188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
15198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* invalid family! */
15208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_FREE(aa, SCTP_M_ASC_ADDR);
15218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ifa)
15228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_free_ifa(ifa);
15238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
15248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aa->sent = 0;		/* clear sent flag */
15268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* delete goes to the back of the queue */
15288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
15298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* sa_ignore MEMLEAK {memory is put on the tailq} */
15318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
15328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
15338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
15358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * find a specific asconf param on our "sent" queue
15368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
15378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sctp_asconf_addr *
15388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id)
15398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
15408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_addr *aa;
15418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
15438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aa->ap.aph.correlation_id == correlation_id &&
15448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    aa->sent == 1) {
15458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* found it */
15468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (aa);
15478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
15488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* didn't find it */
15508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (NULL);
15518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
15528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
15548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do
15558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * notifications based on the error response
15568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
15578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
1558fb3816eaffe5878bb1286adb120fd160da178a05tsctp_asconf_process_error(struct sctp_tcb *stcb SCTP_UNUSED,
15598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			  struct sctp_asconf_paramhdr *aph)
15608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
15618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_error_cause *eh;
15628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_paramhdr *ph;
15638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t param_type;
15648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t error_code;
15658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
15668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	eh = (struct sctp_error_cause *)(aph + 1);
15678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ph = (struct sctp_paramhdr *)(eh + 1);
15688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* validate lengths */
15698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (htons(eh->length) + sizeof(struct sctp_error_cause) >
15708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    htons(aph->ph.param_length)) {
15718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* invalid error cause length */
15728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
15738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"asconf_process_error: cause element too long\n");
15748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
15758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) >
15778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    htons(eh->length)) {
15788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* invalid included TLV length */
15798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
15808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"asconf_process_error: included TLV too long\n");
15818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
15828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
15838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* which error code ? */
15848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	error_code = ntohs(eh->code);
15858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	param_type = ntohs(aph->ph.param_type);
15868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* FIX: this should go back up the REMOTE_ERROR ULP notify */
15878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (error_code) {
15888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_CAUSE_RESOURCE_SHORTAGE:
15898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we allow ourselves to "try again" for this error */
15908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
15918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
15928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* peer can't handle it... */
15938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (param_type) {
15948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ADD_IP_ADDRESS:
15958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_DEL_IP_ADDRESS:
15968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SET_PRIM_ADDR:
15978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
15988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
15998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
16008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
16018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
16038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
16058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * process an asconf queue param.
16068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * aparam: parameter to process, will be removed from the queue.
16078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * flag: 1=success case, 0=failure case
16088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
16098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
16108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_process_param_ack(struct sctp_tcb *stcb,
16118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			      struct sctp_asconf_addr *aparam, uint32_t flag)
16128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
16138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t param_type;
16148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* process this param */
16168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	param_type = aparam->ap.aph.ph.param_type;
16178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (param_type) {
16188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_ADD_IP_ADDRESS:
16198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
16208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"process_param_ack: added IP address\n");
16210ac02f34d6041cd0018437596a5a9a94685e6919tuexen		sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, flag);
16228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
16238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_DEL_IP_ADDRESS:
16248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
16258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"process_param_ack: deleted IP address\n");
16268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* nothing really to do... lists already updated */
16278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
16288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case SCTP_SET_PRIM_ADDR:
16298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
16308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"process_param_ack: set primary IP address\n");
16318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* nothing to do... peer may start using this addr */
16328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
16338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
16348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* should NEVER happen */
16358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
16368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* remove the param and free it */
16398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next);
16408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (aparam->ifa)
16418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_ifa(aparam->ifa);
16428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
16438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
16448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
16468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * cleanup from a bad asconf ack parameter
16478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
16488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
1649fb3816eaffe5878bb1286adb120fd160da178a05tsctp_asconf_ack_clear(struct sctp_tcb *stcb SCTP_UNUSED)
16508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
16518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* assume peer doesn't really know how to do asconfs */
16528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* XXX we could free the pending queue here */
1653fb3816eaffe5878bb1286adb120fd160da178a05t
16548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
16558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
16578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_handle_asconf_ack(struct mbuf *m, int offset,
16588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb,
16598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		       struct sctp_nets *net, int *abort_no_unlock)
16608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
16618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_association *asoc;
16628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t serial_num;
16638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t ack_length;
16648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_paramhdr *aph;
16658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_addr *aa, *aa_next;
16668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t last_error_id = 0;	/* last error correlation id */
16678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t id;
16688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_addr *ap;
16698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* asconf param buffer */
16718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
16728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* verify minimum length */
16748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) {
16758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
16768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"handle_asconf_ack: chunk too small = %xh\n",
16778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ntohs(cp->ch.chunk_length));
16788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
16798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
16808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc = &stcb->asoc;
16818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	serial_num = ntohl(cp->serial_number);
16828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
16848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * NOTE: we may want to handle this differently- currently, we will
16858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * abort when we get an ack for the expected serial number + 1 (eg.
16868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * we didn't send it), process an ack normally if it is the expected
16878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * serial number, and re-send the previous ack for *ALL* other
16888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * serial numbers
16898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
16908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
16918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
16928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * if the serial number is the next expected, but I didn't send it,
16938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * abort the asoc, since someone probably just hijacked us...
16948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
16958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (serial_num == (asoc->asconf_seq_out + 1)) {
16968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
169747674b651417d493ff4e0318113fd7beeef119dbtuexen		sctp_abort_an_association(stcb->sctp_ep, stcb, NULL, SCTP_SO_NOT_LOCKED);
16988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		*abort_no_unlock = 1;
16998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
17008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (serial_num != asoc->asconf_seq_out_acked + 1) {
17028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* got a duplicate/unexpected ASCONF-ACK */
17038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n",
17048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			serial_num, asoc->asconf_seq_out_acked + 1);
17058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
17068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (serial_num == asoc->asconf_seq_out - 1) {
17098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* stop our timer */
17108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
1711b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen				SCTP_FROM_SCTP_ASCONF+SCTP_LOC_3);
17128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
17138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* process the ASCONF-ACK contents */
17158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ack_length = ntohs(cp->ch.chunk_length) -
17168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sizeof(struct sctp_asconf_ack_chunk);
17178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	offset += sizeof(struct sctp_asconf_ack_chunk);
17188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* process through all parameters */
17198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) {
17208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		unsigned int param_length, param_type;
17218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* get pointer to next asconf parameter */
17238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
17248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sizeof(struct sctp_asconf_paramhdr), aparam_buf);
17258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aph == NULL) {
17268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* can't get an asconf paramhdr */
17278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_asconf_ack_clear(stcb);
17288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
17298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		param_type = ntohs(aph->ph.param_type);
17318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		param_length = ntohs(aph->ph.param_length);
17328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (param_length > ack_length) {
17338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_asconf_ack_clear(stcb);
17348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
17358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (param_length < sizeof(struct sctp_paramhdr)) {
17378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_asconf_ack_clear(stcb);
17388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
17398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* get the complete parameter... */
17418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (param_length > sizeof(aparam_buf)) {
17428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1,
17438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				"param length (%u) larger than buffer size!\n", param_length);
17448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_asconf_ack_clear(stcb);
17458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
17468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
17488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aph == NULL) {
17498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_asconf_ack_clear(stcb);
17508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
17518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* correlation_id is transparent to peer, no ntohl needed */
17538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		id = aph->correlation_id;
17548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (param_type) {
17568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_ERROR_CAUSE_IND:
17578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			last_error_id = id;
17588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* find the corresponding asconf param in our queue */
17598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ap = sctp_asconf_find_param(stcb, id);
17608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (ap == NULL) {
17618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* hmm... can't find this in our queue! */
17628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
17638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
17648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* process the parameter, failed flag */
17658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_asconf_process_param_ack(stcb, ap, 0);
17668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* process the error response */
17678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_asconf_process_error(stcb, aph);
17688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
17698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_SUCCESS_REPORT:
17708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* find the corresponding asconf param in our queue */
17718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ap = sctp_asconf_find_param(stcb, id);
17728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (ap == NULL) {
17738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* hmm... can't find this in our queue! */
17748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
17758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
17768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* process the parameter, success flag */
17778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_asconf_process_param_ack(stcb, ap, 1);
17788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
17798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
17808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
17818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}		/* switch */
17828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* update remaining ASCONF-ACK message length to process */
17848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ack_length -= SCTP_SIZE32(param_length);
17858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ack_length <= 0) {
17868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* no more data in the mbuf chain */
17878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
17888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
17898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset += SCTP_SIZE32(param_length);
17908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* while */
17918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
17928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
17938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * if there are any "sent" params still on the queue, these are
17948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * implicitly "success", or "failed" (if we got an error back) ...
17958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * so process these appropriately
17968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 *
17978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * we assume that the correlation_id's are monotonically increasing
17988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * beginning from 1 and that we don't have *that* many outstanding
17998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * at any given time
18008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
18018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (last_error_id == 0)
18028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		last_error_id--;	/* set to "max" value */
18038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
18048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aa->sent == 1) {
18058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
18068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * implicitly successful or failed if correlation_id
18078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * < last_error_id, then success else, failure
18088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
18098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (aa->ap.aph.correlation_id < last_error_id)
18108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_asconf_process_param_ack(stcb, aa, 1);
18118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
18128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_asconf_process_param_ack(stcb, aa, 0);
18138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
18148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
18158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * since we always process in order (FIFO queue) if
18168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * we reach one that hasn't been sent, the rest
18178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * should not have been sent either. so, we're
18188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * done...
18198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
18208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
18218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* update the next sequence number to use */
18258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asoc->asconf_seq_out_acked++;
18268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* remove the old ASCONF on our outbound queue */
18278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_toss_old_asconf(stcb);
18288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) {
18298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TIMER_BASED_ASCONF
18308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we have more params, so restart our timer */
18318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep,
18328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 stcb, net);
18338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
18348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* we have more params, so send out more */
18358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
18368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
18398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
18418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t
18428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa)
18438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
18448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in6 *sin6, *net6;
18458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_nets *net;
18468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sa->sa_family != AF_INET6) {
18488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* wrong family */
18498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
18508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sin6 = (struct sockaddr_in6 *)sa;
18528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) {
18538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* not link local address */
18548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
18558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* hunt through our destination nets list for this scope_id */
18578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
18588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (((struct sockaddr *)(&net->ro._l_addr))->sa_family !=
18598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    AF_INET6)
18608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
18618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		net6 = (struct sockaddr_in6 *)&net->ro._l_addr;
18628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0)
18638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
18648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_same_scope(sin6, net6)) {
18658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* found one */
18668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (1);
18678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
18688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* didn't find one */
18708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
18718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
18728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
18738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
18758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address management functions
18768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
18778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
18788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
18798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		     struct sctp_ifa *ifa, uint16_t type, int addr_locked)
18808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
18818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int status;
18828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
18838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 ||
18848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
18858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* subset bound, no ASCONF allowed case, so ignore */
18868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
18878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
18888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
18898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * note: we know this is not the subset bound, no ASCONF case eg.
18908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * this is boundall or subset bound w/ASCONF allowed
18918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
18928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1893998635733088fde643e6d807fa76679c4ceeaa00t	/* first, make sure that the address is IPv4 or IPv6 and not jailed */
18948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (ifa->address.sa.sa_family) {
18958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
18968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
1897998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
1898998635733088fde643e6d807fa76679c4ceeaa00t		if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
1899998635733088fde643e6d807fa76679c4ceeaa00t		                     &ifa->address.sin6.sin6_addr) != 0) {
1900998635733088fde643e6d807fa76679c4ceeaa00t			return;
1901998635733088fde643e6d807fa76679c4ceeaa00t		}
1902998635733088fde643e6d807fa76679c4ceeaa00t#endif
19038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
19048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
19068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
1907998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
1908998635733088fde643e6d807fa76679c4ceeaa00t		if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
1909998635733088fde643e6d807fa76679c4ceeaa00t		                     &ifa->address.sin.sin_addr) != 0) {
1910998635733088fde643e6d807fa76679c4ceeaa00t			return;
1911998635733088fde643e6d807fa76679c4ceeaa00t		}
1912998635733088fde643e6d807fa76679c4ceeaa00t#endif
19138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
19148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
19168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
19178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
19198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* make sure we're "allowed" to add this type of addr */
19208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ifa->address.sa.sa_family == AF_INET6) {
19218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* invalid if we're not a v6 endpoint */
19228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0)
19238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
19248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* is the v6 addr really valid ? */
19258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
19268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
19278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* put this address on the "pending/do not use yet" list */
19318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_add_local_addr_restricted(stcb, ifa);
19328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
19338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * check address scope if address is out of scope, don't queue
19348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * anything... note: this would leave the address on both inp and
19358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * asoc lists
19368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
19378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (ifa->address.sa.sa_family) {
19388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
19398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
19408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
19418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in6 *sin6;
19428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1943bfb1bf7e665a02b48026482bf33d05c83dfad73bt		sin6 = &ifa->address.sin6;
19448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
19458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* we skip unspecifed addresses */
19468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
19478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
19497988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			if (stcb->asoc.scope.local_scope == 0) {
19508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
19518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* is it the right link local scope? */
19538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
19548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
19558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
19568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19577988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		if (stcb->asoc.scope.site_scope == 0 &&
19588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
19598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
19608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
19628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
19658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
19668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	{
19678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr_in *sin;
19688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct in6pcb *inp6;
19698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		inp6 = (struct in6pcb *)&inp->ip_inp.inp;
19718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* invalid if we are a v6 only endpoint */
19728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
19738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_IPV6_V6ONLY(inp6))
19748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
19758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
1976bfb1bf7e665a02b48026482bf33d05c83dfad73bt		sin = &ifa->address.sin;
19778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sin->sin_addr.s_addr == 0) {
19788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* we skip unspecifed addresses */
19798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
19808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19817988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		if (stcb->asoc.scope.ipv4_local_scope == 0 &&
19828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
19838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
19848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
19858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
19868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
19888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
19898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* else, not AF_INET or AF_INET6, so skip */
19908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
19918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
19928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
19938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* queue an asconf for this address add/delete */
19948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
19958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* does the peer do asconf? */
1996fb3816eaffe5878bb1286adb120fd160da178a05t		if (stcb->asoc.asconf_supported) {
19978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* queue an asconf for this addr */
19988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			status = sctp_asconf_queue_add(stcb, ifa, type);
19998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
20018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * if queued ok, and in the open state, send out the
20028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * ASCONF.  If in the non-open state, these will be
20038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * sent when the state goes open.
20048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
20058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (status == 0 &&
20068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
20078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TIMER_BASED_ASCONF
20088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
20098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    stcb, stcb->asoc.primary_destination);
20108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
20118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_send_asconf(stcb, NULL, addr_locked);
20128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
20138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
20178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
20200ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED)
20218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
20228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_iterator *asc;
20238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *ifa;
20248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_laddr *l;
2025b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	int cnt_invalid = 0;
20268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asc = (struct sctp_asconf_iterator *)ptr;
20288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
20298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ifa = l->ifa;
20308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (ifa->address.sa.sa_family) {
20318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
20328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case AF_INET6:
20338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid if we're not a v6 endpoint */
20348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
20358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				cnt_invalid++;
20368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (asc->cnt == cnt_invalid)
20378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (1);
20388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
20408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
20418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
20428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case AF_INET:
20438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
20448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid if we are a v6 only endpoint */
20458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct in6pcb *inp6;
20468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp6 = (struct in6pcb *)&inp->ip_inp.inp;
20478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
20488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_IPV6_V6ONLY(inp6)) {
20498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				cnt_invalid++;
20508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (asc->cnt == cnt_invalid)
20518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (1);
20528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
20548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
20568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
20578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid address family */
20588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cnt_invalid++;
20598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asc->cnt == cnt_invalid)
20608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (1);
20618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
20648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
20658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic int
20670ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val SCTP_UNUSED)
20688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
20698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *ifa;
20708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_iterator *asc;
20718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_laddr *laddr, *nladdr, *l;
20728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Only for specific case not bound all */
20748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asc = (struct sctp_asconf_iterator *)ptr;
20758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
20768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ifa = l->ifa;
20778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (l->action == SCTP_ADD_IP_ADDRESS) {
20788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_FOREACH(laddr, &inp->sctp_addr_list,
20798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     sctp_nxt_addr) {
20808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (laddr->ifa == ifa) {
20818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					laddr->action = 0;
20828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
20838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
20848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (l->action == SCTP_DEL_IP_ADDRESS) {
20878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
20888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* remove only after all guys are done */
20898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (laddr->ifa == ifa) {
20908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_del_local_addr_ep(inp, ifa);
20918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
20928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
20938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
20948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
20958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
20968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
20978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
20988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
20998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
21000ac02f34d6041cd0018437596a5a9a94685e6919tuexen			  void *ptr, uint32_t val SCTP_UNUSED)
21018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
21028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_iterator *asc;
21038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *ifa;
21048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_laddr *l;
21058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int cnt_invalid = 0;
21068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int type, status;
21078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int num_queued = 0;
21088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asc = (struct sctp_asconf_iterator *)ptr;
21108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
21118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ifa = l->ifa;
21128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		type = l->action;
21138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* address's vrf_id must be the vrf_id of the assoc */
21158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ifa->vrf_id != stcb->asoc.vrf_id) {
21168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
21178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Same checks again for assoc */
21208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (ifa->address.sa.sa_family) {
21218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
21228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case AF_INET6:
21238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
21248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid if we're not a v6 endpoint */
21258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr_in6 *sin6;
21268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
21288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				cnt_invalid++;
21298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (asc->cnt == cnt_invalid)
21308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
21318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
21328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
21338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
2134bfb1bf7e665a02b48026482bf33d05c83dfad73bt			sin6 = &ifa->address.sin6;
21358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
21368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* we skip unspecifed addresses */
21378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
21388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
2139998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
2140998635733088fde643e6d807fa76679c4ceeaa00t			if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
2141998635733088fde643e6d807fa76679c4ceeaa00t			                     &sin6->sin6_addr) != 0) {
2142998635733088fde643e6d807fa76679c4ceeaa00t				continue;
2143998635733088fde643e6d807fa76679c4ceeaa00t			}
2144998635733088fde643e6d807fa76679c4ceeaa00t#endif
21458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
21467988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				if (stcb->asoc.scope.local_scope == 0) {
21478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
21488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
21498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* is it the right link local scope? */
21508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
21518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
21528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
21538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
21558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
21578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
21588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case AF_INET:
21598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
21608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid if we are a v6 only endpoint */
21618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct in6pcb *inp6;
21628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sockaddr_in *sin;
21638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
21648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			inp6 = (struct in6pcb *)&inp->ip_inp.inp;
21658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid if we are a v6 only endpoint */
21668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
21678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_IPV6_V6ONLY(inp6))
21688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
21698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2170bfb1bf7e665a02b48026482bf33d05c83dfad73bt			sin = &ifa->address.sin;
21718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sin->sin_addr.s_addr == 0) {
21728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* we skip unspecifed addresses */
21738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
21748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
2175998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
2176998635733088fde643e6d807fa76679c4ceeaa00t			if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
2177998635733088fde643e6d807fa76679c4ceeaa00t			                     &sin->sin_addr) != 0) {
2178998635733088fde643e6d807fa76679c4ceeaa00t				continue;
2179998635733088fde643e6d807fa76679c4ceeaa00t			}
2180998635733088fde643e6d807fa76679c4ceeaa00t#endif
21817988ea8f0c067cf3757e798b473b1ae4d34b6dfdt			if (stcb->asoc.scope.ipv4_local_scope == 0 &&
21828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
21838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
21848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
21868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_IPV6_V6ONLY(inp6)) {
21878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				cnt_invalid++;
21888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (asc->cnt == cnt_invalid)
21898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return;
21908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				else
21918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
21928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
21938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
21948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
21958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
21968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
21978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* invalid address family */
21988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			cnt_invalid++;
21998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asc->cnt == cnt_invalid)
22008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
22018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			else
22028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
2203000a5bac556b28e74e4e98c540f66b1743e9312dtuexen			break;
22048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (type == SCTP_ADD_IP_ADDRESS) {
22078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* prevent this address from being used as a source */
22088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_add_local_addr_restricted(stcb, ifa);
22098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (type == SCTP_DEL_IP_ADDRESS) {
22108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_nets *net;
22118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
22128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_rtentry_t *rt;
22138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* delete this address if cached */
22158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (net->ro._s_addr == ifa) {
22168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_free_ifa(net->ro._s_addr);
22178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->ro._s_addr = NULL;
22188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->src_addr_selected = 0;
22198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					rt = net->ro.ro_rt;
22208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (rt) {
22218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						RTFREE(rt);
22228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						net->ro.ro_rt = NULL;
22238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
22248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/*
22258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * Now we deleted our src address,
22268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * should we not also now reset the
22278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * cwnd/rto to start as if its a new
22288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 * address?
22298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 */
22308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
22318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					net->RTO = 0;
22328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
22348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
22358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (type == SCTP_SET_PRIM_ADDR) {
22368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
22378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* must validate the ifa is in the ep */
2238998635733088fde643e6d807fa76679c4ceeaa00t				if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) {
22398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
22408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
22418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
22428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Need to check scopes for this guy */
22437988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				if (sctp_is_address_in_scope(ifa, &stcb->asoc.scope, 0) == 0) {
22448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
22458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
22468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
22478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* queue an asconf for this address add/delete */
22498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) &&
2250fb3816eaffe5878bb1286adb120fd160da178a05t		    stcb->asoc.asconf_supported == 1) {
22518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* queue an asconf for this addr */
22528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			status = sctp_asconf_queue_add(stcb, ifa, type);
22538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
22548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * if queued ok, and in the open state, update the
22558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * count of queued params.  If in the non-open state,
22568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * these get sent when the assoc goes open.
22578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
22588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
22598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (status >= 0) {
22608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					num_queued++;
22618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
22628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
22638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
22668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * If we have queued params in the open state, send out an ASCONF.
22678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
22688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (num_queued > 0) {
22698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
22708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
22728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
22740ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_asconf_iterator_end(void *ptr, uint32_t val SCTP_UNUSED)
22758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
22768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_iterator *asc;
22778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *ifa;
22788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_laddr *l, *nl;
22798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	asc = (struct sctp_asconf_iterator *)ptr;
22818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH_SAFE(l, &asc->list_of_work, sctp_nxt_addr, nl) {
22828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ifa = l->ifa;
22838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (l->action == SCTP_ADD_IP_ADDRESS) {
22848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Clear the defer use flag */
22858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
22868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
22878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_free_ifa(ifa);
22888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l);
22898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_DECR_LADDR_COUNT();
22908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
22918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_FREE(asc, SCTP_M_ASC_IT);
22928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
22938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
22948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
22958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sa is the sockaddr to ask the peer to set primary to.
22968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns: 0 = completed, -1 = error
22978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
22988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint32_t
22998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
23008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
2301e2828360ea9cf8951730d46f5c14626c9425cb30t	uint32_t vrf_id;
23028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *ifa;
23038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* find the ifa for the desired set primary */
23058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf_id = stcb->asoc.vrf_id;
23068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
23078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ifa == NULL) {
23088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* Invalid address */
23098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
23108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* queue an ASCONF:SET_PRIM_ADDR to be sent */
23138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) {
23148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* set primary queuing succeeded */
23158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
23168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"set_primary_ip_address_sa: queued on tcb=%p, ",
2317ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t			(void *)stcb);
23188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
23198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
23208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TIMER_BASED_ASCONF
23218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
23228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 stcb->sctp_ep, stcb,
23238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					 stcb->asoc.primary_destination);
23248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
23258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
23268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
23278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
23298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ",
2330ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t			(void *)stcb);
23318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
23328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (-1);
23338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
23348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
23358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
23368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
23388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_set_primary_ip_address(struct sctp_ifa *ifa)
23398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
23408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_inpcb *inp;
23418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* go through all our PCB's */
23438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
23448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_tcb *stcb;
23458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* process for all associations for this endpoint */
23478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
23488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* queue an ASCONF:SET_PRIM_ADDR to be sent */
23498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (!sctp_asconf_queue_add(stcb, ifa,
23508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						   SCTP_SET_PRIM_ADDR)) {
23518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* set primary queuing succeeded */
23528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ",
2353ef2346ee09e2a6d7e580c0d41191f82e3b1f4937t					(void *)stcb);
23548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa);
23558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
23568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TIMER_BASED_ASCONF
23578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
23588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 stcb->sctp_ep, stcb,
23598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 stcb->asoc.primary_destination);
23608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
23618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
23628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
23638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
23648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
23658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} /* for each stcb */
23668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* for each inp */
23678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
23688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenint
23708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
23718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
23728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_tmit_chunk *chk, *nchk;
23738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	unsigned int offset, asconf_limit;
23748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_chunk *acp;
23758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_paramhdr *aph;
23768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
23778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_paramhdr *ph;
23788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	int add_cnt, del_cnt;
23798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t last_param_type;
23808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	add_cnt = del_cnt = 0;
23828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	last_param_type = 0;
23838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH_SAFE(chk, &stcb->asoc.asconf_send_queue, sctp_next, nchk) {
23848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (chk->data == NULL) {
23858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n");
23868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
23878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset = 0;
23898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		acp = mtod(chk->data, struct sctp_asconf_chunk *);
23908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset += sizeof(struct sctp_asconf_chunk);
23918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		asconf_limit = ntohs(acp->ch.chunk_length);
23928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph = (struct sctp_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf);
23938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (ph == NULL) {
23948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n");
23958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
23968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
23978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset += ntohs(ph->param_length);
23988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
23998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
24008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aph == NULL) {
24018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: Empty ASCONF will be sent?\n");
24028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
24038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		while (aph != NULL) {
24058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			unsigned int param_length, param_type;
24068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			param_type = ntohs(aph->ph.param_type);
24088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			param_length = ntohs(aph->ph.param_length);
24098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (offset + param_length > asconf_limit) {
24108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* parameter goes beyond end of chunk! */
24118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
24128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (param_length > sizeof(aparam_buf)) {
24148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length (%u) larger than buffer size!\n", param_length);
24158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
24168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (param_length <= sizeof(struct sctp_paramhdr)) {
24188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length(%u) too short\n", param_length);
24198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
24208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, param_length, aparam_buf);
24238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (aph == NULL) {
24248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n");
24258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
24268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			ph = (struct sctp_paramhdr *)(aph + 1);
24298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_addr_match(ph, &sctp_ifa->address.sa) != 0) {
24308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				switch (param_type) {
24318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case SCTP_ADD_IP_ADDRESS:
24328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					add_cnt++;
24338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
24348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case SCTP_DEL_IP_ADDRESS:
24358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					del_cnt++;
24368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
24378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				default:
24388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
24398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
24408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				last_param_type = param_type;
24418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			offset += SCTP_SIZE32(param_length);
24448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (offset >= asconf_limit) {
24458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* no more data in the mbuf chain */
24468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
24478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
24488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* get pointer to next asconf param */
24498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
24508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* we want to find the sequences which consist of ADD -> DEL -> ADD or DEL -> ADD */
24548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (add_cnt > del_cnt ||
24558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    (add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) {
2456b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen		return (1);
24578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
2458b7ebbfc1bd4420174e2a11b3b2bfd64281f44032tuexen	return (0);
24598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
24608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sockaddr *
24628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
24638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
24648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_vrf *vrf = NULL;
24658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifn *sctp_ifn;
24668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *sctp_ifa;
24678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
24688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (addr_locked == SCTP_ADDR_NOT_LOCKED)
24698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_IPI_ADDR_RLOCK();
24708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf = sctp_find_vrf(stcb->asoc.vrf_id);
24718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (vrf == NULL) {
24728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (addr_locked == SCTP_ADDR_NOT_LOCKED)
24738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_IPI_ADDR_RUNLOCK();
24748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
24758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
24768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
24777988ea8f0c067cf3757e798b473b1ae4d34b6dfdt		if (stcb->asoc.scope.loopback_scope == 0 &&
24788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
24798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* Skip if loopback_scope not set */
24808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
24818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
24828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
24838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			switch (sctp_ifa->address.sa.sa_family) {
24848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
24858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET:
24867988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				if (stcb->asoc.scope.ipv4_addr_legal) {
24878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					struct sockaddr_in *sin;
24888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2489bfb1bf7e665a02b48026482bf33d05c83dfad73bt					sin = &sctp_ifa->address.sin;
24908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sin->sin_addr.s_addr == 0) {
24918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* skip unspecifed addresses */
24928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
24938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
2494998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
2495998635733088fde643e6d807fa76679c4ceeaa00t					if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
2496998635733088fde643e6d807fa76679c4ceeaa00t					                     &sin->sin_addr) != 0) {
2497998635733088fde643e6d807fa76679c4ceeaa00t						continue;
2498998635733088fde643e6d807fa76679c4ceeaa00t					}
2499998635733088fde643e6d807fa76679c4ceeaa00t#endif
25007988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					if (stcb->asoc.scope.ipv4_local_scope == 0 &&
25018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
25028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
25038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
25058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (!sctp_is_addr_pending(stcb, sctp_ifa)))
25068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
25078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* found a valid local v4 address to use */
25088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (addr_locked == SCTP_ADDR_NOT_LOCKED)
25098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_IPI_ADDR_RUNLOCK();
25108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (&sctp_ifa->address.sa);
25118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
25128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
25138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
25148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
25158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET6:
25167988ea8f0c067cf3757e798b473b1ae4d34b6dfdt				if (stcb->asoc.scope.ipv6_addr_legal) {
25178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					struct sockaddr_in6 *sin6;
25188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
25208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
25218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
25228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
2523bfb1bf7e665a02b48026482bf33d05c83dfad73bt					sin6 = &sctp_ifa->address.sin6;
25248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
25258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						/* we skip unspecifed addresses */
25268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
25278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
2528998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
2529998635733088fde643e6d807fa76679c4ceeaa00t					if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
2530998635733088fde643e6d807fa76679c4ceeaa00t					                     &sin6->sin6_addr) != 0) {
2531998635733088fde643e6d807fa76679c4ceeaa00t						continue;
2532998635733088fde643e6d807fa76679c4ceeaa00t					}
2533998635733088fde643e6d807fa76679c4ceeaa00t#endif
25347988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					if (stcb->asoc.scope.local_scope == 0 &&
25358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
25368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
25377988ea8f0c067cf3757e798b473b1ae4d34b6dfdt					if (stcb->asoc.scope.site_scope == 0 &&
25388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
25398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
25408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
25428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					    (!sctp_is_addr_pending(stcb, sctp_ifa)))
25438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
25448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* found a valid local v6 address to use */
25458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (addr_locked == SCTP_ADDR_NOT_LOCKED)
25468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						SCTP_IPI_ADDR_RUNLOCK();
25478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (&sctp_ifa->address.sa);
25488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
25498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
25508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
25518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			default:
25528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
25538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
25548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* no valid addresses found */
25578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (addr_locked == SCTP_ADDR_NOT_LOCKED)
25588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_IPI_ADDR_RUNLOCK();
25598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (NULL);
25608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
25618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic struct sockaddr *
25638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_find_valid_localaddr_ep(struct sctp_tcb *stcb)
25648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
25658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_laddr *laddr;
25668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
25688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (laddr->ifa == NULL) {
25698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
25708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
25718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* is the address restricted ? */
25728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_addr_restricted(stcb, laddr->ifa) &&
25738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (!sctp_is_addr_pending(stcb, laddr->ifa)))
25748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
25758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* found a valid local address to use */
25778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (&laddr->ifa->address.sa);
25788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
25798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* no valid addresses found */
25808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (NULL);
25818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
25828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
25838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
25848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * builds an ASCONF chunk from queued ASCONF params.
25858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * returns NULL on error (no mbuf, no ASCONF params queued, etc).
25868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
25878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstruct mbuf *
25888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
25898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
25908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct mbuf *m_asconf, *m_asconf_chk;
25918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_addr *aa;
25928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_chunk *acp;
25938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_paramhdr *aph;
25948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_addr_param *aap;
25958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t p_length;
25968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t correlation_id = 1;	/* 0 is reserved... */
25978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	caddr_t ptr, lookup_ptr;
25988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint8_t lookup_used = 0;
25998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* are there any asconf params to send? */
26018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
26028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aa->sent == 0)
26038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
26048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (aa == NULL)
26068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
26078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/*
26098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * get a chunk header mbuf and a cluster for the asconf params since
26108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * it's simpler to fill in the asconf chunk header lookup address on
26118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 * the fly
26128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	 */
261368beeca578347438d9c434680197647ed551935ft	m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_NOWAIT, 1, MT_DATA);
26148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_asconf_chk == NULL) {
26158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no mbuf's */
26168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
26178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"compose_asconf: couldn't get chunk mbuf!\n");
26188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
26198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
262068beeca578347438d9c434680197647ed551935ft	m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_NOWAIT, 1, MT_DATA);
26218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (m_asconf == NULL) {
26228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* no mbuf's */
26238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
26248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"compose_asconf: couldn't get mbuf!\n");
26258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_m_freem(m_asconf_chk);
26268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (NULL);
26278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
26288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk);
26298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_LEN(m_asconf) = 0;
26308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *);
26318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	bzero(acp, sizeof(struct sctp_asconf_chunk));
26328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* save pointers to lookup address and asconf params */
26338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	lookup_ptr = (caddr_t)(acp + 1);	/* after the header */
26348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ptr = mtod(m_asconf, caddr_t);	/* beginning of cluster */
26358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* fill in chunk header info */
26378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	acp->ch.chunk_type = SCTP_ASCONF;
26388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	acp->ch.chunk_flags = 0;
26398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	acp->serial_number = htonl(stcb->asoc.asconf_seq_out);
26408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	stcb->asoc.asconf_seq_out++;
26418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* add parameters... up to smallest MTU allowed */
26438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
26448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (aa->sent)
26458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
26468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* get the parameter length */
26478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length);
26488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* will it fit in current chunk? */
2649b48fc31e0eefd3b5593a363dd52d50c254a69f89t		if ((SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) ||
2650b48fc31e0eefd3b5593a363dd52d50c254a69f89t		    (SCTP_BUF_LEN(m_asconf) + p_length > MCLBYTES)) {
26518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* won't fit, so we're done with this chunk */
26528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
26538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* assign (and store) a correlation id */
26558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.correlation_id = correlation_id++;
26568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
26588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * fill in address if we're doing a delete this is a simple
26598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * way for us to fill in the correlation address, which
26608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * should only be used by the peer if we're deleting our
26618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * source address and adding a new address (e.g. renumbering
26628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * case)
26638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
26648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (lookup_used == 0 &&
26658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (aa->special_del == 0) &&
26668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
26678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_ipv6addr_param *lookup;
26688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			uint16_t p_size, addr_size;
26698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
26718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			lookup->ph.param_type =
26728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    htons(aa->ap.addrp.ph.param_type);
26738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) {
26748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* copy IPv6 address */
26758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				p_size = sizeof(struct sctp_ipv6addr_param);
26768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr_size = sizeof(struct in6_addr);
26778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			} else {
26788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* copy IPv4 address */
26798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				p_size = sizeof(struct sctp_ipv4addr_param);
26808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr_size = sizeof(struct in_addr);
26818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
26828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
26838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size);
26848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
26858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			lookup_used = 1;
26868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
26878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* copy into current space */
26888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		memcpy(ptr, &aa->ap, p_length);
26898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* network elements and update lengths */
26918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aph = (struct sctp_asconf_paramhdr *)ptr;
26928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aap = (struct sctp_asconf_addr_param *)ptr;
26938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* correlation_id is transparent to peer, no htonl needed */
26948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aph->ph.param_type = htons(aph->ph.param_type);
26958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aph->ph.param_length = htons(aph->ph.param_length);
26968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type);
26978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length);
26988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
26998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length);
27008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ptr += SCTP_SIZE32(p_length);
27018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
27038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * these params are removed off the pending list upon
27048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * getting an ASCONF-ACK back from the peer, just set flag
27058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
27068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->sent = 1;
27078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
27088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* check to see if the lookup addr has been populated yet */
27098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (lookup_used == 0) {
27108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* NOTE: if the address param is optional, can skip this... */
27118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* add any valid (existing) address... */
27128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_ipv6addr_param *lookup;
27138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint16_t p_size, addr_size;
27148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sockaddr *found_addr;
27158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		caddr_t addr_ptr;
27168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL)
27188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			found_addr = sctp_find_valid_localaddr(stcb,
27198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							       addr_locked);
27208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		else
27218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			found_addr = sctp_find_valid_localaddr_ep(stcb);
27228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
27248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (found_addr != NULL) {
27258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			switch (found_addr->sa_family) {
27268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
27278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET6:
27288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* copy IPv6 address */
27298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				lookup->ph.param_type =
27308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    htons(SCTP_IPV6_ADDRESS);
27318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				p_size = sizeof(struct sctp_ipv6addr_param);
27328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr_size = sizeof(struct in6_addr);
27338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr_ptr = (caddr_t)&((struct sockaddr_in6 *)
27348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    found_addr)->sin6_addr;
27358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
27368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
27378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
27388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET:
27398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* copy IPv4 address */
27408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				lookup->ph.param_type =
27418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    htons(SCTP_IPV4_ADDRESS);
27428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				p_size = sizeof(struct sctp_ipv4addr_param);
27438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr_size = sizeof(struct in_addr);
27448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr_ptr = (caddr_t)&((struct sockaddr_in *)
27458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    found_addr)->sin_addr;
27468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
27478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
27488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			default:
27498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				p_size = 0;
27508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr_size = 0;
27518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				addr_ptr = NULL;
27528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
27538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
27548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
27558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			memcpy(lookup->addr, addr_ptr, addr_size);
27568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
27578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
27588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* uh oh... don't have any address?? */
27598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1,
27608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				"compose_asconf: no lookup addr!\n");
27618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* XXX for now, we send a IPv4 address of 0.0.0.0 */
27628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS);
27638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)));
27648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			bzero(lookup->addr, sizeof(struct in_addr));
27658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param));
27668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
27678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
27688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* chain it all together */
27698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_BUF_NEXT(m_asconf_chk) = m_asconf;
27708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	*retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf);
27715310a647a74c51d125d106f350ff224bb017b0a5t	acp->ch.chunk_length = htons(*retlen);
27728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (m_asconf_chk);
27748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
27758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
27778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * section to handle address changes before an association is up eg. changes
27788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * during INIT/INIT-ACK/COOKIE-ECHO handshake
27798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
27808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
27818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
27828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * processes the (local) addresses in the INIT-ACK chunk
27838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
27848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
27858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
27868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    unsigned int offset, unsigned int length)
27878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
27888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_paramhdr tmp_param, *ph;
27898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t plen, ptype;
27908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *sctp_ifa;
27911b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t	union sctp_sockstore store;
27928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
2793c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen	struct sctp_ipv6addr_param addr6_store;
27948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
27958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
2796c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen	struct sctp_ipv4addr_param addr4_store;
27978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
27988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
27998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n");
28018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) /* Un-needed check for SA */
28028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
28038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* convert to upper bound */
28058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	length += offset;
28060ac02f34d6041cd0018437596a5a9a94685e6919tuexen
28078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((offset + sizeof(struct sctp_paramhdr)) > length) {
28088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
28098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
28108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* go through the addresses in the init-ack */
28118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ph = (struct sctp_paramhdr *)
28128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	     sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
28138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	                   (uint8_t *)&tmp_param);
28148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (ph != NULL) {
28158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ptype = ntohs(ph->param_type);
28168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		plen = ntohs(ph->param_length);
28178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (ptype) {
28188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
28198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_IPV6_ADDRESS:
28208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
28218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_ipv6addr_param *a6p;
28228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* get the entire IPv6 address param */
28248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			a6p = (struct sctp_ipv6addr_param *)
28258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    sctp_m_getptr(m, offset,
28268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    sizeof(struct sctp_ipv6addr_param),
2827c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen			    (uint8_t *)&addr6_store);
28288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (plen != sizeof(struct sctp_ipv6addr_param) ||
28298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    a6p == NULL) {
28308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
28318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
28321b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t			memset(&store, 0, sizeof(union sctp_sockstore));
28331b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t			store.sin6.sin6_family = AF_INET6;
28341b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t#ifdef HAVE_SIN6_LEN
28351b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t			store.sin6.sin6_len = sizeof(struct sockaddr_in6);
28361b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t#endif
28371b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t			store.sin6.sin6_port = stcb->rport;
28381b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t			memcpy(&store.sin6.sin6_addr, a6p->addr, sizeof(struct in6_addr));
28398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
28408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
28428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
28438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_IPV4_ADDRESS:
28448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		{
28458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_ipv4addr_param *a4p;
28468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* get the entire IPv4 address param */
28488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset,
28498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen									  sizeof(struct sctp_ipv4addr_param),
2850c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen									  (uint8_t *)&addr4_store);
28518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (plen != sizeof(struct sctp_ipv4addr_param) ||
28528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    a4p == NULL) {
28538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return;
28548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
28551b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t			memset(&store, 0, sizeof(union sctp_sockstore));
28561b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t			store.sin.sin_family = AF_INET;
28571b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t#ifdef HAVE_SIN_LEN
28581b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t			store.sin.sin_len = sizeof(struct sockaddr_in);
28591b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t#endif
28601b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t			store.sin.sin_port = stcb->rport;
28611b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t			store.sin.sin_addr.s_addr = a4p->addr;
28628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
28638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
28658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
28668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto next_addr;
28678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* see if this address really (still) exists */
28708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (stcb) {
28718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			vrf_id = stcb->asoc.vrf_id;
28728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
28738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			vrf_id = SCTP_DEFAULT_VRFID;
28748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
28751b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t		sctp_ifa = sctp_find_ifa_by_addr(&store.sa, vrf_id,
28768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						 SCTP_ADDR_NOT_LOCKED);
28778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_ifa == NULL) {
28788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* address doesn't exist anymore */
28798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			int status;
28808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
28818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* are ASCONFs allowed ? */
28828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if ((sctp_is_feature_on(stcb->sctp_ep,
28838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_PCB_FLAGS_DO_ASCONF)) &&
2884fb3816eaffe5878bb1286adb120fd160da178a05t			    stcb->asoc.asconf_supported) {
28858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* queue an ASCONF DEL_IP_ADDRESS */
28861b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t				status = sctp_asconf_queue_sa_delete(stcb, &store.sa);
28878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/*
28888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * if queued ok, and in correct state, send
28898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * out the ASCONF.
28908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
28918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (status == 0 &&
28928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_GET_STATE(&stcb->asoc) ==
28938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_STATE_OPEN) {
28948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_TIMER_BASED_ASCONF
28958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
28968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 stcb->sctp_ep, stcb,
28978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen							 stcb->asoc.primary_destination);
28988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#else
28998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sctp_send_asconf(stcb, NULL, SCTP_ADDR_NOT_LOCKED);
29008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
29038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexennext_addr:
29068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/*
29078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * Sanity check:  Make sure the length isn't 0, otherwise
29088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 * we'll be stuck in this loop for a long time...
29098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		 */
29108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (SCTP_SIZE32(plen) == 0) {
29118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_PRINTF("process_initack_addrs: bad len (%d) type=%xh\n",
29128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    plen, ptype);
29138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
29148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
29158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* get next parameter */
29168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset += SCTP_SIZE32(plen);
29178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if ((offset + sizeof(struct sctp_paramhdr)) > length)
29188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return;
29198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
29201b77b4778bf4ea247d4e18d1694d8dc2d3d1d150t		    sizeof(struct sctp_paramhdr), (uint8_t *)&tmp_param);
29218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* while */
29228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
29238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/* FIX ME: need to verify return result for v6 address type if v6 disabled */
29258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
29268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * checks to see if a specific address is in the initack address list returns
29278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * 1 if found, 0 if not
29288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
29298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic uint32_t
29300ac02f34d6041cd0018437596a5a9a94685e6919tuexensctp_addr_in_initack(struct mbuf *m, uint32_t offset, uint32_t length, struct sockaddr *sa)
29318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
29328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_paramhdr tmp_param, *ph;
29338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint16_t plen, ptype;
29348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
29358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *sin;
29368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ipv4addr_param *a4p;
2937c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen	struct sctp_ipv6addr_param addr4_store;
29388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
29408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in6 *sin6;
29418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ipv6addr_param *a6p;
2942c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen	struct sctp_ipv6addr_param addr6_store;
29438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_EMBEDDED_V6_SCOPE
29448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in6 sin6_tmp;
29458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (sa->sa_family) {
29498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
29508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
29518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
29528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
29548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
29558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
29568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
29578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	default:
29588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
29598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for ");
29628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
29638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* convert to upper bound */
29648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	length += offset;
29658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
29668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if ((offset + sizeof(struct sctp_paramhdr)) > length) {
29678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
29688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			"find_initack_addr: invalid offset?\n");
29698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
29708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
29718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* go through the addresses in the init-ack */
29728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
29738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	    sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
29748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	while (ph != NULL) {
29758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ptype = ntohs(ph->param_type);
29768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		plen = ntohs(ph->param_length);
29778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		switch (ptype) {
29788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
29798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_IPV6_ADDRESS:
29808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET6) {
29818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get the entire IPv6 address param */
29828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (plen != sizeof(struct sctp_ipv6addr_param)) {
29838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
29848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get the entire IPv6 address param */
29868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				a6p = (struct sctp_ipv6addr_param *)
29878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				      sctp_m_getptr(m, offset,
29888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                    sizeof(struct sctp_ipv6addr_param),
2989c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen				                    (uint8_t *)&addr6_store);
29908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (a6p == NULL) {
29918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (0);
29928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
29938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin6 = (struct sockaddr_in6 *)sa;
29948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef SCTP_EMBEDDED_V6_SCOPE
29958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
29968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* create a copy and clear scope */
29978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					memcpy(&sin6_tmp, sin6,
29988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					       sizeof(struct sockaddr_in6));
29998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					sin6 = &sin6_tmp;
30008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					in6_clearscope(&sin6->sin6_addr);
30018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* SCTP_EMBEDDED_V6_SCOPE */
30038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (memcmp(&sin6->sin6_addr, a6p->addr,
30048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				           sizeof(struct in6_addr)) == 0) {
30058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* found it */
30068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (1);
30078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
30098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
30108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif /* INET6 */
30118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
30128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		case SCTP_IPV4_ADDRESS:
30138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sa->sa_family == AF_INET) {
30148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (plen != sizeof(struct sctp_ipv4addr_param)) {
30158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
30168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* get the entire IPv4 address param */
30188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				a4p = (struct sctp_ipv4addr_param *)
30198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				      sctp_m_getptr(m, offset,
30208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				                    sizeof(struct sctp_ipv4addr_param),
3021c5e505da69d2f4a94b68ccdf8fcbd336110ff77ctuexen				                    (uint8_t *)&addr4_store);
30228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (a4p == NULL) {
30238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (0);
30248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sin = (struct sockaddr_in *)sa;
30268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (sin->sin_addr.s_addr == a4p->addr) {
30278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* found it */
30288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					return (1);
30298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
30308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
30318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
30328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
30338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		default:
30348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			break;
30358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* get next parameter */
30378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		offset += SCTP_SIZE32(plen);
30388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (offset + sizeof(struct sctp_paramhdr) > length) {
30398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			return (0);
30408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ph = (struct sctp_paramhdr *)
30428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
30438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    (uint8_t *) & tmp_param);
30448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* while */
30458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* not found! */
30468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	return (0);
30478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
30488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
30508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * makes sure that the current endpoint local addr list is consistent with
30518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * the new association (eg. subset bound, asconf allowed) adds addresses as
30528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * necessary
30538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
30548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
30558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset,
30568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int length, struct sockaddr *init_addr)
30578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
30588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_laddr *laddr;
30598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* go through the endpoint list */
30618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
30628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* be paranoid and validate the laddr */
30638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (laddr->ifa == NULL) {
30648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1,
30658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				"check_addr_list_ep: laddr->ifa is NULL");
30668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
30678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (laddr->ifa == NULL) {
30698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTPDBG(SCTP_DEBUG_ASCONF1, "check_addr_list_ep: laddr->ifa->ifa_addr is NULL");
30708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
30718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* do i have it implicitly? */
30738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_cmpaddr(&laddr->ifa->address.sa, init_addr)) {
30748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
30758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* check to see if in the init-ack */
30770ac02f34d6041cd0018437596a5a9a94685e6919tuexen		if (!sctp_addr_in_initack(m, offset, length, &laddr->ifa->address.sa)) {
30788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* try to add it */
30798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa,
30808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    SCTP_ADD_IP_ADDRESS, SCTP_ADDR_NOT_LOCKED);
30818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
30828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
30838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
30848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
30858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
30868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * makes sure that the current kernel address list is consistent with the new
30878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * association (with all addrs bound) adds addresses as necessary
30888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
30898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenstatic void
30908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
30918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int length, struct sockaddr *init_addr,
30928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint16_t local_scope, uint16_t site_scope,
30938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint16_t ipv4_scope, uint16_t loopback_scope)
30948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
30958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_vrf *vrf = NULL;
30968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifn *sctp_ifn;
30978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *sctp_ifa;
30988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	uint32_t vrf_id;
30990ac02f34d6041cd0018437596a5a9a94685e6919tuexen#ifdef INET
31000ac02f34d6041cd0018437596a5a9a94685e6919tuexen	struct sockaddr_in *sin;
31010ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif
31020ac02f34d6041cd0018437596a5a9a94685e6919tuexen#ifdef INET6
31030ac02f34d6041cd0018437596a5a9a94685e6919tuexen	struct sockaddr_in6 *sin6;
31040ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif
31058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb) {
31078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		vrf_id = stcb->asoc.vrf_id;
31080ac02f34d6041cd0018437596a5a9a94685e6919tuexen	} else {
31098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
31108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
31118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RLOCK();
31128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vrf = sctp_find_vrf(vrf_id);
31138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (vrf == NULL) {
31148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_IPI_ADDR_RUNLOCK();
31158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
31168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
31178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* go through all our known interfaces */
31188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
31198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
31208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* skip loopback interface */
31218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			continue;
31228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
31238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* go through each interface address */
31248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
31258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* do i have it implicitly? */
31268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) {
31278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
31288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31290ac02f34d6041cd0018437596a5a9a94685e6919tuexen			switch (sctp_ifa->address.sa.sa_family) {
31300ac02f34d6041cd0018437596a5a9a94685e6919tuexen#ifdef INET
31310ac02f34d6041cd0018437596a5a9a94685e6919tuexen			case AF_INET:
3132bfb1bf7e665a02b48026482bf33d05c83dfad73bt				sin = &sctp_ifa->address.sin;
3133998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
3134998635733088fde643e6d807fa76679c4ceeaa00t				if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
3135998635733088fde643e6d807fa76679c4ceeaa00t				                     &sin->sin_addr) != 0) {
3136998635733088fde643e6d807fa76679c4ceeaa00t					continue;
3137998635733088fde643e6d807fa76679c4ceeaa00t				}
3138998635733088fde643e6d807fa76679c4ceeaa00t#endif
31390ac02f34d6041cd0018437596a5a9a94685e6919tuexen				if ((ipv4_scope == 0) &&
31400ac02f34d6041cd0018437596a5a9a94685e6919tuexen				    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
31410ac02f34d6041cd0018437596a5a9a94685e6919tuexen					/* private address not in scope */
31420ac02f34d6041cd0018437596a5a9a94685e6919tuexen					continue;
31430ac02f34d6041cd0018437596a5a9a94685e6919tuexen				}
31440ac02f34d6041cd0018437596a5a9a94685e6919tuexen				break;
31450ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif
31460ac02f34d6041cd0018437596a5a9a94685e6919tuexen#ifdef INET6
31470ac02f34d6041cd0018437596a5a9a94685e6919tuexen			case AF_INET6:
3148bfb1bf7e665a02b48026482bf33d05c83dfad73bt				sin6 = &sctp_ifa->address.sin6;
3149998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
3150998635733088fde643e6d807fa76679c4ceeaa00t				if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
3151998635733088fde643e6d807fa76679c4ceeaa00t				                     &sin6->sin6_addr) != 0) {
3152998635733088fde643e6d807fa76679c4ceeaa00t					continue;
3153998635733088fde643e6d807fa76679c4ceeaa00t				}
3154998635733088fde643e6d807fa76679c4ceeaa00t#endif
31550ac02f34d6041cd0018437596a5a9a94685e6919tuexen				if ((local_scope == 0) &&
31560ac02f34d6041cd0018437596a5a9a94685e6919tuexen				    (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) {
31570ac02f34d6041cd0018437596a5a9a94685e6919tuexen					continue;
31580ac02f34d6041cd0018437596a5a9a94685e6919tuexen				}
31590ac02f34d6041cd0018437596a5a9a94685e6919tuexen				if ((site_scope == 0) &&
31600ac02f34d6041cd0018437596a5a9a94685e6919tuexen				    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
31610ac02f34d6041cd0018437596a5a9a94685e6919tuexen					continue;
31620ac02f34d6041cd0018437596a5a9a94685e6919tuexen				}
31630ac02f34d6041cd0018437596a5a9a94685e6919tuexen				break;
31640ac02f34d6041cd0018437596a5a9a94685e6919tuexen#endif
31650ac02f34d6041cd0018437596a5a9a94685e6919tuexen			default:
31660ac02f34d6041cd0018437596a5a9a94685e6919tuexen				break;
31670ac02f34d6041cd0018437596a5a9a94685e6919tuexen			}
31688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* check to see if in the init-ack */
31690ac02f34d6041cd0018437596a5a9a94685e6919tuexen			if (!sctp_addr_in_initack(m, offset, length, &sctp_ifa->address.sa)) {
31708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* try to add it */
31718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb,
31728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    sctp_ifa, SCTP_ADD_IP_ADDRESS,
31738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				    SCTP_ADDR_LOCKED);
31748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
31758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} /* end foreach ifa */
31768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} /* end foreach ifn */
31778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_IPI_ADDR_RUNLOCK();
31788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
31798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
31818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * validates an init-ack chunk (from a cookie-echo) with current addresses
31828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * adds addresses from the init-ack into our local address list, if needed
31838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * queues asconf adds/deletes addresses as needed and makes appropriate list
31848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * changes for source address selection m, offset: points to the start of the
31858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * address list in an init-ack chunk length: total length of the address
31868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * params only init_addr: address where my INIT-ACK was sent from
31878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
31888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
31898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset,
31908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    int length, struct sockaddr *init_addr,
31918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint16_t local_scope, uint16_t site_scope,
31928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint16_t ipv4_scope, uint16_t loopback_scope)
31938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
31948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* process the local addresses in the initack */
31958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_process_initack_addresses(stcb, m, offset, length);
31968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
31978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
31988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* bound all case */
31998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		sctp_check_address_list_all(stcb, m, offset, length, init_addr,
32008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    local_scope, site_scope, ipv4_scope, loopback_scope);
32018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
32028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* subset bound case */
32038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (sctp_is_feature_on(stcb->sctp_ep,
32048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		    SCTP_PCB_FLAGS_DO_ASCONF)) {
32058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/* asconf's allowed */
32068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_check_address_list_ep(stcb, m, offset, length,
32078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			    init_addr);
32088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
32098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* else, no asconfs allowed, so what we sent is what we get */
32108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
32128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
32138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen/*
32148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen * sctp_bindx() support
32158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen */
32168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenuint32_t
32178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
32188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen    uint32_t type, uint32_t vrf_id, struct sctp_ifa *sctp_ifap)
32198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
32208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *ifa;
32218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_laddr *laddr, *nladdr;
32228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
3223f48c9397d7b9d7cee2e31a28173480bbfe22e6c7t#ifdef HAVE_SA_LEN
32248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sa->sa_len == 0) {
32258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
32268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EINVAL);
32278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
32298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (sctp_ifap) {
32308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ifa = sctp_ifap;
3231e2828360ea9cf8951730d46f5c14626c9425cb30t	} else if (type == SCTP_ADD_IP_ADDRESS) {
32328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* For an add the address MUST be on the system */
32338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
32348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else if (type == SCTP_DEL_IP_ADDRESS) {
32358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* For a delete we need to find it in the inp */
32368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED);
32378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
32388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		ifa = NULL;
32398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
32408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (ifa != NULL) {
32418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (type == SCTP_ADD_IP_ADDRESS) {
32428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_add_local_addr_ep(inp, ifa, type);
32438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else if (type == SCTP_DEL_IP_ADDRESS) {
32448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (inp->laddr_count < 2) {
32458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* can't delete the last local address */
32468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
32478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (EINVAL);
32488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_FOREACH(laddr, &inp->sctp_addr_list,
32508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				     sctp_nxt_addr) {
32518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (ifa == laddr->ifa) {
32528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					/* Mark in the delete */
32538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					laddr->action = type;
32548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
32558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
32578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (LIST_EMPTY(&inp->sctp_asoc_list)) {
32588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			/*
32598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * There is no need to start the iterator if
32608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 * the inp has no associations.
32618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			 */
32628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (type == SCTP_DEL_IP_ADDRESS) {
32638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
32648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (laddr->ifa == ifa) {
32658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						sctp_del_local_addr_ep(inp, ifa);
32668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
32678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
32688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		} else {
32708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_asconf_iterator *asc;
32718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			struct sctp_laddr *wi;
3272000a5bac556b28e74e4e98c540f66b1743e9312dtuexen
32738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
32748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			            sizeof(struct sctp_asconf_iterator),
32758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			            SCTP_M_ASC_IT);
32768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (asc == NULL) {
32778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
32788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (ENOMEM);
32798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr);
32818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (wi == NULL) {
32828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_FREE(asc, SCTP_M_ASC_IT);
32838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
32848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				return (ENOMEM);
32858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
32868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_INIT(&asc->list_of_work);
32878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			asc->cnt = 1;
32888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			SCTP_INCR_LADDR_COUNT();
32898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			wi->ifa = ifa;
32908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			wi->action = type;
32918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			atomic_add_int(&ifa->refcount, 1);
32928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
32938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			(void)sctp_initiate_iterator(sctp_asconf_iterator_ep,
32948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                             sctp_asconf_iterator_stcb,
32958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                             sctp_asconf_iterator_ep_end,
32968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                             SCTP_PCB_ANY_FLAGS,
32978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                             SCTP_PCB_ANY_FEATURES,
32988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                             SCTP_ASOC_ANY_STATE,
32998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                             (void *)asc, 0,
33008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			                             sctp_asconf_iterator_end, inp, 0);
33018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
33028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (0);
33038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
33048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* invalid address! */
33058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL);
33068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return (EADDRNOTAVAIL);
33078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
33098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexenvoid
33118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexensctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
33128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				  struct sctp_nets *net)
33138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen{
33148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_addr *aa;
33158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_ifa *sctp_ifap;
33168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sctp_asconf_tag_param *vtag;
33178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
33188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in *to;
33198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
33208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
33218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	struct sockaddr_in6 *to6;
33228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
33238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (net == NULL) {
33248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n");
33258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
33268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb == NULL) {
33288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing stcb\n");
33298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
33308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen  /* Need to have in the asconf:
33328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen   * - vtagparam(my_vtag/peer_vtag)
33338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen   * - add(0.0.0.0)
33348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen   * - del(0.0.0.0)
33358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen   * - Any global addresses add(addr)
33368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen   */
33378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
33388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	            SCTP_M_ASC_ADDR);
33398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (aa == NULL) {
33408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* didn't get memory */
33418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
33428c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        "sctp_asconf_send_nat_state_update: failed to get memory!\n");
33438c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
33448c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33458c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aa->special_del = 0;
33468c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* fill in asconf address parameter fields */
33478c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* top level elements are "networked" during send */
33488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aa->ifa = NULL;
33498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	aa->sent = 0;		/* clear sent flag */
33508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vtag = (struct sctp_asconf_tag_param *)&aa->ap.aph;
33518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vtag->aph.ph.param_type = SCTP_NAT_VTAGS;
33528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vtag->aph.ph.param_length = sizeof(struct sctp_asconf_tag_param);
33538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vtag->local_vtag = htonl(stcb->asoc.my_vtag);
33548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	vtag->remote_vtag = htonl(stcb->asoc.peer_vtag);
33558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
33568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
33578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
33588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	            SCTP_M_ASC_ADDR);
33598c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (aa == NULL) {
33608c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* didn't get memory */
33618c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
33628c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        "sctp_asconf_send_nat_state_update: failed to get memory!\n");
33638c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
33648c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(aa, 0, sizeof(struct sctp_asconf_addr));
33668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* fill in asconf address parameter fields */
33678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* ADD(0.0.0.0) */
33688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (net->ro._l_addr.sa.sa_family) {
33698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
33708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
33718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
33728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
33738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
33748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv4addr_param);
33758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* No need to add an address, we are using 0.0.0.0 */
33768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
33778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
33788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
33798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
33808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
33818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
33828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
33838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
33848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv6addr_param);
33858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* No need to add an address, we are using 0.0.0.0 */
33868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
33878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
33888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
33898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
33918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	            SCTP_M_ASC_ADDR);
33928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (aa == NULL) {
33938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* didn't get memory */
33948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTPDBG(SCTP_DEBUG_ASCONF1,
33958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		        "sctp_asconf_send_nat_state_update: failed to get memory!\n");
33968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		return;
33978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
33988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	memset(aa, 0, sizeof(struct sctp_asconf_addr));
33998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* fill in asconf address parameter fields */
34008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* ADD(0.0.0.0) */
34018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	switch (net->ro._l_addr.sa.sa_family) {
34028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
34038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET:
34048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
34058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
34068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
34078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv4addr_param);
34088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* No need to add an address, we are using 0.0.0.0 */
34098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
34108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
34118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
34128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
34138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	case AF_INET6:
34148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
34158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
34168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
34178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		aa->ap.addrp.ph.param_length = sizeof (struct sctp_ipv6addr_param);
34188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		/* No need to add an address, we are using 0.0.0.0 */
34198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
34208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		break;
34218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
34228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
34238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now we must hunt the addresses and add all global addresses */
34248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
34258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_vrf *vrf = NULL;
34268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_ifn *sctp_ifnp;
34278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		uint32_t vrf_id;
34288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		vrf_id = stcb->sctp_ep->def_vrf_id;
34308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		vrf = sctp_find_vrf(vrf_id);
34318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		if (vrf == NULL) {
34328c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			goto skip_rest;
34338c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34348c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34358c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_IPI_ADDR_RLOCK();
34368c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
34378c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
34388c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				switch (sctp_ifap->address.sa.sa_family) {
34398c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
34408c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET:
34418c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					to = &sctp_ifap->address.sin;
3442998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
3443998635733088fde643e6d807fa76679c4ceeaa00t					if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
3444998635733088fde643e6d807fa76679c4ceeaa00t					                     &to->sin_addr) != 0) {
3445998635733088fde643e6d807fa76679c4ceeaa00t						continue;
3446998635733088fde643e6d807fa76679c4ceeaa00t					}
3447998635733088fde643e6d807fa76679c4ceeaa00t#endif
34488c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
34498c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
34508c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
34518c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
34528c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
34538c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
34548c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
34558c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
34568c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
34578c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				case AF_INET6:
34588c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					to6 = &sctp_ifap->address.sin6;
3459998635733088fde643e6d807fa76679c4ceeaa00t#if defined(__FreeBSD__)
3460998635733088fde643e6d807fa76679c4ceeaa00t					if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
3461998635733088fde643e6d807fa76679c4ceeaa00t					                     &to6->sin6_addr) != 0) {
3462998635733088fde643e6d807fa76679c4ceeaa00t						continue;
3463998635733088fde643e6d807fa76679c4ceeaa00t					}
3464998635733088fde643e6d807fa76679c4ceeaa00t#endif
34658c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
34668c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
34678c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
34688c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
34698c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen						continue;
34708c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					}
34718c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					break;
34728c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
34738c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				default:
34748c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
34758c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
34768c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
34778c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
34788c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
34798c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		SCTP_IPI_ADDR_RUNLOCK();
34808c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	} else {
34818c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		struct sctp_laddr *laddr;
34828c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen
34838c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
34848c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (laddr->ifa == NULL) {
34858c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
34868c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
34878c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED)
34888c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Address being deleted by the system, dont
34898c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * list.
34908c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
34918c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
34928c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			if (laddr->action == SCTP_DEL_IP_ADDRESS) {
34938c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				/* Address being deleted on this ep
34948c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 * don't list.
34958c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				 */
34968c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
34978c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
34988c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_ifap = laddr->ifa;
34998c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			switch (sctp_ifap->address.sa.sa_family) {
35008c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET
35018c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET:
35028c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				to = &sctp_ifap->address.sin;
35038c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
35048c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
35058c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
35068c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
35078c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
35088c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
35098c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
35108c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
35118c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#ifdef INET6
35128c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			case AF_INET6:
35138c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				to6 = &sctp_ifap->address.sin6;
35148c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
35158c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
35168c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
35178c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
35188c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen					continue;
35198c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				}
35208c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				break;
35218c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen#endif
35228c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			default:
35238c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen				continue;
35248c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			}
35258c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen			sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
35268c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen		}
35278c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	}
35288c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen skip_rest:
35298c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	/* Now we must send the asconf into the queue */
35308c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen	sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
35318c8a4cae58a2deed148551d56cb1ab315a55dbbdtuexen}
3532