sctp_asconf.c revision 218319
1/*-
2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
3 * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved.
4 * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * a) Redistributions of source code must retain the above copyright notice,
10 *   this list of conditions and the following disclaimer.
11 *
12 * b) Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in
14 *   the documentation and/or other materials provided with the distribution.
15 *
16 * c) Neither the name of Cisco Systems, Inc. nor the names of its
17 *    contributors may be used to endorse or promote products derived
18 *    from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/* $KAME: sctp_asconf.c,v 1.24 2005/03/06 16:04:16 itojun Exp $	 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/sys/netinet/sctp_asconf.c 218319 2011-02-05 12:12:51Z rrs $");
37#include <netinet/sctp_os.h>
38#include <netinet/sctp_var.h>
39#include <netinet/sctp_sysctl.h>
40#include <netinet/sctp_pcb.h>
41#include <netinet/sctp_header.h>
42#include <netinet/sctputil.h>
43#include <netinet/sctp_output.h>
44#include <netinet/sctp_asconf.h>
45#include <netinet/sctp_timer.h>
46
47/*
48 * debug flags:
49 * SCTP_DEBUG_ASCONF1: protocol info, general info and errors
50 * SCTP_DEBUG_ASCONF2: detailed info
51 */
52#ifdef SCTP_DEBUG
53#endif				/* SCTP_DEBUG */
54
55
56static void
57sctp_asconf_get_source_ip(struct mbuf *m, struct sockaddr *sa)
58{
59	struct ip *iph;
60	struct sockaddr_in *sin;
61
62#ifdef INET6
63	struct sockaddr_in6 *sin6;
64
65#endif
66
67	iph = mtod(m, struct ip *);
68	if (iph->ip_v == IPVERSION) {
69		/* IPv4 source */
70		sin = (struct sockaddr_in *)sa;
71		bzero(sin, sizeof(*sin));
72		sin->sin_family = AF_INET;
73		sin->sin_len = sizeof(struct sockaddr_in);
74		sin->sin_port = 0;
75		sin->sin_addr.s_addr = iph->ip_src.s_addr;
76		return;
77	}
78#ifdef INET6
79	else if (iph->ip_v == (IPV6_VERSION >> 4)) {
80		/* IPv6 source */
81		struct ip6_hdr *ip6;
82
83		sin6 = (struct sockaddr_in6 *)sa;
84		bzero(sin6, sizeof(*sin6));
85		sin6->sin6_family = AF_INET6;
86		sin6->sin6_len = sizeof(struct sockaddr_in6);
87		sin6->sin6_port = 0;
88		ip6 = mtod(m, struct ip6_hdr *);
89		sin6->sin6_addr = ip6->ip6_src;
90		return;
91	}
92#endif				/* INET6 */
93	else
94		return;
95}
96
97/*
98 * draft-ietf-tsvwg-addip-sctp
99 *
100 * An ASCONF parameter queue exists per asoc which holds the pending address
101 * operations.  Lists are updated upon receipt of ASCONF-ACK.
102 *
103 * A restricted_addrs list exists per assoc to hold local addresses that are
104 * not (yet) usable by the assoc as a source address.  These addresses are
105 * either pending an ASCONF operation (and exist on the ASCONF parameter
106 * queue), or they are permanently restricted (the peer has returned an
107 * ERROR indication to an ASCONF(ADD), or the peer does not support ASCONF).
108 *
109 * Deleted addresses are always immediately removed from the lists as they will
110 * (shortly) no longer exist in the kernel.  We send ASCONFs as a courtesy,
111 * only if allowed.
112 */
113
114/*
115 * ASCONF parameter processing.
116 * response_required: set if a reply is required (eg. SUCCESS_REPORT).
117 * returns a mbuf to an "error" response parameter or NULL/"success" if ok.
118 * FIX: allocating this many mbufs on the fly is pretty inefficient...
119 */
120static struct mbuf *
121sctp_asconf_success_response(uint32_t id)
122{
123	struct mbuf *m_reply = NULL;
124	struct sctp_asconf_paramhdr *aph;
125
126	m_reply = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_paramhdr),
127	    0, M_DONTWAIT, 1, MT_DATA);
128	if (m_reply == NULL) {
129		SCTPDBG(SCTP_DEBUG_ASCONF1,
130		    "asconf_success_response: couldn't get mbuf!\n");
131		return NULL;
132	}
133	aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
134	aph->correlation_id = id;
135	aph->ph.param_type = htons(SCTP_SUCCESS_REPORT);
136	aph->ph.param_length = sizeof(struct sctp_asconf_paramhdr);
137	SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
138	aph->ph.param_length = htons(aph->ph.param_length);
139
140	return m_reply;
141}
142
143static struct mbuf *
144sctp_asconf_error_response(uint32_t id, uint16_t cause, uint8_t * error_tlv,
145    uint16_t tlv_length)
146{
147	struct mbuf *m_reply = NULL;
148	struct sctp_asconf_paramhdr *aph;
149	struct sctp_error_cause *error;
150	uint8_t *tlv;
151
152	m_reply = sctp_get_mbuf_for_msg((sizeof(struct sctp_asconf_paramhdr) +
153	    tlv_length +
154	    sizeof(struct sctp_error_cause)),
155	    0, M_DONTWAIT, 1, MT_DATA);
156	if (m_reply == NULL) {
157		SCTPDBG(SCTP_DEBUG_ASCONF1,
158		    "asconf_error_response: couldn't get mbuf!\n");
159		return NULL;
160	}
161	aph = mtod(m_reply, struct sctp_asconf_paramhdr *);
162	error = (struct sctp_error_cause *)(aph + 1);
163
164	aph->correlation_id = id;
165	aph->ph.param_type = htons(SCTP_ERROR_CAUSE_IND);
166	error->code = htons(cause);
167	error->length = tlv_length + sizeof(struct sctp_error_cause);
168	aph->ph.param_length = error->length +
169	    sizeof(struct sctp_asconf_paramhdr);
170
171	if (aph->ph.param_length > MLEN) {
172		SCTPDBG(SCTP_DEBUG_ASCONF1,
173		    "asconf_error_response: tlv_length (%xh) too big\n",
174		    tlv_length);
175		sctp_m_freem(m_reply);	/* discard */
176		return NULL;
177	}
178	if (error_tlv != NULL) {
179		tlv = (uint8_t *) (error + 1);
180		memcpy(tlv, error_tlv, tlv_length);
181	}
182	SCTP_BUF_LEN(m_reply) = aph->ph.param_length;
183	error->length = htons(error->length);
184	aph->ph.param_length = htons(aph->ph.param_length);
185
186	return m_reply;
187}
188
189static struct mbuf *
190sctp_process_asconf_add_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
191    struct sctp_tcb *stcb, int response_required)
192{
193	struct mbuf *m_reply = NULL;
194	struct sockaddr_storage sa_source, sa_store;
195	struct sctp_ipv4addr_param *v4addr;
196	uint16_t param_type, param_length, aparam_length;
197	struct sockaddr *sa;
198	struct sockaddr_in *sin;
199	int zero_address = 0;
200
201#ifdef INET6
202	struct sockaddr_in6 *sin6;
203	struct sctp_ipv6addr_param *v6addr;
204
205#endif				/* INET6 */
206
207	aparam_length = ntohs(aph->ph.param_length);
208	v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
209#ifdef INET6
210	v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
211#endif				/* INET6 */
212	param_type = ntohs(v4addr->ph.param_type);
213	param_length = ntohs(v4addr->ph.param_length);
214
215	sa = (struct sockaddr *)&sa_store;
216	switch (param_type) {
217	case SCTP_IPV4_ADDRESS:
218		if (param_length != sizeof(struct sctp_ipv4addr_param)) {
219			/* invalid param size */
220			return NULL;
221		}
222		sin = (struct sockaddr_in *)&sa_store;
223		bzero(sin, sizeof(*sin));
224		sin->sin_family = AF_INET;
225		sin->sin_len = sizeof(struct sockaddr_in);
226		sin->sin_port = stcb->rport;
227		sin->sin_addr.s_addr = v4addr->addr;
228		if (sin->sin_addr.s_addr == INADDR_ANY)
229			zero_address = 1;
230		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
231		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
232		break;
233	case SCTP_IPV6_ADDRESS:
234#ifdef INET6
235		if (param_length != sizeof(struct sctp_ipv6addr_param)) {
236			/* invalid param size */
237			return NULL;
238		}
239		sin6 = (struct sockaddr_in6 *)&sa_store;
240		bzero(sin6, sizeof(*sin6));
241		sin6->sin6_family = AF_INET6;
242		sin6->sin6_len = sizeof(struct sockaddr_in6);
243		sin6->sin6_port = stcb->rport;
244		memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
245		    sizeof(struct in6_addr));
246		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
247			zero_address = 1;
248		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_add_ip: adding ");
249		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
250#else
251		/* IPv6 not enabled! */
252		/* FIX ME: currently sends back an invalid param error */
253		m_reply = sctp_asconf_error_response(aph->correlation_id,
254		    SCTP_CAUSE_INVALID_PARAM, (uint8_t *) aph, aparam_length);
255		SCTPDBG(SCTP_DEBUG_ASCONF1,
256		    "process_asconf_add_ip: v6 disabled- skipping ");
257		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
258		return m_reply;
259#endif
260		break;
261	default:
262		m_reply = sctp_asconf_error_response(aph->correlation_id,
263		    SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
264		    aparam_length);
265		return m_reply;
266	}			/* end switch */
267
268	/* if 0.0.0.0/::0, add the source address instead */
269	if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
270		sa = (struct sockaddr *)&sa_source;
271		sctp_asconf_get_source_ip(m, sa);
272		SCTPDBG(SCTP_DEBUG_ASCONF1,
273		    "process_asconf_add_ip: using source addr ");
274		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
275	}
276	/* add the address */
277	if (sctp_add_remote_addr(stcb, sa, SCTP_DONOT_SETSCOPE,
278	    SCTP_ADDR_DYNAMIC_ADDED) != 0) {
279		SCTPDBG(SCTP_DEBUG_ASCONF1,
280		    "process_asconf_add_ip: error adding address\n");
281		m_reply = sctp_asconf_error_response(aph->correlation_id,
282		    SCTP_CAUSE_RESOURCE_SHORTAGE, (uint8_t *) aph,
283		    aparam_length);
284	} else {
285		/* notify upper layer */
286		sctp_ulp_notify(SCTP_NOTIFY_ASCONF_ADD_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
287		if (response_required) {
288			m_reply =
289			    sctp_asconf_success_response(aph->correlation_id);
290		}
291		sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb,
292		    NULL, SCTP_FROM_SCTP_ASCONF + SCTP_LOC_1);
293		sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
294		    stcb, NULL);
295	}
296
297	return m_reply;
298}
299
300static int
301sctp_asconf_del_remote_addrs_except(struct sctp_tcb *stcb, struct sockaddr *src)
302{
303	struct sctp_nets *src_net, *net;
304
305	/* make sure the source address exists as a destination net */
306	src_net = sctp_findnet(stcb, src);
307	if (src_net == NULL) {
308		/* not found */
309		return -1;
310	}
311	/* delete all destination addresses except the source */
312	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
313		if (net != src_net) {
314			/* delete this address */
315			sctp_remove_net(stcb, net);
316			SCTPDBG(SCTP_DEBUG_ASCONF1,
317			    "asconf_del_remote_addrs_except: deleting ");
318			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1,
319			    (struct sockaddr *)&net->ro._l_addr);
320			/* notify upper layer */
321			sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0,
322			    (struct sockaddr *)&net->ro._l_addr, SCTP_SO_NOT_LOCKED);
323		}
324	}
325	return 0;
326}
327
328static struct mbuf *
329sctp_process_asconf_delete_ip(struct mbuf *m, struct sctp_asconf_paramhdr *aph,
330    struct sctp_tcb *stcb, int response_required)
331{
332	struct mbuf *m_reply = NULL;
333	struct sockaddr_storage sa_source, sa_store;
334	struct sctp_ipv4addr_param *v4addr;
335	uint16_t param_type, param_length, aparam_length;
336	struct sockaddr *sa;
337	struct sockaddr_in *sin;
338	int zero_address = 0;
339	int result;
340
341#ifdef INET6
342	struct sockaddr_in6 *sin6;
343	struct sctp_ipv6addr_param *v6addr;
344
345#endif				/* INET6 */
346
347	/* get the source IP address for src and 0.0.0.0/::0 delete checks */
348	sctp_asconf_get_source_ip(m, (struct sockaddr *)&sa_source);
349
350	aparam_length = ntohs(aph->ph.param_length);
351	v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
352#ifdef INET6
353	v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
354#endif				/* INET6 */
355	param_type = ntohs(v4addr->ph.param_type);
356	param_length = ntohs(v4addr->ph.param_length);
357
358	sa = (struct sockaddr *)&sa_store;
359	switch (param_type) {
360	case SCTP_IPV4_ADDRESS:
361		if (param_length != sizeof(struct sctp_ipv4addr_param)) {
362			/* invalid param size */
363			return NULL;
364		}
365		sin = (struct sockaddr_in *)&sa_store;
366		bzero(sin, sizeof(*sin));
367		sin->sin_family = AF_INET;
368		sin->sin_len = sizeof(struct sockaddr_in);
369		sin->sin_port = stcb->rport;
370		sin->sin_addr.s_addr = v4addr->addr;
371		if (sin->sin_addr.s_addr == INADDR_ANY)
372			zero_address = 1;
373		SCTPDBG(SCTP_DEBUG_ASCONF1,
374		    "process_asconf_delete_ip: deleting ");
375		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
376		break;
377	case SCTP_IPV6_ADDRESS:
378		if (param_length != sizeof(struct sctp_ipv6addr_param)) {
379			/* invalid param size */
380			return NULL;
381		}
382#ifdef INET6
383		sin6 = (struct sockaddr_in6 *)&sa_store;
384		bzero(sin6, sizeof(*sin6));
385		sin6->sin6_family = AF_INET6;
386		sin6->sin6_len = sizeof(struct sockaddr_in6);
387		sin6->sin6_port = stcb->rport;
388		memcpy(&sin6->sin6_addr, v6addr->addr,
389		    sizeof(struct in6_addr));
390		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
391			zero_address = 1;
392		SCTPDBG(SCTP_DEBUG_ASCONF1,
393		    "process_asconf_delete_ip: deleting ");
394		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
395#else
396		/* IPv6 not enabled!  No "action" needed; just ack it */
397		SCTPDBG(SCTP_DEBUG_ASCONF1,
398		    "process_asconf_delete_ip: v6 disabled- ignoring: ");
399		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
400		/* just respond with a "success" ASCONF-ACK */
401		return NULL;
402#endif
403		break;
404	default:
405		m_reply = sctp_asconf_error_response(aph->correlation_id,
406		    SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
407		    aparam_length);
408		return m_reply;
409	}
410
411	/* make sure the source address is not being deleted */
412	if (sctp_cmpaddr(sa, (struct sockaddr *)&sa_source)) {
413		/* trying to delete the source address! */
414		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete source addr\n");
415		m_reply = sctp_asconf_error_response(aph->correlation_id,
416		    SCTP_CAUSE_DELETING_SRC_ADDR, (uint8_t *) aph,
417		    aparam_length);
418		return m_reply;
419	}
420	/* if deleting 0.0.0.0/::0, delete all addresses except src addr */
421	if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
422		result = sctp_asconf_del_remote_addrs_except(stcb,
423		    (struct sockaddr *)&sa_source);
424
425		if (result) {
426			/* src address did not exist? */
427			SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: src addr does not exist?\n");
428			/* what error to reply with?? */
429			m_reply =
430			    sctp_asconf_error_response(aph->correlation_id,
431			    SCTP_CAUSE_REQUEST_REFUSED, (uint8_t *) aph,
432			    aparam_length);
433		} else if (response_required) {
434			m_reply =
435			    sctp_asconf_success_response(aph->correlation_id);
436		}
437		return m_reply;
438	}
439	/* delete the address */
440	result = sctp_del_remote_addr(stcb, sa);
441	/*
442	 * note if result == -2, the address doesn't exist in the asoc but
443	 * since it's being deleted anyways, we just ack the delete -- but
444	 * this probably means something has already gone awry
445	 */
446	if (result == -1) {
447		/* only one address in the asoc */
448		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_delete_ip: tried to delete last IP addr!\n");
449		m_reply = sctp_asconf_error_response(aph->correlation_id,
450		    SCTP_CAUSE_DELETING_LAST_ADDR, (uint8_t *) aph,
451		    aparam_length);
452	} else {
453		if (response_required) {
454			m_reply = sctp_asconf_success_response(aph->correlation_id);
455		}
456		/* notify upper layer */
457		sctp_ulp_notify(SCTP_NOTIFY_ASCONF_DELETE_IP, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
458	}
459	return m_reply;
460}
461
462static struct mbuf *
463sctp_process_asconf_set_primary(struct mbuf *m,
464    struct sctp_asconf_paramhdr *aph,
465    struct sctp_tcb *stcb, int response_required)
466{
467	struct mbuf *m_reply = NULL;
468	struct sockaddr_storage sa_source, sa_store;
469	struct sctp_ipv4addr_param *v4addr;
470	uint16_t param_type, param_length, aparam_length;
471	struct sockaddr *sa;
472	struct sockaddr_in *sin;
473	int zero_address = 0;
474
475#ifdef INET6
476	struct sockaddr_in6 *sin6;
477	struct sctp_ipv6addr_param *v6addr;
478
479#endif				/* INET6 */
480
481	aparam_length = ntohs(aph->ph.param_length);
482	v4addr = (struct sctp_ipv4addr_param *)(aph + 1);
483#ifdef INET6
484	v6addr = (struct sctp_ipv6addr_param *)(aph + 1);
485#endif				/* INET6 */
486	param_type = ntohs(v4addr->ph.param_type);
487	param_length = ntohs(v4addr->ph.param_length);
488
489	sa = (struct sockaddr *)&sa_store;
490	switch (param_type) {
491	case SCTP_IPV4_ADDRESS:
492		if (param_length != sizeof(struct sctp_ipv4addr_param)) {
493			/* invalid param size */
494			return NULL;
495		}
496		sin = (struct sockaddr_in *)&sa_store;
497		bzero(sin, sizeof(*sin));
498		sin->sin_family = AF_INET;
499		sin->sin_len = sizeof(struct sockaddr_in);
500		sin->sin_addr.s_addr = v4addr->addr;
501		if (sin->sin_addr.s_addr == INADDR_ANY)
502			zero_address = 1;
503		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: ");
504		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
505		break;
506	case SCTP_IPV6_ADDRESS:
507		if (param_length != sizeof(struct sctp_ipv6addr_param)) {
508			/* invalid param size */
509			return NULL;
510		}
511#ifdef INET6
512		sin6 = (struct sockaddr_in6 *)&sa_store;
513		bzero(sin6, sizeof(*sin6));
514		sin6->sin6_family = AF_INET6;
515		sin6->sin6_len = sizeof(struct sockaddr_in6);
516		memcpy((caddr_t)&sin6->sin6_addr, v6addr->addr,
517		    sizeof(struct in6_addr));
518		if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
519			zero_address = 1;
520		SCTPDBG(SCTP_DEBUG_ASCONF1, "process_asconf_set_primary: ");
521		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
522#else
523		/* IPv6 not enabled!  No "action" needed; just ack it */
524		SCTPDBG(SCTP_DEBUG_ASCONF1,
525		    "process_asconf_set_primary: v6 disabled- ignoring: ");
526		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
527		/* just respond with a "success" ASCONF-ACK */
528		return NULL;
529#endif
530		break;
531	default:
532		m_reply = sctp_asconf_error_response(aph->correlation_id,
533		    SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
534		    aparam_length);
535		return m_reply;
536	}
537
538	/* if 0.0.0.0/::0, use the source address instead */
539	if (zero_address && SCTP_BASE_SYSCTL(sctp_nat_friendly)) {
540		sa = (struct sockaddr *)&sa_source;
541		sctp_asconf_get_source_ip(m, sa);
542		SCTPDBG(SCTP_DEBUG_ASCONF1,
543		    "process_asconf_set_primary: using source addr ");
544		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
545	}
546	/* set the primary address */
547	if (sctp_set_primary_addr(stcb, sa, NULL) == 0) {
548		SCTPDBG(SCTP_DEBUG_ASCONF1,
549		    "process_asconf_set_primary: primary address set\n");
550		/* notify upper layer */
551		sctp_ulp_notify(SCTP_NOTIFY_ASCONF_SET_PRIMARY, stcb, 0, sa, SCTP_SO_NOT_LOCKED);
552
553		if (response_required) {
554			m_reply = sctp_asconf_success_response(aph->correlation_id);
555		}
556		/*
557		 * Mobility adaptation. Ideally, when the reception of SET
558		 * PRIMARY with DELETE IP ADDRESS of the previous primary
559		 * destination, unacknowledged DATA are retransmitted
560		 * immediately to the new primary destination for seamless
561		 * handover. If the destination is UNCONFIRMED and marked to
562		 * REQ_PRIM, The retransmission occur when reception of the
563		 * HEARTBEAT-ACK.  (See sctp_handle_heartbeat_ack in
564		 * sctp_input.c) Also, when change of the primary
565		 * destination, it is better that all subsequent new DATA
566		 * containing already queued DATA are transmitted to the new
567		 * primary destination. (by micchie)
568		 */
569		if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
570		    SCTP_MOBILITY_BASE) ||
571		    sctp_is_mobility_feature_on(stcb->sctp_ep,
572		    SCTP_MOBILITY_FASTHANDOFF)) &&
573		    sctp_is_mobility_feature_on(stcb->sctp_ep,
574		    SCTP_MOBILITY_PRIM_DELETED) &&
575		    (stcb->asoc.primary_destination->dest_state &
576		    SCTP_ADDR_UNCONFIRMED) == 0) {
577
578			sctp_timer_stop(SCTP_TIMER_TYPE_PRIM_DELETED, stcb->sctp_ep, stcb, NULL, SCTP_FROM_SCTP_TIMER + SCTP_LOC_7);
579			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
580			    SCTP_MOBILITY_FASTHANDOFF)) {
581				sctp_assoc_immediate_retrans(stcb,
582				    stcb->asoc.primary_destination);
583			}
584			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
585			    SCTP_MOBILITY_BASE)) {
586				sctp_move_chunks_from_net(stcb,
587				    stcb->asoc.deleted_primary);
588			}
589			sctp_delete_prim_timer(stcb->sctp_ep, stcb,
590			    stcb->asoc.deleted_primary);
591		}
592	} else {
593		/* couldn't set the requested primary address! */
594		SCTPDBG(SCTP_DEBUG_ASCONF1,
595		    "process_asconf_set_primary: set primary failed!\n");
596		/* must have been an invalid address, so report */
597		m_reply = sctp_asconf_error_response(aph->correlation_id,
598		    SCTP_CAUSE_UNRESOLVABLE_ADDR, (uint8_t *) aph,
599		    aparam_length);
600	}
601
602	return m_reply;
603}
604
605/*
606 * handles an ASCONF chunk.
607 * if all parameters are processed ok, send a plain (empty) ASCONF-ACK
608 */
609void
610sctp_handle_asconf(struct mbuf *m, unsigned int offset,
611    struct sctp_asconf_chunk *cp, struct sctp_tcb *stcb,
612    int first)
613{
614	struct sctp_association *asoc;
615	uint32_t serial_num;
616	struct mbuf *n, *m_ack, *m_result, *m_tail;
617	struct sctp_asconf_ack_chunk *ack_cp;
618	struct sctp_asconf_paramhdr *aph, *ack_aph;
619	struct sctp_ipv6addr_param *p_addr;
620	unsigned int asconf_limit;
621	int error = 0;		/* did an error occur? */
622
623	/* asconf param buffer */
624	uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
625	struct sctp_asconf_ack *ack, *ack_next;
626
627	/* verify minimum length */
628	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_chunk)) {
629		SCTPDBG(SCTP_DEBUG_ASCONF1,
630		    "handle_asconf: chunk too small = %xh\n",
631		    ntohs(cp->ch.chunk_length));
632		return;
633	}
634	asoc = &stcb->asoc;
635	serial_num = ntohl(cp->serial_number);
636
637	if (SCTP_TSN_GE(asoc->asconf_seq_in, serial_num)) {
638		/* got a duplicate ASCONF */
639		SCTPDBG(SCTP_DEBUG_ASCONF1,
640		    "handle_asconf: got duplicate serial number = %xh\n",
641		    serial_num);
642		return;
643	} else if (serial_num != (asoc->asconf_seq_in + 1)) {
644		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: incorrect serial number = %xh (expected next = %xh)\n",
645		    serial_num, asoc->asconf_seq_in + 1);
646		return;
647	}
648	/* it's the expected "next" sequence number, so process it */
649	asoc->asconf_seq_in = serial_num;	/* update sequence */
650	/* get length of all the param's in the ASCONF */
651	asconf_limit = offset + ntohs(cp->ch.chunk_length);
652	SCTPDBG(SCTP_DEBUG_ASCONF1,
653	    "handle_asconf: asconf_limit=%u, sequence=%xh\n",
654	    asconf_limit, serial_num);
655
656	if (first) {
657		/* delete old cache */
658		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: Now processing firstASCONF. Try to delte old cache\n");
659
660		TAILQ_FOREACH_SAFE(ack, &asoc->asconf_ack_sent, next, ack_next) {
661			if (ack->serial_number == serial_num)
662				break;
663			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: delete old(%u) < first(%u)\n",
664			    ack->serial_number, serial_num);
665			TAILQ_REMOVE(&asoc->asconf_ack_sent, ack, next);
666			if (ack->data != NULL) {
667				sctp_m_freem(ack->data);
668			}
669			SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asconf_ack), ack);
670		}
671	}
672	m_ack = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_ack_chunk), 0,
673	    M_DONTWAIT, 1, MT_DATA);
674	if (m_ack == NULL) {
675		SCTPDBG(SCTP_DEBUG_ASCONF1,
676		    "handle_asconf: couldn't get mbuf!\n");
677		return;
678	}
679	m_tail = m_ack;		/* current reply chain's tail */
680
681	/* fill in ASCONF-ACK header */
682	ack_cp = mtod(m_ack, struct sctp_asconf_ack_chunk *);
683	ack_cp->ch.chunk_type = SCTP_ASCONF_ACK;
684	ack_cp->ch.chunk_flags = 0;
685	ack_cp->serial_number = htonl(serial_num);
686	/* set initial lengths (eg. just an ASCONF-ACK), ntohx at the end! */
687	SCTP_BUF_LEN(m_ack) = sizeof(struct sctp_asconf_ack_chunk);
688	ack_cp->ch.chunk_length = sizeof(struct sctp_asconf_ack_chunk);
689
690	/* skip the lookup address parameter */
691	offset += sizeof(struct sctp_asconf_chunk);
692	p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr), (uint8_t *) & aparam_buf);
693	if (p_addr == NULL) {
694		SCTPDBG(SCTP_DEBUG_ASCONF1,
695		    "handle_asconf: couldn't get lookup addr!\n");
696		/* respond with a missing/invalid mandatory parameter error */
697		return;
698	}
699	/* param_length is already validated in process_control... */
700	offset += ntohs(p_addr->ph.param_length);	/* skip lookup addr */
701
702	/* get pointer to first asconf param in ASCONF-ACK */
703	ack_aph = (struct sctp_asconf_paramhdr *)(mtod(m_ack, caddr_t)+sizeof(struct sctp_asconf_ack_chunk));
704	if (ack_aph == NULL) {
705		SCTPDBG(SCTP_DEBUG_ASCONF1, "Gak in asconf2\n");
706		return;
707	}
708	/* get pointer to first asconf param in ASCONF */
709	aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, sizeof(struct sctp_asconf_paramhdr), (uint8_t *) & aparam_buf);
710	if (aph == NULL) {
711		SCTPDBG(SCTP_DEBUG_ASCONF1, "Empty ASCONF received?\n");
712		goto send_reply;
713	}
714	/* process through all parameters */
715	while (aph != NULL) {
716		unsigned int param_length, param_type;
717
718		param_type = ntohs(aph->ph.param_type);
719		param_length = ntohs(aph->ph.param_length);
720		if (offset + param_length > asconf_limit) {
721			/* parameter goes beyond end of chunk! */
722			sctp_m_freem(m_ack);
723			return;
724		}
725		m_result = NULL;
726
727		if (param_length > sizeof(aparam_buf)) {
728			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) larger than buffer size!\n", param_length);
729			sctp_m_freem(m_ack);
730			return;
731		}
732		if (param_length <= sizeof(struct sctp_paramhdr)) {
733			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: param length (%u) too short\n", param_length);
734			sctp_m_freem(m_ack);
735		}
736		/* get the entire parameter */
737		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
738		if (aph == NULL) {
739			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: couldn't get entire param\n");
740			sctp_m_freem(m_ack);
741			return;
742		}
743		switch (param_type) {
744		case SCTP_ADD_IP_ADDRESS:
745			asoc->peer_supports_asconf = 1;
746			m_result = sctp_process_asconf_add_ip(m, aph, stcb,
747			    error);
748			break;
749		case SCTP_DEL_IP_ADDRESS:
750			asoc->peer_supports_asconf = 1;
751			m_result = sctp_process_asconf_delete_ip(m, aph, stcb,
752			    error);
753			break;
754		case SCTP_ERROR_CAUSE_IND:
755			/* not valid in an ASCONF chunk */
756			break;
757		case SCTP_SET_PRIM_ADDR:
758			asoc->peer_supports_asconf = 1;
759			m_result = sctp_process_asconf_set_primary(m, aph,
760			    stcb, error);
761			break;
762		case SCTP_NAT_VTAGS:
763			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: sees a NAT VTAG state parameter\n");
764			break;
765		case SCTP_SUCCESS_REPORT:
766			/* not valid in an ASCONF chunk */
767			break;
768		case SCTP_ULP_ADAPTATION:
769			/* FIX */
770			break;
771		default:
772			if ((param_type & 0x8000) == 0) {
773				/* Been told to STOP at this param */
774				asconf_limit = offset;
775				/*
776				 * FIX FIX - We need to call
777				 * sctp_arethere_unrecognized_parameters()
778				 * to get a operr and send it for any
779				 * param's with the 0x4000 bit set OR do it
780				 * here ourselves... note we still must STOP
781				 * if the 0x8000 bit is clear.
782				 */
783			}
784			/* unknown/invalid param type */
785			break;
786		}		/* switch */
787
788		/* add any (error) result to the reply mbuf chain */
789		if (m_result != NULL) {
790			SCTP_BUF_NEXT(m_tail) = m_result;
791			m_tail = m_result;
792			/* update lengths, make sure it's aligned too */
793			SCTP_BUF_LEN(m_result) = SCTP_SIZE32(SCTP_BUF_LEN(m_result));
794			ack_cp->ch.chunk_length += SCTP_BUF_LEN(m_result);
795			/* set flag to force success reports */
796			error = 1;
797		}
798		offset += SCTP_SIZE32(param_length);
799		/* update remaining ASCONF message length to process */
800		if (offset >= asconf_limit) {
801			/* no more data in the mbuf chain */
802			break;
803		}
804		/* get pointer to next asconf param */
805		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
806		    sizeof(struct sctp_asconf_paramhdr),
807		    (uint8_t *) & aparam_buf);
808		if (aph == NULL) {
809			/* can't get an asconf paramhdr */
810			SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: can't get asconf param hdr!\n");
811			/* FIX ME - add error here... */
812		}
813	}
814
815send_reply:
816	ack_cp->ch.chunk_length = htons(ack_cp->ch.chunk_length);
817	/* save the ASCONF-ACK reply */
818	ack = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_asconf_ack),
819	    struct sctp_asconf_ack);
820	if (ack == NULL) {
821		sctp_m_freem(m_ack);
822		return;
823	}
824	ack->serial_number = serial_num;
825	ack->last_sent_to = NULL;
826	ack->data = m_ack;
827	ack->len = 0;
828	n = m_ack;
829	while (n) {
830		ack->len += SCTP_BUF_LEN(n);
831		n = SCTP_BUF_NEXT(n);
832	}
833	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_ack_sent, ack, next);
834
835	/* see if last_control_chunk_from is set properly (use IP src addr) */
836	if (stcb->asoc.last_control_chunk_from == NULL) {
837		/*
838		 * this could happen if the source address was just newly
839		 * added
840		 */
841		struct ip *iph;
842		struct sctphdr *sh;
843		struct sockaddr_storage from_store;
844		struct sockaddr *from = (struct sockaddr *)&from_store;
845
846		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: looking up net for IP source address\n");
847		/* pullup already done, IP options already stripped */
848		iph = mtod(m, struct ip *);
849		sh = (struct sctphdr *)((caddr_t)iph + sizeof(*iph));
850		switch (iph->ip_v) {
851		case IPVERSION:
852			{
853				struct sockaddr_in *from4;
854
855				from4 = (struct sockaddr_in *)&from_store;
856				bzero(from4, sizeof(*from4));
857				from4->sin_family = AF_INET;
858				from4->sin_len = sizeof(struct sockaddr_in);
859				from4->sin_addr.s_addr = iph->ip_src.s_addr;
860				from4->sin_port = sh->src_port;
861				break;
862			}
863#ifdef INET6
864		case IPV6_VERSION >> 4:
865			{
866				struct ip6_hdr *ip6;
867				struct sockaddr_in6 *from6;
868
869				ip6 = mtod(m, struct ip6_hdr *);
870				from6 = (struct sockaddr_in6 *)&from_store;
871				bzero(from6, sizeof(*from6));
872				from6->sin6_family = AF_INET6;
873				from6->sin6_len = sizeof(struct sockaddr_in6);
874				from6->sin6_addr = ip6->ip6_src;
875				from6->sin6_port = sh->src_port;
876				/*
877				 * Get the scopes in properly to the sin6
878				 * addr's
879				 */
880				/* we probably don't need these operations */
881				(void)sa6_recoverscope(from6);
882				sa6_embedscope(from6,
883				    MODULE_GLOBAL(ip6_use_defzone));
884
885				break;
886			}
887#endif
888		default:
889			/* unknown address type */
890			from = NULL;
891		}
892		if (from != NULL) {
893			SCTPDBG(SCTP_DEBUG_ASCONF1, "Looking for IP source: ");
894			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, from);
895			/* look up the from address */
896			stcb->asoc.last_control_chunk_from = sctp_findnet(stcb, from);
897#ifdef SCTP_DEBUG
898			if (stcb->asoc.last_control_chunk_from == NULL)
899				SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf: IP source address not found?!\n");
900#endif
901		}
902	}
903}
904
905/*
906 * does the address match? returns 0 if not, 1 if so
907 */
908static uint32_t
909sctp_asconf_addr_match(struct sctp_asconf_addr *aa, struct sockaddr *sa)
910{
911#ifdef INET6
912	if (sa->sa_family == AF_INET6) {
913		/* IPv6 sa address */
914		/* XXX scopeid */
915		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
916
917		if ((aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) &&
918		    (memcmp(&aa->ap.addrp.addr, &sin6->sin6_addr,
919		    sizeof(struct in6_addr)) == 0)) {
920			return (1);
921		}
922	} else
923#endif				/* INET6 */
924	if (sa->sa_family == AF_INET) {
925		/* IPv4 sa address */
926		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
927
928		if ((aa->ap.addrp.ph.param_type == SCTP_IPV4_ADDRESS) &&
929		    (memcmp(&aa->ap.addrp.addr, &sin->sin_addr,
930		    sizeof(struct in_addr)) == 0)) {
931			return (1);
932		}
933	}
934	return (0);
935}
936
937/*
938 * does the address match? returns 0 if not, 1 if so
939 */
940static uint32_t
941sctp_addr_match(
942    struct sctp_ipv6addr_param *v6addr,
943    struct sockaddr *sa)
944{
945	uint16_t param_type, param_length;
946	struct sctp_ipv4addr_param *v4addr = (struct sctp_ipv4addr_param *)v6addr;
947
948#ifdef INET6
949	if (sa->sa_family == AF_INET6) {
950		/* IPv6 sa address */
951		/* XXX scopeid */
952		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
953
954		param_type = ntohs(v6addr->ph.param_type);
955		param_length = ntohs(v6addr->ph.param_length);
956
957		if ((param_type == SCTP_IPV6_ADDRESS) &&
958		    param_length == sizeof(struct sctp_ipv6addr_param) &&
959		    (memcmp(&v6addr->addr, &sin6->sin6_addr,
960		    sizeof(struct in6_addr)) == 0)) {
961			return (1);
962		}
963	}
964#endif
965	if (sa->sa_family == AF_INET) {
966		/* IPv4 sa address */
967		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
968
969		param_type = ntohs(v4addr->ph.param_type);
970		param_length = ntohs(v4addr->ph.param_length);
971
972		if ((param_type == SCTP_IPV4_ADDRESS) &&
973		    param_length == sizeof(struct sctp_ipv4addr_param) &&
974		    (memcmp(&v4addr->addr, &sin->sin_addr,
975		    sizeof(struct in_addr)) == 0)) {
976			return (1);
977		}
978	}
979	return (0);
980}
981
982/*
983 * Cleanup for non-responded/OP ERR'd ASCONF
984 */
985void
986sctp_asconf_cleanup(struct sctp_tcb *stcb, struct sctp_nets *net)
987{
988	/* mark peer as ASCONF incapable */
989	stcb->asoc.peer_supports_asconf = 0;
990	/*
991	 * clear out any existing asconfs going out
992	 */
993	sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
994	    SCTP_FROM_SCTP_ASCONF + SCTP_LOC_2);
995	stcb->asoc.asconf_seq_out_acked = stcb->asoc.asconf_seq_out;
996	/* remove the old ASCONF on our outbound queue */
997	sctp_toss_old_asconf(stcb);
998}
999
1000/*
1001 * cleanup any cached source addresses that may be topologically
1002 * incorrect after a new address has been added to this interface.
1003 */
1004static void
1005sctp_asconf_nets_cleanup(struct sctp_tcb *stcb, struct sctp_ifn *ifn)
1006{
1007	struct sctp_nets *net;
1008
1009	/*
1010	 * Ideally, we want to only clear cached routes and source addresses
1011	 * that are topologically incorrect.  But since there is no easy way
1012	 * to know whether the newly added address on the ifn would cause a
1013	 * routing change (i.e. a new egress interface would be chosen)
1014	 * without doing a new routing lookup and source address selection,
1015	 * we will (for now) just flush any cached route using a different
1016	 * ifn (and cached source addrs) and let output re-choose them
1017	 * during the next send on that net.
1018	 */
1019	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1020		/*
1021		 * clear any cached route (and cached source address) if the
1022		 * route's interface is NOT the same as the address change.
1023		 * If it's the same interface, just clear the cached source
1024		 * address.
1025		 */
1026		if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro) &&
1027		    ((ifn == NULL) ||
1028		    (SCTP_GET_IF_INDEX_FROM_ROUTE(&net->ro) != ifn->ifn_index))) {
1029			/* clear any cached route */
1030			RTFREE(net->ro.ro_rt);
1031			net->ro.ro_rt = NULL;
1032		}
1033		/* clear any cached source address */
1034		if (net->src_addr_selected) {
1035			sctp_free_ifa(net->ro._s_addr);
1036			net->ro._s_addr = NULL;
1037			net->src_addr_selected = 0;
1038		}
1039	}
1040}
1041
1042
1043void
1044sctp_assoc_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *dstnet)
1045{
1046	int error;
1047
1048	if (dstnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
1049		return;
1050	}
1051	if (stcb->asoc.deleted_primary == NULL) {
1052		return;
1053	}
1054	if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
1055		SCTPDBG(SCTP_DEBUG_ASCONF1, "assoc_immediate_retrans: Deleted primary is ");
1056		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.deleted_primary->ro._l_addr.sa);
1057		SCTPDBG(SCTP_DEBUG_ASCONF1, "Current Primary is ");
1058		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &stcb->asoc.primary_destination->ro._l_addr.sa);
1059		sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb,
1060		    stcb->asoc.deleted_primary,
1061		    SCTP_FROM_SCTP_TIMER + SCTP_LOC_8);
1062		stcb->asoc.num_send_timers_up--;
1063		if (stcb->asoc.num_send_timers_up < 0) {
1064			stcb->asoc.num_send_timers_up = 0;
1065		}
1066		SCTP_TCB_LOCK_ASSERT(stcb);
1067		error = sctp_t3rxt_timer(stcb->sctp_ep, stcb,
1068		    stcb->asoc.deleted_primary);
1069		if (error) {
1070			SCTP_INP_DECR_REF(stcb->sctp_ep);
1071			return;
1072		}
1073		SCTP_TCB_LOCK_ASSERT(stcb);
1074#ifdef SCTP_AUDITING_ENABLED
1075		sctp_auditing(4, stcb->sctp_ep, stcb, stcb->asoc.deleted_primary);
1076#endif
1077		sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
1078		if ((stcb->asoc.num_send_timers_up == 0) &&
1079		    (stcb->asoc.sent_queue_cnt > 0)) {
1080			struct sctp_tmit_chunk *chk;
1081
1082			chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
1083			sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
1084			    stcb, chk->whoTo);
1085		}
1086	}
1087	return;
1088}
1089
1090static int
1091    sctp_asconf_queue_mgmt(struct sctp_tcb *, struct sctp_ifa *, uint16_t);
1092
1093void
1094sctp_net_immediate_retrans(struct sctp_tcb *stcb, struct sctp_nets *net)
1095{
1096	struct sctp_tmit_chunk *chk;
1097
1098	SCTPDBG(SCTP_DEBUG_ASCONF1, "net_immediate_retrans: RTO is %d\n", net->RTO);
1099	sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep, stcb, net,
1100	    SCTP_FROM_SCTP_TIMER + SCTP_LOC_5);
1101	stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
1102	net->error_count = 0;
1103	TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
1104		if (chk->whoTo == net) {
1105			if (chk->sent < SCTP_DATAGRAM_RESEND) {
1106				chk->sent = SCTP_DATAGRAM_RESEND;
1107				sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
1108				sctp_flight_size_decrease(chk);
1109				sctp_total_flight_decrease(stcb, chk);
1110				net->marked_retrans++;
1111				stcb->asoc.marked_retrans++;
1112			}
1113		}
1114	}
1115	if (net->marked_retrans) {
1116		sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);
1117	}
1118}
1119
1120static void
1121sctp_path_check_and_react(struct sctp_tcb *stcb, struct sctp_ifa *newifa)
1122{
1123	struct sctp_nets *net;
1124	int addrnum, changed;
1125
1126	/*
1127	 * If number of local valid addresses is 1, the valid address is
1128	 * probably newly added address. Several valid addresses in this
1129	 * association.  A source address may not be changed.  Additionally,
1130	 * they can be configured on a same interface as "alias" addresses.
1131	 * (by micchie)
1132	 */
1133	addrnum = sctp_local_addr_count(stcb);
1134	SCTPDBG(SCTP_DEBUG_ASCONF1, "p_check_react(): %d local addresses\n",
1135	    addrnum);
1136	if (addrnum == 1) {
1137		TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1138			/* clear any cached route and source address */
1139			if (net->ro.ro_rt) {
1140				RTFREE(net->ro.ro_rt);
1141				net->ro.ro_rt = NULL;
1142			}
1143			if (net->src_addr_selected) {
1144				sctp_free_ifa(net->ro._s_addr);
1145				net->ro._s_addr = NULL;
1146				net->src_addr_selected = 0;
1147			}
1148			/* Retransmit unacknowledged DATA chunks immediately */
1149			if (sctp_is_mobility_feature_on(stcb->sctp_ep,
1150			    SCTP_MOBILITY_FASTHANDOFF)) {
1151				sctp_net_immediate_retrans(stcb, net);
1152			}
1153			/* also, SET PRIMARY is maybe already sent */
1154		}
1155		return;
1156	}
1157	/* Multiple local addresses exsist in the association.  */
1158	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1159		/* clear any cached route and source address */
1160		if (net->ro.ro_rt) {
1161			RTFREE(net->ro.ro_rt);
1162			net->ro.ro_rt = NULL;
1163		}
1164		if (net->src_addr_selected) {
1165			sctp_free_ifa(net->ro._s_addr);
1166			net->ro._s_addr = NULL;
1167			net->src_addr_selected = 0;
1168		}
1169		/*
1170		 * Check if the nexthop is corresponding to the new address.
1171		 * If the new address is corresponding to the current
1172		 * nexthop, the path will be changed. If the new address is
1173		 * NOT corresponding to the current nexthop, the path will
1174		 * not be changed.
1175		 */
1176		SCTP_RTALLOC((sctp_route_t *) & net->ro,
1177		    stcb->sctp_ep->def_vrf_id);
1178		if (net->ro.ro_rt == NULL)
1179			continue;
1180
1181		changed = 0;
1182		if (net->ro._l_addr.sa.sa_family == AF_INET) {
1183			if (sctp_v4src_match_nexthop(newifa, (sctp_route_t *) & net->ro))
1184				changed = 1;
1185		}
1186#ifdef INET6
1187		if (net->ro._l_addr.sa.sa_family == AF_INET6) {
1188			if (sctp_v6src_match_nexthop(
1189			    &newifa->address.sin6, (sctp_route_t *) & net->ro))
1190				changed = 1;
1191		}
1192#endif
1193		/*
1194		 * if the newly added address does not relate routing
1195		 * information, we skip.
1196		 */
1197		if (changed == 0)
1198			continue;
1199		/* Retransmit unacknowledged DATA chunks immediately */
1200		if (sctp_is_mobility_feature_on(stcb->sctp_ep,
1201		    SCTP_MOBILITY_FASTHANDOFF)) {
1202			sctp_net_immediate_retrans(stcb, net);
1203		}
1204		/* Send SET PRIMARY for this new address */
1205		if (net == stcb->asoc.primary_destination) {
1206			(void)sctp_asconf_queue_mgmt(stcb, newifa,
1207			    SCTP_SET_PRIM_ADDR);
1208		}
1209	}
1210}
1211
1212/*
1213 * process an ADD/DELETE IP ack from peer.
1214 * addr: corresponding sctp_ifa to the address being added/deleted.
1215 * type: SCTP_ADD_IP_ADDRESS or SCTP_DEL_IP_ADDRESS.
1216 * flag: 1=success, 0=failure.
1217 */
1218static void
1219sctp_asconf_addr_mgmt_ack(struct sctp_tcb *stcb, struct sctp_ifa *addr,
1220    uint16_t type, uint32_t flag)
1221{
1222	/*
1223	 * do the necessary asoc list work- if we get a failure indication,
1224	 * leave the address on the assoc's restricted list.  If we get a
1225	 * success indication, remove the address from the restricted list.
1226	 */
1227	/*
1228	 * Note: this will only occur for ADD_IP_ADDRESS, since
1229	 * DEL_IP_ADDRESS is never actually added to the list...
1230	 */
1231	if (flag) {
1232		/* success case, so remove from the restricted list */
1233		sctp_del_local_addr_restricted(stcb, addr);
1234
1235		if (sctp_is_mobility_feature_on(stcb->sctp_ep,
1236		    SCTP_MOBILITY_BASE) ||
1237		    sctp_is_mobility_feature_on(stcb->sctp_ep,
1238		    SCTP_MOBILITY_FASTHANDOFF)) {
1239			sctp_path_check_and_react(stcb, addr);
1240			return;
1241		}
1242		/* clear any cached/topologically incorrect source addresses */
1243		sctp_asconf_nets_cleanup(stcb, addr->ifn_p);
1244	}
1245	/* else, leave it on the list */
1246}
1247
1248/*
1249 * add an asconf add/delete/set primary IP address parameter to the queue.
1250 * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
1251 * returns 0 if queued, -1 if not queued/removed.
1252 * NOTE: if adding, but a delete for the same address is already scheduled
1253 * (and not yet sent out), simply remove it from queue.  Same for deleting
1254 * an address already scheduled for add.  If a duplicate operation is found,
1255 * ignore the new one.
1256 */
1257static int
1258sctp_asconf_queue_mgmt(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
1259    uint16_t type)
1260{
1261	struct sctp_asconf_addr *aa, *aa_next;
1262	struct sockaddr *sa;
1263
1264	/* make sure the request isn't already in the queue */
1265	TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
1266		/* address match? */
1267		if (sctp_asconf_addr_match(aa, &ifa->address.sa) == 0)
1268			continue;
1269		/*
1270		 * is the request already in queue but not sent? pass the
1271		 * request already sent in order to resolve the following
1272		 * case: 1. arrival of ADD, then sent 2. arrival of DEL. we
1273		 * can't remove the ADD request already sent 3. arrival of
1274		 * ADD
1275		 */
1276		if (aa->ap.aph.ph.param_type == type && aa->sent == 0) {
1277			return (-1);
1278		}
1279		/* is the negative request already in queue, and not sent */
1280		if ((aa->sent == 0) && (type == SCTP_ADD_IP_ADDRESS) &&
1281		    (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS)) {
1282			/* add requested, delete already queued */
1283			TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
1284			/* remove the ifa from the restricted list */
1285			sctp_del_local_addr_restricted(stcb, ifa);
1286			/* free the asconf param */
1287			SCTP_FREE(aa, SCTP_M_ASC_ADDR);
1288			SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: add removes queued entry\n");
1289			return (-1);
1290		}
1291		if ((aa->sent == 0) && (type == SCTP_DEL_IP_ADDRESS) &&
1292		    (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS)) {
1293			/* delete requested, add already queued */
1294			TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
1295			/* remove the aa->ifa from the restricted list */
1296			sctp_del_local_addr_restricted(stcb, aa->ifa);
1297			/* free the asconf param */
1298			SCTP_FREE(aa, SCTP_M_ASC_ADDR);
1299			SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_mgmt: delete removes queued entry\n");
1300			return (-1);
1301		}
1302	}			/* for each aa */
1303
1304	/* adding new request to the queue */
1305	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
1306	    SCTP_M_ASC_ADDR);
1307	if (aa == NULL) {
1308		/* didn't get memory */
1309		SCTPDBG(SCTP_DEBUG_ASCONF1, "asconf_queue_mgmt: failed to get memory!\n");
1310		return (-1);
1311	}
1312	aa->special_del = 0;
1313	/* fill in asconf address parameter fields */
1314	/* top level elements are "networked" during send */
1315	aa->ap.aph.ph.param_type = type;
1316	aa->ifa = ifa;
1317	atomic_add_int(&ifa->refcount, 1);
1318	/* correlation_id filled in during send routine later... */
1319	if (ifa->address.sa.sa_family == AF_INET6) {
1320		/* IPv6 address */
1321		struct sockaddr_in6 *sin6;
1322
1323		sin6 = (struct sockaddr_in6 *)&ifa->address.sa;
1324		sa = (struct sockaddr *)sin6;
1325		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
1326		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
1327		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
1328		    sizeof(struct sctp_ipv6addr_param);
1329		memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
1330		    sizeof(struct in6_addr));
1331	} else if (ifa->address.sa.sa_family == AF_INET) {
1332		/* IPv4 address */
1333		struct sockaddr_in *sin;
1334
1335		sin = (struct sockaddr_in *)&ifa->address.sa;
1336		sa = (struct sockaddr *)sin;
1337		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
1338		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
1339		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) +
1340		    sizeof(struct sctp_ipv4addr_param);
1341		memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
1342		    sizeof(struct in_addr));
1343	} else {
1344		/* invalid family! */
1345		SCTP_FREE(aa, SCTP_M_ASC_ADDR);
1346		sctp_free_ifa(ifa);
1347		return (-1);
1348	}
1349	aa->sent = 0;		/* clear sent flag */
1350
1351	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
1352#ifdef SCTP_DEBUG
1353	if (SCTP_BASE_SYSCTL(sctp_debug_on) & SCTP_DEBUG_ASCONF2) {
1354		if (type == SCTP_ADD_IP_ADDRESS) {
1355			SCTP_PRINTF("asconf_queue_mgmt: inserted asconf ADD_IP_ADDRESS: ");
1356			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
1357		} else if (type == SCTP_DEL_IP_ADDRESS) {
1358			SCTP_PRINTF("asconf_queue_mgmt: appended asconf DEL_IP_ADDRESS: ");
1359			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
1360		} else {
1361			SCTP_PRINTF("asconf_queue_mgmt: appended asconf SET_PRIM_ADDR: ");
1362			SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
1363		}
1364	}
1365#endif
1366
1367	return (0);
1368}
1369
1370
1371/*
1372 * add an asconf operation for the given ifa and type.
1373 * type = SCTP_ADD_IP_ADDRESS, SCTP_DEL_IP_ADDRESS, SCTP_SET_PRIM_ADDR.
1374 * returns 0 if completed, -1 if not completed, 1 if immediate send is
1375 * advisable.
1376 */
1377static int
1378sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa,
1379    uint16_t type)
1380{
1381	uint32_t status;
1382	int pending_delete_queued = 0;
1383
1384	/* see if peer supports ASCONF */
1385	if (stcb->asoc.peer_supports_asconf == 0) {
1386		return (-1);
1387	}
1388	/*
1389	 * if this is deleting the last address from the assoc, mark it as
1390	 * pending.
1391	 */
1392	if ((type == SCTP_DEL_IP_ADDRESS) && !stcb->asoc.asconf_del_pending &&
1393	    (sctp_local_addr_count(stcb) < 2)) {
1394		/* set the pending delete info only */
1395		stcb->asoc.asconf_del_pending = 1;
1396		stcb->asoc.asconf_addr_del_pending = ifa;
1397		atomic_add_int(&ifa->refcount, 1);
1398		SCTPDBG(SCTP_DEBUG_ASCONF2,
1399		    "asconf_queue_add: mark delete last address pending\n");
1400		return (-1);
1401	}
1402	/* queue an asconf parameter */
1403	status = sctp_asconf_queue_mgmt(stcb, ifa, type);
1404
1405	/*
1406	 * if this is an add, and there is a delete also pending (i.e. the
1407	 * last local address is being changed), queue the pending delete
1408	 * too.
1409	 */
1410	if ((type == SCTP_ADD_IP_ADDRESS) && stcb->asoc.asconf_del_pending && (status == 0)) {
1411		/* queue in the pending delete */
1412		if (sctp_asconf_queue_mgmt(stcb,
1413		    stcb->asoc.asconf_addr_del_pending,
1414		    SCTP_DEL_IP_ADDRESS) == 0) {
1415			SCTPDBG(SCTP_DEBUG_ASCONF2, "asconf_queue_add: queing pending delete\n");
1416			pending_delete_queued = 1;
1417			/* clear out the pending delete info */
1418			stcb->asoc.asconf_del_pending = 0;
1419			sctp_free_ifa(stcb->asoc.asconf_addr_del_pending);
1420			stcb->asoc.asconf_addr_del_pending = NULL;
1421		}
1422	}
1423	if (pending_delete_queued) {
1424		struct sctp_nets *net;
1425
1426		/*
1427		 * since we know that the only/last address is now being
1428		 * changed in this case, reset the cwnd/rto on all nets to
1429		 * start as a new address and path.  Also clear the error
1430		 * counts to give the assoc the best chance to complete the
1431		 * address change.
1432		 */
1433		TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1434			stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb,
1435			    net);
1436			net->RTO = 0;
1437			net->error_count = 0;
1438		}
1439		stcb->asoc.overall_error_count = 0;
1440		if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_THRESHOLD_LOGGING) {
1441			sctp_misc_ints(SCTP_THRESHOLD_CLEAR,
1442			    stcb->asoc.overall_error_count,
1443			    0,
1444			    SCTP_FROM_SCTP_ASCONF,
1445			    __LINE__);
1446		}
1447		/* queue in an advisory set primary too */
1448		(void)sctp_asconf_queue_mgmt(stcb, ifa, SCTP_SET_PRIM_ADDR);
1449		/* let caller know we should send this out immediately */
1450		status = 1;
1451	}
1452	return (status);
1453}
1454
1455/*-
1456 * add an asconf delete IP address parameter to the queue by sockaddr and
1457 * possibly with no sctp_ifa available.  This is only called by the routine
1458 * that checks the addresses in an INIT-ACK against the current address list.
1459 * returns 0 if completed, non-zero if not completed.
1460 * NOTE: if an add is already scheduled (and not yet sent out), simply
1461 * remove it from queue.  If a duplicate operation is found, ignore the
1462 * new one.
1463 */
1464static int
1465sctp_asconf_queue_sa_delete(struct sctp_tcb *stcb, struct sockaddr *sa)
1466{
1467	struct sctp_ifa *ifa;
1468	struct sctp_asconf_addr *aa, *aa_next;
1469	uint32_t vrf_id;
1470
1471	if (stcb == NULL) {
1472		return (-1);
1473	}
1474	/* see if peer supports ASCONF */
1475	if (stcb->asoc.peer_supports_asconf == 0) {
1476		return (-1);
1477	}
1478	/* make sure the request isn't already in the queue */
1479	TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
1480		/* address match? */
1481		if (sctp_asconf_addr_match(aa, sa) == 0)
1482			continue;
1483		/* is the request already in queue (sent or not) */
1484		if (aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
1485			return (-1);
1486		}
1487		/* is the negative request already in queue, and not sent */
1488		if (aa->sent == 1)
1489			continue;
1490		if (aa->ap.aph.ph.param_type == SCTP_ADD_IP_ADDRESS) {
1491			/* add already queued, so remove existing entry */
1492			TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next);
1493			sctp_del_local_addr_restricted(stcb, aa->ifa);
1494			/* free the entry */
1495			SCTP_FREE(aa, SCTP_M_ASC_ADDR);
1496			return (-1);
1497		}
1498	}			/* for each aa */
1499
1500	/* find any existing ifa-- NOTE ifa CAN be allowed to be NULL */
1501	if (stcb) {
1502		vrf_id = stcb->asoc.vrf_id;
1503	} else {
1504		vrf_id = SCTP_DEFAULT_VRFID;
1505	}
1506	ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
1507
1508	/* adding new request to the queue */
1509	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
1510	    SCTP_M_ASC_ADDR);
1511	if (aa == NULL) {
1512		/* didn't get memory */
1513		SCTPDBG(SCTP_DEBUG_ASCONF1,
1514		    "sctp_asconf_queue_sa_delete: failed to get memory!\n");
1515		return (-1);
1516	}
1517	aa->special_del = 0;
1518	/* fill in asconf address parameter fields */
1519	/* top level elements are "networked" during send */
1520	aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
1521	aa->ifa = ifa;
1522	if (ifa)
1523		atomic_add_int(&ifa->refcount, 1);
1524	/* correlation_id filled in during send routine later... */
1525	if (sa->sa_family == AF_INET6) {
1526		/* IPv6 address */
1527		struct sockaddr_in6 *sin6;
1528
1529		sin6 = (struct sockaddr_in6 *)sa;
1530		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
1531		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv6addr_param));
1532		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv6addr_param);
1533		memcpy(&aa->ap.addrp.addr, &sin6->sin6_addr,
1534		    sizeof(struct in6_addr));
1535	} else if (sa->sa_family == AF_INET) {
1536		/* IPv4 address */
1537		struct sockaddr_in *sin = (struct sockaddr_in *)sa;
1538
1539		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
1540		aa->ap.addrp.ph.param_length = (sizeof(struct sctp_ipv4addr_param));
1541		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_paramhdr) + sizeof(struct sctp_ipv4addr_param);
1542		memcpy(&aa->ap.addrp.addr, &sin->sin_addr,
1543		    sizeof(struct in_addr));
1544	} else {
1545		/* invalid family! */
1546		SCTP_FREE(aa, SCTP_M_ASC_ADDR);
1547		if (ifa)
1548			sctp_free_ifa(ifa);
1549		return (-1);
1550	}
1551	aa->sent = 0;		/* clear sent flag */
1552
1553	/* delete goes to the back of the queue */
1554	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
1555
1556	/* sa_ignore MEMLEAK {memory is put on the tailq} */
1557	return (0);
1558}
1559
1560/*
1561 * find a specific asconf param on our "sent" queue
1562 */
1563static struct sctp_asconf_addr *
1564sctp_asconf_find_param(struct sctp_tcb *stcb, uint32_t correlation_id)
1565{
1566	struct sctp_asconf_addr *aa;
1567
1568	TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
1569		if (aa->ap.aph.correlation_id == correlation_id &&
1570		    aa->sent == 1) {
1571			/* found it */
1572			return (aa);
1573		}
1574	}
1575	/* didn't find it */
1576	return (NULL);
1577}
1578
1579/*
1580 * process an SCTP_ERROR_CAUSE_IND for a ASCONF-ACK parameter and do
1581 * notifications based on the error response
1582 */
1583static void
1584sctp_asconf_process_error(struct sctp_tcb *stcb,
1585    struct sctp_asconf_paramhdr *aph)
1586{
1587	struct sctp_error_cause *eh;
1588	struct sctp_paramhdr *ph;
1589	uint16_t param_type;
1590	uint16_t error_code;
1591
1592	eh = (struct sctp_error_cause *)(aph + 1);
1593	ph = (struct sctp_paramhdr *)(eh + 1);
1594	/* validate lengths */
1595	if (htons(eh->length) + sizeof(struct sctp_error_cause) >
1596	    htons(aph->ph.param_length)) {
1597		/* invalid error cause length */
1598		SCTPDBG(SCTP_DEBUG_ASCONF1,
1599		    "asconf_process_error: cause element too long\n");
1600		return;
1601	}
1602	if (htons(ph->param_length) + sizeof(struct sctp_paramhdr) >
1603	    htons(eh->length)) {
1604		/* invalid included TLV length */
1605		SCTPDBG(SCTP_DEBUG_ASCONF1,
1606		    "asconf_process_error: included TLV too long\n");
1607		return;
1608	}
1609	/* which error code ? */
1610	error_code = ntohs(eh->code);
1611	param_type = ntohs(aph->ph.param_type);
1612	/* FIX: this should go back up the REMOTE_ERROR ULP notify */
1613	switch (error_code) {
1614	case SCTP_CAUSE_RESOURCE_SHORTAGE:
1615		/* we allow ourselves to "try again" for this error */
1616		break;
1617	default:
1618		/* peer can't handle it... */
1619		switch (param_type) {
1620		case SCTP_ADD_IP_ADDRESS:
1621		case SCTP_DEL_IP_ADDRESS:
1622			stcb->asoc.peer_supports_asconf = 0;
1623			break;
1624		case SCTP_SET_PRIM_ADDR:
1625			stcb->asoc.peer_supports_asconf = 0;
1626			break;
1627		default:
1628			break;
1629		}
1630	}
1631}
1632
1633/*
1634 * process an asconf queue param.
1635 * aparam: parameter to process, will be removed from the queue.
1636 * flag: 1=success case, 0=failure case
1637 */
1638static void
1639sctp_asconf_process_param_ack(struct sctp_tcb *stcb,
1640    struct sctp_asconf_addr *aparam, uint32_t flag)
1641{
1642	uint16_t param_type;
1643
1644	/* process this param */
1645	param_type = aparam->ap.aph.ph.param_type;
1646	switch (param_type) {
1647	case SCTP_ADD_IP_ADDRESS:
1648		SCTPDBG(SCTP_DEBUG_ASCONF1,
1649		    "process_param_ack: added IP address\n");
1650		sctp_asconf_addr_mgmt_ack(stcb, aparam->ifa, param_type, flag);
1651		break;
1652	case SCTP_DEL_IP_ADDRESS:
1653		SCTPDBG(SCTP_DEBUG_ASCONF1,
1654		    "process_param_ack: deleted IP address\n");
1655		/* nothing really to do... lists already updated */
1656		break;
1657	case SCTP_SET_PRIM_ADDR:
1658		SCTPDBG(SCTP_DEBUG_ASCONF1,
1659		    "process_param_ack: set primary IP address\n");
1660		/* nothing to do... peer may start using this addr */
1661		if (flag == 0)
1662			stcb->asoc.peer_supports_asconf = 0;
1663		break;
1664	default:
1665		/* should NEVER happen */
1666		break;
1667	}
1668
1669	/* remove the param and free it */
1670	TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next);
1671	if (aparam->ifa)
1672		sctp_free_ifa(aparam->ifa);
1673	SCTP_FREE(aparam, SCTP_M_ASC_ADDR);
1674}
1675
1676/*
1677 * cleanup from a bad asconf ack parameter
1678 */
1679static void
1680sctp_asconf_ack_clear(struct sctp_tcb *stcb)
1681{
1682	/* assume peer doesn't really know how to do asconfs */
1683	stcb->asoc.peer_supports_asconf = 0;
1684	/* XXX we could free the pending queue here */
1685}
1686
1687void
1688sctp_handle_asconf_ack(struct mbuf *m, int offset,
1689    struct sctp_asconf_ack_chunk *cp, struct sctp_tcb *stcb,
1690    struct sctp_nets *net, int *abort_no_unlock)
1691{
1692	struct sctp_association *asoc;
1693	uint32_t serial_num;
1694	uint16_t ack_length;
1695	struct sctp_asconf_paramhdr *aph;
1696	struct sctp_asconf_addr *aa, *aa_next;
1697	uint32_t last_error_id = 0;	/* last error correlation id */
1698	uint32_t id;
1699	struct sctp_asconf_addr *ap;
1700
1701	/* asconf param buffer */
1702	uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
1703
1704	/* verify minimum length */
1705	if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_asconf_ack_chunk)) {
1706		SCTPDBG(SCTP_DEBUG_ASCONF1,
1707		    "handle_asconf_ack: chunk too small = %xh\n",
1708		    ntohs(cp->ch.chunk_length));
1709		return;
1710	}
1711	asoc = &stcb->asoc;
1712	serial_num = ntohl(cp->serial_number);
1713
1714	/*
1715	 * NOTE: we may want to handle this differently- currently, we will
1716	 * abort when we get an ack for the expected serial number + 1 (eg.
1717	 * we didn't send it), process an ack normally if it is the expected
1718	 * serial number, and re-send the previous ack for *ALL* other
1719	 * serial numbers
1720	 */
1721
1722	/*
1723	 * if the serial number is the next expected, but I didn't send it,
1724	 * abort the asoc, since someone probably just hijacked us...
1725	 */
1726	if (serial_num == (asoc->asconf_seq_out + 1)) {
1727		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got unexpected next serial number! Aborting asoc!\n");
1728		sctp_abort_an_association(stcb->sctp_ep, stcb,
1729		    SCTP_CAUSE_ILLEGAL_ASCONF_ACK, NULL, SCTP_SO_NOT_LOCKED);
1730		*abort_no_unlock = 1;
1731		return;
1732	}
1733	if (serial_num != asoc->asconf_seq_out_acked + 1) {
1734		/* got a duplicate/unexpected ASCONF-ACK */
1735		SCTPDBG(SCTP_DEBUG_ASCONF1, "handle_asconf_ack: got duplicate/unexpected serial number = %xh (expected = %xh)\n",
1736		    serial_num, asoc->asconf_seq_out_acked + 1);
1737		return;
1738	}
1739	if (serial_num == asoc->asconf_seq_out - 1) {
1740		/* stop our timer */
1741		sctp_timer_stop(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep, stcb, net,
1742		    SCTP_FROM_SCTP_ASCONF + SCTP_LOC_3);
1743	}
1744	/* process the ASCONF-ACK contents */
1745	ack_length = ntohs(cp->ch.chunk_length) -
1746	    sizeof(struct sctp_asconf_ack_chunk);
1747	offset += sizeof(struct sctp_asconf_ack_chunk);
1748	/* process through all parameters */
1749	while (ack_length >= sizeof(struct sctp_asconf_paramhdr)) {
1750		unsigned int param_length, param_type;
1751
1752		/* get pointer to next asconf parameter */
1753		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset,
1754		    sizeof(struct sctp_asconf_paramhdr), aparam_buf);
1755		if (aph == NULL) {
1756			/* can't get an asconf paramhdr */
1757			sctp_asconf_ack_clear(stcb);
1758			return;
1759		}
1760		param_type = ntohs(aph->ph.param_type);
1761		param_length = ntohs(aph->ph.param_length);
1762		if (param_length > ack_length) {
1763			sctp_asconf_ack_clear(stcb);
1764			return;
1765		}
1766		if (param_length < sizeof(struct sctp_paramhdr)) {
1767			sctp_asconf_ack_clear(stcb);
1768			return;
1769		}
1770		/* get the complete parameter... */
1771		if (param_length > sizeof(aparam_buf)) {
1772			SCTPDBG(SCTP_DEBUG_ASCONF1,
1773			    "param length (%u) larger than buffer size!\n", param_length);
1774			sctp_asconf_ack_clear(stcb);
1775			return;
1776		}
1777		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(m, offset, param_length, aparam_buf);
1778		if (aph == NULL) {
1779			sctp_asconf_ack_clear(stcb);
1780			return;
1781		}
1782		/* correlation_id is transparent to peer, no ntohl needed */
1783		id = aph->correlation_id;
1784
1785		switch (param_type) {
1786		case SCTP_ERROR_CAUSE_IND:
1787			last_error_id = id;
1788			/* find the corresponding asconf param in our queue */
1789			ap = sctp_asconf_find_param(stcb, id);
1790			if (ap == NULL) {
1791				/* hmm... can't find this in our queue! */
1792				break;
1793			}
1794			/* process the parameter, failed flag */
1795			sctp_asconf_process_param_ack(stcb, ap, 0);
1796			/* process the error response */
1797			sctp_asconf_process_error(stcb, aph);
1798			break;
1799		case SCTP_SUCCESS_REPORT:
1800			/* find the corresponding asconf param in our queue */
1801			ap = sctp_asconf_find_param(stcb, id);
1802			if (ap == NULL) {
1803				/* hmm... can't find this in our queue! */
1804				break;
1805			}
1806			/* process the parameter, success flag */
1807			sctp_asconf_process_param_ack(stcb, ap, 1);
1808			break;
1809		default:
1810			break;
1811		}		/* switch */
1812
1813		/* update remaining ASCONF-ACK message length to process */
1814		ack_length -= SCTP_SIZE32(param_length);
1815		if (ack_length <= 0) {
1816			/* no more data in the mbuf chain */
1817			break;
1818		}
1819		offset += SCTP_SIZE32(param_length);
1820	}			/* while */
1821
1822	/*
1823	 * if there are any "sent" params still on the queue, these are
1824	 * implicitly "success", or "failed" (if we got an error back) ...
1825	 * so process these appropriately
1826	 *
1827	 * we assume that the correlation_id's are monotonically increasing
1828	 * beginning from 1 and that we don't have *that* many outstanding
1829	 * at any given time
1830	 */
1831	if (last_error_id == 0)
1832		last_error_id--;/* set to "max" value */
1833	TAILQ_FOREACH_SAFE(aa, &stcb->asoc.asconf_queue, next, aa_next) {
1834		if (aa->sent == 1) {
1835			/*
1836			 * implicitly successful or failed if correlation_id
1837			 * < last_error_id, then success else, failure
1838			 */
1839			if (aa->ap.aph.correlation_id < last_error_id)
1840				sctp_asconf_process_param_ack(stcb, aa, 1);
1841			else
1842				sctp_asconf_process_param_ack(stcb, aa, 0);
1843		} else {
1844			/*
1845			 * since we always process in order (FIFO queue) if
1846			 * we reach one that hasn't been sent, the rest
1847			 * should not have been sent either. so, we're
1848			 * done...
1849			 */
1850			break;
1851		}
1852	}
1853
1854	/* update the next sequence number to use */
1855	asoc->asconf_seq_out_acked++;
1856	/* remove the old ASCONF on our outbound queue */
1857	sctp_toss_old_asconf(stcb);
1858	if (!TAILQ_EMPTY(&stcb->asoc.asconf_queue)) {
1859#ifdef SCTP_TIMER_BASED_ASCONF
1860		/* we have more params, so restart our timer */
1861		sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, stcb->sctp_ep,
1862		    stcb, net);
1863#else
1864		/* we have more params, so send out more */
1865		sctp_send_asconf(stcb, net, SCTP_ADDR_NOT_LOCKED);
1866#endif
1867	}
1868}
1869
1870#ifdef INET6
1871static uint32_t
1872sctp_is_scopeid_in_nets(struct sctp_tcb *stcb, struct sockaddr *sa)
1873{
1874	struct sockaddr_in6 *sin6, *net6;
1875	struct sctp_nets *net;
1876
1877	if (sa->sa_family != AF_INET6) {
1878		/* wrong family */
1879		return (0);
1880	}
1881	sin6 = (struct sockaddr_in6 *)sa;
1882	if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) == 0) {
1883		/* not link local address */
1884		return (0);
1885	}
1886	/* hunt through our destination nets list for this scope_id */
1887	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1888		if (((struct sockaddr *)(&net->ro._l_addr))->sa_family !=
1889		    AF_INET6)
1890			continue;
1891		net6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1892		if (IN6_IS_ADDR_LINKLOCAL(&net6->sin6_addr) == 0)
1893			continue;
1894		if (sctp_is_same_scope(sin6, net6)) {
1895			/* found one */
1896			return (1);
1897		}
1898	}
1899	/* didn't find one */
1900	return (0);
1901}
1902
1903#endif
1904
1905/*
1906 * address management functions
1907 */
1908static void
1909sctp_addr_mgmt_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
1910    struct sctp_ifa *ifa, uint16_t type, int addr_locked)
1911{
1912	int status;
1913
1914
1915	if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0 &&
1916	    sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
1917		/* subset bound, no ASCONF allowed case, so ignore */
1918		return;
1919	}
1920	/*
1921	 * note: we know this is not the subset bound, no ASCONF case eg.
1922	 * this is boundall or subset bound w/ASCONF allowed
1923	 */
1924
1925	/* first, make sure it's a good address family */
1926	if (ifa->address.sa.sa_family != AF_INET6 &&
1927	    ifa->address.sa.sa_family != AF_INET) {
1928		return;
1929	}
1930	/* make sure we're "allowed" to add this type of addr */
1931	if (ifa->address.sa.sa_family == AF_INET6) {
1932		/* invalid if we're not a v6 endpoint */
1933		if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0)
1934			return;
1935		/* is the v6 addr really valid ? */
1936		if (ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
1937			return;
1938		}
1939	}
1940	/* put this address on the "pending/do not use yet" list */
1941	sctp_add_local_addr_restricted(stcb, ifa);
1942	/*
1943	 * check address scope if address is out of scope, don't queue
1944	 * anything... note: this would leave the address on both inp and
1945	 * asoc lists
1946	 */
1947	switch (ifa->address.sa.sa_family) {
1948#ifdef INET6
1949	case AF_INET6:
1950		{
1951			struct sockaddr_in6 *sin6;
1952
1953			sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
1954			if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1955				/* we skip unspecifed addresses */
1956				return;
1957			}
1958			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1959				if (stcb->asoc.local_scope == 0) {
1960					return;
1961				}
1962				/* is it the right link local scope? */
1963				if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
1964					return;
1965				}
1966			}
1967			if (stcb->asoc.site_scope == 0 &&
1968			    IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) {
1969				return;
1970			}
1971			break;
1972		}
1973#endif
1974	case AF_INET:
1975		{
1976			struct sockaddr_in *sin;
1977			struct in6pcb *inp6;
1978
1979			inp6 = (struct in6pcb *)&inp->ip_inp.inp;
1980			/* invalid if we are a v6 only endpoint */
1981			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1982			    SCTP_IPV6_V6ONLY(inp6))
1983				return;
1984
1985			sin = (struct sockaddr_in *)&ifa->address.sa;
1986			if (sin->sin_addr.s_addr == 0) {
1987				/* we skip unspecifed addresses */
1988				return;
1989			}
1990			if (stcb->asoc.ipv4_local_scope == 0 &&
1991			    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
1992				return;
1993			}
1994			break;
1995		}
1996	default:
1997		/* else, not AF_INET or AF_INET6, so skip */
1998		return;
1999	}
2000
2001	/* queue an asconf for this address add/delete */
2002	if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF)) {
2003		/* does the peer do asconf? */
2004		if (stcb->asoc.peer_supports_asconf) {
2005			/* queue an asconf for this addr */
2006			status = sctp_asconf_queue_add(stcb, ifa, type);
2007
2008			/*
2009			 * if queued ok, and in the open state, send out the
2010			 * ASCONF.  If in the non-open state, these will be
2011			 * sent when the state goes open.
2012			 */
2013			if (status == 0 &&
2014			    SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
2015#ifdef SCTP_TIMER_BASED_ASCONF
2016				sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp,
2017				    stcb, stcb->asoc.primary_destination);
2018#else
2019				sctp_send_asconf(stcb, stcb->asoc.primary_destination,
2020				    addr_locked);
2021#endif
2022			}
2023		}
2024	}
2025}
2026
2027
2028int
2029sctp_asconf_iterator_ep(struct sctp_inpcb *inp, void *ptr, uint32_t val)
2030{
2031	struct sctp_asconf_iterator *asc;
2032	struct sctp_ifa *ifa;
2033	struct sctp_laddr *l;
2034	int cnt_invalid = 0;
2035
2036	asc = (struct sctp_asconf_iterator *)ptr;
2037	LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
2038		ifa = l->ifa;
2039		if (ifa->address.sa.sa_family == AF_INET6) {
2040			/* invalid if we're not a v6 endpoint */
2041			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
2042				cnt_invalid++;
2043				if (asc->cnt == cnt_invalid)
2044					return (1);
2045				else
2046					continue;
2047			}
2048		} else if (ifa->address.sa.sa_family == AF_INET) {
2049			/* invalid if we are a v6 only endpoint */
2050			struct in6pcb *inp6;
2051
2052			inp6 = (struct in6pcb *)&inp->ip_inp.inp;
2053			if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2054			    SCTP_IPV6_V6ONLY(inp6)) {
2055				cnt_invalid++;
2056				if (asc->cnt == cnt_invalid)
2057					return (1);
2058				else
2059					continue;
2060			}
2061		} else {
2062			/* invalid address family */
2063			cnt_invalid++;
2064			if (asc->cnt == cnt_invalid)
2065				return (1);
2066			else
2067				continue;
2068		}
2069	}
2070	return (0);
2071}
2072
2073static int
2074sctp_asconf_iterator_ep_end(struct sctp_inpcb *inp, void *ptr, uint32_t val)
2075{
2076	struct sctp_ifa *ifa;
2077	struct sctp_asconf_iterator *asc;
2078	struct sctp_laddr *laddr, *nladdr, *l;
2079
2080	/* Only for specific case not bound all */
2081	asc = (struct sctp_asconf_iterator *)ptr;
2082	LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
2083		ifa = l->ifa;
2084		if (l->action == SCTP_ADD_IP_ADDRESS) {
2085			LIST_FOREACH(laddr, &inp->sctp_addr_list,
2086			    sctp_nxt_addr) {
2087				if (laddr->ifa == ifa) {
2088					laddr->action = 0;
2089					break;
2090				}
2091			}
2092		} else if (l->action == SCTP_DEL_IP_ADDRESS) {
2093			LIST_FOREACH_SAFE(laddr, &inp->sctp_addr_list, sctp_nxt_addr, nladdr) {
2094				/* remove only after all guys are done */
2095				if (laddr->ifa == ifa) {
2096					sctp_del_local_addr_ep(inp, ifa);
2097				}
2098			}
2099		}
2100	}
2101	return (0);
2102}
2103
2104void
2105sctp_asconf_iterator_stcb(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
2106    void *ptr, uint32_t val)
2107{
2108	struct sctp_asconf_iterator *asc;
2109	struct sctp_ifa *ifa;
2110	struct sctp_laddr *l;
2111	int cnt_invalid = 0;
2112	int type, status;
2113	int num_queued = 0;
2114
2115	asc = (struct sctp_asconf_iterator *)ptr;
2116	LIST_FOREACH(l, &asc->list_of_work, sctp_nxt_addr) {
2117		ifa = l->ifa;
2118		type = l->action;
2119
2120		/* address's vrf_id must be the vrf_id of the assoc */
2121		if (ifa->vrf_id != stcb->asoc.vrf_id) {
2122			continue;
2123		}
2124		/* Same checks again for assoc */
2125		switch (ifa->address.sa.sa_family) {
2126#ifdef INET6
2127		case AF_INET6:
2128			{
2129				/* invalid if we're not a v6 endpoint */
2130				struct sockaddr_in6 *sin6;
2131
2132				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
2133					cnt_invalid++;
2134					if (asc->cnt == cnt_invalid)
2135						return;
2136					else
2137						continue;
2138				}
2139				sin6 = (struct sockaddr_in6 *)&ifa->address.sin6;
2140				if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2141					/* we skip unspecifed addresses */
2142					continue;
2143				}
2144				if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
2145					if (stcb->asoc.local_scope == 0) {
2146						continue;
2147					}
2148					/* is it the right link local scope? */
2149					if (sctp_is_scopeid_in_nets(stcb, &ifa->address.sa) == 0) {
2150						continue;
2151					}
2152				}
2153				break;
2154			}
2155#endif
2156		case AF_INET:
2157			{
2158				/* invalid if we are a v6 only endpoint */
2159				struct in6pcb *inp6;
2160				struct sockaddr_in *sin;
2161
2162				inp6 = (struct in6pcb *)&inp->ip_inp.inp;
2163				/* invalid if we are a v6 only endpoint */
2164				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2165				    SCTP_IPV6_V6ONLY(inp6))
2166					continue;
2167
2168				sin = (struct sockaddr_in *)&ifa->address.sa;
2169				if (sin->sin_addr.s_addr == 0) {
2170					/* we skip unspecifed addresses */
2171					continue;
2172				}
2173				if (stcb->asoc.ipv4_local_scope == 0 &&
2174				    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) {
2175					continue;
2176				}
2177				if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2178				    SCTP_IPV6_V6ONLY(inp6)) {
2179					cnt_invalid++;
2180					if (asc->cnt == cnt_invalid)
2181						return;
2182					else
2183						continue;
2184				}
2185				break;
2186			}
2187		default:
2188			/* invalid address family */
2189			cnt_invalid++;
2190			if (asc->cnt == cnt_invalid)
2191				return;
2192			else
2193				continue;
2194			break;
2195		}
2196
2197		if (type == SCTP_ADD_IP_ADDRESS) {
2198			/* prevent this address from being used as a source */
2199			sctp_add_local_addr_restricted(stcb, ifa);
2200		} else if (type == SCTP_DEL_IP_ADDRESS) {
2201			struct sctp_nets *net;
2202
2203			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2204				sctp_rtentry_t *rt;
2205
2206				/* delete this address if cached */
2207				if (net->ro._s_addr == ifa) {
2208					sctp_free_ifa(net->ro._s_addr);
2209					net->ro._s_addr = NULL;
2210					net->src_addr_selected = 0;
2211					rt = net->ro.ro_rt;
2212					if (rt) {
2213						RTFREE(rt);
2214						net->ro.ro_rt = NULL;
2215					}
2216					/*
2217					 * Now we deleted our src address,
2218					 * should we not also now reset the
2219					 * cwnd/rto to start as if its a new
2220					 * address?
2221					 */
2222					stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
2223					net->RTO = 0;
2224
2225				}
2226			}
2227		} else if (type == SCTP_SET_PRIM_ADDR) {
2228			if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
2229				/* must validate the ifa is in the ep */
2230				if (sctp_is_addr_in_ep(stcb->sctp_ep, ifa) == 0) {
2231					continue;
2232				}
2233			} else {
2234				/* Need to check scopes for this guy */
2235				if (sctp_is_address_in_scope(ifa,
2236				    stcb->asoc.ipv4_addr_legal,
2237				    stcb->asoc.ipv6_addr_legal,
2238				    stcb->asoc.loopback_scope,
2239				    stcb->asoc.ipv4_local_scope,
2240				    stcb->asoc.local_scope,
2241				    stcb->asoc.site_scope, 0) == 0) {
2242					continue;
2243				}
2244			}
2245		}
2246		/* queue an asconf for this address add/delete */
2247		if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DO_ASCONF) &&
2248		    stcb->asoc.peer_supports_asconf) {
2249			/* queue an asconf for this addr */
2250			status = sctp_asconf_queue_add(stcb, ifa, type);
2251			/*
2252			 * if queued ok, and in the open state, update the
2253			 * count of queued params.  If in the non-open
2254			 * state, these get sent when the assoc goes open.
2255			 */
2256			if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
2257				if (status >= 0) {
2258					num_queued++;
2259				}
2260			}
2261		}
2262	}
2263	/*
2264	 * If we have queued params in the open state, send out an ASCONF.
2265	 */
2266	if (num_queued > 0) {
2267		sctp_send_asconf(stcb, stcb->asoc.primary_destination,
2268		    SCTP_ADDR_NOT_LOCKED);
2269	}
2270}
2271
2272void
2273sctp_asconf_iterator_end(void *ptr, uint32_t val)
2274{
2275	struct sctp_asconf_iterator *asc;
2276	struct sctp_ifa *ifa;
2277	struct sctp_laddr *l, *nl;
2278
2279	asc = (struct sctp_asconf_iterator *)ptr;
2280	LIST_FOREACH_SAFE(l, &asc->list_of_work, sctp_nxt_addr, nl) {
2281		ifa = l->ifa;
2282		if (l->action == SCTP_ADD_IP_ADDRESS) {
2283			/* Clear the defer use flag */
2284			ifa->localifa_flags &= ~SCTP_ADDR_DEFER_USE;
2285		}
2286		sctp_free_ifa(ifa);
2287		SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), l);
2288		SCTP_DECR_LADDR_COUNT();
2289	}
2290	SCTP_FREE(asc, SCTP_M_ASC_IT);
2291}
2292
2293/*
2294 * sa is the sockaddr to ask the peer to set primary to.
2295 * returns: 0 = completed, -1 = error
2296 */
2297int32_t
2298sctp_set_primary_ip_address_sa(struct sctp_tcb *stcb, struct sockaddr *sa)
2299{
2300	uint32_t vrf_id;
2301	struct sctp_ifa *ifa;
2302
2303	/* find the ifa for the desired set primary */
2304	vrf_id = stcb->asoc.vrf_id;
2305	ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
2306	if (ifa == NULL) {
2307		/* Invalid address */
2308		return (-1);
2309	}
2310	/* queue an ASCONF:SET_PRIM_ADDR to be sent */
2311	if (!sctp_asconf_queue_add(stcb, ifa, SCTP_SET_PRIM_ADDR)) {
2312		/* set primary queuing succeeded */
2313		SCTPDBG(SCTP_DEBUG_ASCONF1,
2314		    "set_primary_ip_address_sa: queued on tcb=%p, ",
2315		    stcb);
2316		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
2317		if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
2318#ifdef SCTP_TIMER_BASED_ASCONF
2319			sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
2320			    stcb->sctp_ep, stcb,
2321			    stcb->asoc.primary_destination);
2322#else
2323			sctp_send_asconf(stcb, stcb->asoc.primary_destination,
2324			    SCTP_ADDR_NOT_LOCKED);
2325#endif
2326		}
2327	} else {
2328		SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address_sa: failed to add to queue on tcb=%p, ",
2329		    stcb);
2330		SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, sa);
2331		return (-1);
2332	}
2333	return (0);
2334}
2335
2336void
2337sctp_set_primary_ip_address(struct sctp_ifa *ifa)
2338{
2339	struct sctp_inpcb *inp;
2340
2341	/* go through all our PCB's */
2342	LIST_FOREACH(inp, &SCTP_BASE_INFO(listhead), sctp_list) {
2343		struct sctp_tcb *stcb;
2344
2345		/* process for all associations for this endpoint */
2346		LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
2347			/* queue an ASCONF:SET_PRIM_ADDR to be sent */
2348			if (!sctp_asconf_queue_add(stcb, ifa,
2349			    SCTP_SET_PRIM_ADDR)) {
2350				/* set primary queuing succeeded */
2351				SCTPDBG(SCTP_DEBUG_ASCONF1, "set_primary_ip_address: queued on stcb=%p, ",
2352				    stcb);
2353				SCTPDBG_ADDR(SCTP_DEBUG_ASCONF1, &ifa->address.sa);
2354				if (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) {
2355#ifdef SCTP_TIMER_BASED_ASCONF
2356					sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
2357					    stcb->sctp_ep, stcb,
2358					    stcb->asoc.primary_destination);
2359#else
2360					sctp_send_asconf(stcb, stcb->asoc.primary_destination,
2361					    SCTP_ADDR_NOT_LOCKED);
2362#endif
2363				}
2364			}
2365		}		/* for each stcb */
2366	}			/* for each inp */
2367}
2368
2369int
2370sctp_is_addr_pending(struct sctp_tcb *stcb, struct sctp_ifa *sctp_ifa)
2371{
2372	struct sctp_tmit_chunk *chk, *nchk;
2373	unsigned int offset, asconf_limit;
2374	struct sctp_asconf_chunk *acp;
2375	struct sctp_asconf_paramhdr *aph;
2376	uint8_t aparam_buf[SCTP_PARAM_BUFFER_SIZE];
2377	struct sctp_ipv6addr_param *p_addr;
2378	int add_cnt, del_cnt;
2379	uint16_t last_param_type;
2380
2381	add_cnt = del_cnt = 0;
2382	last_param_type = 0;
2383	TAILQ_FOREACH_SAFE(chk, &stcb->asoc.asconf_send_queue, sctp_next, nchk) {
2384		if (chk->data == NULL) {
2385			SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: No mbuf data?\n");
2386			continue;
2387		}
2388		offset = 0;
2389		acp = mtod(chk->data, struct sctp_asconf_chunk *);
2390		offset += sizeof(struct sctp_asconf_chunk);
2391		asconf_limit = ntohs(acp->ch.chunk_length);
2392		p_addr = (struct sctp_ipv6addr_param *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_paramhdr), aparam_buf);
2393		if (p_addr == NULL) {
2394			SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get lookup addr!\n");
2395			continue;
2396		}
2397		offset += ntohs(p_addr->ph.param_length);
2398
2399		aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
2400		if (aph == NULL) {
2401			SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: Empty ASCONF will be sent?\n");
2402			continue;
2403		}
2404		while (aph != NULL) {
2405			unsigned int param_length, param_type;
2406
2407			param_type = ntohs(aph->ph.param_type);
2408			param_length = ntohs(aph->ph.param_length);
2409			if (offset + param_length > asconf_limit) {
2410				/* parameter goes beyond end of chunk! */
2411				break;
2412			}
2413			if (param_length > sizeof(aparam_buf)) {
2414				SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length (%u) larger than buffer size!\n", param_length);
2415				break;
2416			}
2417			if (param_length <= sizeof(struct sctp_paramhdr)) {
2418				SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: param length(%u) too short\n", param_length);
2419				break;
2420			}
2421			aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, param_length, aparam_buf);
2422			if (aph == NULL) {
2423				SCTPDBG(SCTP_DEBUG_ASCONF1, "is_addr_pending: couldn't get entire param\n");
2424				break;
2425			}
2426			p_addr = (struct sctp_ipv6addr_param *)(aph + 1);
2427			if (sctp_addr_match(p_addr, &sctp_ifa->address.sa) != 0) {
2428				switch (param_type) {
2429				case SCTP_ADD_IP_ADDRESS:
2430					add_cnt++;
2431					break;
2432				case SCTP_DEL_IP_ADDRESS:
2433					del_cnt++;
2434					break;
2435				default:
2436					break;
2437				}
2438				last_param_type = param_type;
2439			}
2440			offset += SCTP_SIZE32(param_length);
2441			if (offset >= asconf_limit) {
2442				/* no more data in the mbuf chain */
2443				break;
2444			}
2445			/* get pointer to next asconf param */
2446			aph = (struct sctp_asconf_paramhdr *)sctp_m_getptr(chk->data, offset, sizeof(struct sctp_asconf_paramhdr), aparam_buf);
2447		}
2448	}
2449
2450	/*
2451	 * we want to find the sequences which consist of ADD -> DEL -> ADD
2452	 * or DEL -> ADD
2453	 */
2454	if (add_cnt > del_cnt ||
2455	    (add_cnt == del_cnt && last_param_type == SCTP_ADD_IP_ADDRESS)) {
2456		return 1;
2457	}
2458	return 0;
2459}
2460
2461static struct sockaddr *
2462sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked)
2463{
2464	struct sctp_vrf *vrf = NULL;
2465	struct sctp_ifn *sctp_ifn;
2466	struct sctp_ifa *sctp_ifa;
2467
2468	if (addr_locked == SCTP_ADDR_NOT_LOCKED)
2469		SCTP_IPI_ADDR_RLOCK();
2470	vrf = sctp_find_vrf(stcb->asoc.vrf_id);
2471	if (vrf == NULL) {
2472		if (addr_locked == SCTP_ADDR_NOT_LOCKED)
2473			SCTP_IPI_ADDR_RUNLOCK();
2474		return (NULL);
2475	}
2476	LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
2477		if (stcb->asoc.loopback_scope == 0 &&
2478		    SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
2479			/* Skip if loopback_scope not set */
2480			continue;
2481		}
2482		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
2483			if (sctp_ifa->address.sa.sa_family == AF_INET &&
2484			    stcb->asoc.ipv4_addr_legal) {
2485				struct sockaddr_in *sin;
2486
2487				sin = (struct sockaddr_in *)&sctp_ifa->address.sa;
2488				if (sin->sin_addr.s_addr == 0) {
2489					/* skip unspecifed addresses */
2490					continue;
2491				}
2492				if (stcb->asoc.ipv4_local_scope == 0 &&
2493				    IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))
2494					continue;
2495
2496				if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
2497				    (!sctp_is_addr_pending(stcb, sctp_ifa)))
2498					continue;
2499				/* found a valid local v4 address to use */
2500				if (addr_locked == SCTP_ADDR_NOT_LOCKED)
2501					SCTP_IPI_ADDR_RUNLOCK();
2502				return (&sctp_ifa->address.sa);
2503			} else if (sctp_ifa->address.sa.sa_family == AF_INET6 &&
2504			    stcb->asoc.ipv6_addr_legal) {
2505				struct sockaddr_in6 *sin6;
2506
2507				if (sctp_ifa->localifa_flags & SCTP_ADDR_IFA_UNUSEABLE) {
2508					continue;
2509				}
2510				sin6 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
2511				if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2512					/* we skip unspecifed addresses */
2513					continue;
2514				}
2515				if (stcb->asoc.local_scope == 0 &&
2516				    IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
2517					continue;
2518				if (stcb->asoc.site_scope == 0 &&
2519				    IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))
2520					continue;
2521
2522				if (sctp_is_addr_restricted(stcb, sctp_ifa) &&
2523				    (!sctp_is_addr_pending(stcb, sctp_ifa)))
2524					continue;
2525				/* found a valid local v6 address to use */
2526				if (addr_locked == SCTP_ADDR_NOT_LOCKED)
2527					SCTP_IPI_ADDR_RUNLOCK();
2528				return (&sctp_ifa->address.sa);
2529			}
2530		}
2531	}
2532	/* no valid addresses found */
2533	if (addr_locked == SCTP_ADDR_NOT_LOCKED)
2534		SCTP_IPI_ADDR_RUNLOCK();
2535	return (NULL);
2536}
2537
2538static struct sockaddr *
2539sctp_find_valid_localaddr_ep(struct sctp_tcb *stcb)
2540{
2541	struct sctp_laddr *laddr;
2542
2543	LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
2544		if (laddr->ifa == NULL) {
2545			continue;
2546		}
2547		/* is the address restricted ? */
2548		if (sctp_is_addr_restricted(stcb, laddr->ifa) &&
2549		    (!sctp_is_addr_pending(stcb, laddr->ifa)))
2550			continue;
2551
2552		/* found a valid local address to use */
2553		return (&laddr->ifa->address.sa);
2554	}
2555	/* no valid addresses found */
2556	return (NULL);
2557}
2558
2559/*
2560 * builds an ASCONF chunk from queued ASCONF params.
2561 * returns NULL on error (no mbuf, no ASCONF params queued, etc).
2562 */
2563struct mbuf *
2564sctp_compose_asconf(struct sctp_tcb *stcb, int *retlen, int addr_locked)
2565{
2566	struct mbuf *m_asconf, *m_asconf_chk;
2567	struct sctp_asconf_addr *aa;
2568	struct sctp_asconf_chunk *acp;
2569	struct sctp_asconf_paramhdr *aph;
2570	struct sctp_asconf_addr_param *aap;
2571	uint32_t p_length;
2572	uint32_t correlation_id = 1;	/* 0 is reserved... */
2573	caddr_t ptr, lookup_ptr;
2574	uint8_t lookup_used = 0;
2575
2576	/* are there any asconf params to send? */
2577	TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
2578		if (aa->sent == 0)
2579			break;
2580	}
2581	if (aa == NULL)
2582		return (NULL);
2583
2584	/*
2585	 * get a chunk header mbuf and a cluster for the asconf params since
2586	 * it's simpler to fill in the asconf chunk header lookup address on
2587	 * the fly
2588	 */
2589	m_asconf_chk = sctp_get_mbuf_for_msg(sizeof(struct sctp_asconf_chunk), 0, M_DONTWAIT, 1, MT_DATA);
2590	if (m_asconf_chk == NULL) {
2591		/* no mbuf's */
2592		SCTPDBG(SCTP_DEBUG_ASCONF1,
2593		    "compose_asconf: couldn't get chunk mbuf!\n");
2594		return (NULL);
2595	}
2596	m_asconf = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA);
2597	if (m_asconf == NULL) {
2598		/* no mbuf's */
2599		SCTPDBG(SCTP_DEBUG_ASCONF1,
2600		    "compose_asconf: couldn't get mbuf!\n");
2601		sctp_m_freem(m_asconf_chk);
2602		return (NULL);
2603	}
2604	SCTP_BUF_LEN(m_asconf_chk) = sizeof(struct sctp_asconf_chunk);
2605	SCTP_BUF_LEN(m_asconf) = 0;
2606	acp = mtod(m_asconf_chk, struct sctp_asconf_chunk *);
2607	bzero(acp, sizeof(struct sctp_asconf_chunk));
2608	/* save pointers to lookup address and asconf params */
2609	lookup_ptr = (caddr_t)(acp + 1);	/* after the header */
2610	ptr = mtod(m_asconf, caddr_t);	/* beginning of cluster */
2611
2612	/* fill in chunk header info */
2613	acp->ch.chunk_type = SCTP_ASCONF;
2614	acp->ch.chunk_flags = 0;
2615	acp->serial_number = htonl(stcb->asoc.asconf_seq_out);
2616	stcb->asoc.asconf_seq_out++;
2617
2618	/* add parameters... up to smallest MTU allowed */
2619	TAILQ_FOREACH(aa, &stcb->asoc.asconf_queue, next) {
2620		if (aa->sent)
2621			continue;
2622		/* get the parameter length */
2623		p_length = SCTP_SIZE32(aa->ap.aph.ph.param_length);
2624		/* will it fit in current chunk? */
2625		if (SCTP_BUF_LEN(m_asconf) + p_length > stcb->asoc.smallest_mtu) {
2626			/* won't fit, so we're done with this chunk */
2627			break;
2628		}
2629		/* assign (and store) a correlation id */
2630		aa->ap.aph.correlation_id = correlation_id++;
2631
2632		/*
2633		 * fill in address if we're doing a delete this is a simple
2634		 * way for us to fill in the correlation address, which
2635		 * should only be used by the peer if we're deleting our
2636		 * source address and adding a new address (e.g. renumbering
2637		 * case)
2638		 */
2639		if (lookup_used == 0 &&
2640		    (aa->special_del == 0) &&
2641		    aa->ap.aph.ph.param_type == SCTP_DEL_IP_ADDRESS) {
2642			struct sctp_ipv6addr_param *lookup;
2643			uint16_t p_size, addr_size;
2644
2645			lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
2646			lookup->ph.param_type =
2647			    htons(aa->ap.addrp.ph.param_type);
2648			if (aa->ap.addrp.ph.param_type == SCTP_IPV6_ADDRESS) {
2649				/* copy IPv6 address */
2650				p_size = sizeof(struct sctp_ipv6addr_param);
2651				addr_size = sizeof(struct in6_addr);
2652			} else {
2653				/* copy IPv4 address */
2654				p_size = sizeof(struct sctp_ipv4addr_param);
2655				addr_size = sizeof(struct in_addr);
2656			}
2657			lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
2658			memcpy(lookup->addr, &aa->ap.addrp.addr, addr_size);
2659			SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
2660			lookup_used = 1;
2661		}
2662		/* copy into current space */
2663		memcpy(ptr, &aa->ap, p_length);
2664
2665		/* network elements and update lengths */
2666		aph = (struct sctp_asconf_paramhdr *)ptr;
2667		aap = (struct sctp_asconf_addr_param *)ptr;
2668		/* correlation_id is transparent to peer, no htonl needed */
2669		aph->ph.param_type = htons(aph->ph.param_type);
2670		aph->ph.param_length = htons(aph->ph.param_length);
2671		aap->addrp.ph.param_type = htons(aap->addrp.ph.param_type);
2672		aap->addrp.ph.param_length = htons(aap->addrp.ph.param_length);
2673
2674		SCTP_BUF_LEN(m_asconf) += SCTP_SIZE32(p_length);
2675		ptr += SCTP_SIZE32(p_length);
2676
2677		/*
2678		 * these params are removed off the pending list upon
2679		 * getting an ASCONF-ACK back from the peer, just set flag
2680		 */
2681		aa->sent = 1;
2682	}
2683	/* check to see if the lookup addr has been populated yet */
2684	if (lookup_used == 0) {
2685		/* NOTE: if the address param is optional, can skip this... */
2686		/* add any valid (existing) address... */
2687		struct sctp_ipv6addr_param *lookup;
2688		uint16_t p_size, addr_size;
2689		struct sockaddr *found_addr;
2690		caddr_t addr_ptr;
2691
2692		if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL)
2693			found_addr = sctp_find_valid_localaddr(stcb,
2694			    addr_locked);
2695		else
2696			found_addr = sctp_find_valid_localaddr_ep(stcb);
2697
2698		lookup = (struct sctp_ipv6addr_param *)lookup_ptr;
2699		if (found_addr != NULL) {
2700			if (found_addr->sa_family == AF_INET6) {
2701				/* copy IPv6 address */
2702				lookup->ph.param_type =
2703				    htons(SCTP_IPV6_ADDRESS);
2704				p_size = sizeof(struct sctp_ipv6addr_param);
2705				addr_size = sizeof(struct in6_addr);
2706				addr_ptr = (caddr_t)&((struct sockaddr_in6 *)
2707				    found_addr)->sin6_addr;
2708			} else {
2709				/* copy IPv4 address */
2710				lookup->ph.param_type =
2711				    htons(SCTP_IPV4_ADDRESS);
2712				p_size = sizeof(struct sctp_ipv4addr_param);
2713				addr_size = sizeof(struct in_addr);
2714				addr_ptr = (caddr_t)&((struct sockaddr_in *)
2715				    found_addr)->sin_addr;
2716			}
2717			lookup->ph.param_length = htons(SCTP_SIZE32(p_size));
2718			memcpy(lookup->addr, addr_ptr, addr_size);
2719			SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(p_size);
2720			lookup_used = 1;
2721		} else {
2722			/* uh oh... don't have any address?? */
2723			SCTPDBG(SCTP_DEBUG_ASCONF1,
2724			    "compose_asconf: no lookup addr!\n");
2725			/* for now, we send a IPv4 address of 0.0.0.0 */
2726			lookup->ph.param_type = htons(SCTP_IPV4_ADDRESS);
2727			lookup->ph.param_length = htons(SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param)));
2728			bzero(lookup->addr, sizeof(struct in_addr));
2729			SCTP_BUF_LEN(m_asconf_chk) += SCTP_SIZE32(sizeof(struct sctp_ipv4addr_param));
2730			lookup_used = 1;
2731		}
2732	}
2733	/* chain it all together */
2734	SCTP_BUF_NEXT(m_asconf_chk) = m_asconf;
2735	*retlen = SCTP_BUF_LEN(m_asconf_chk) + SCTP_BUF_LEN(m_asconf);
2736	acp->ch.chunk_length = ntohs(*retlen);
2737
2738	return (m_asconf_chk);
2739}
2740
2741/*
2742 * section to handle address changes before an association is up eg. changes
2743 * during INIT/INIT-ACK/COOKIE-ECHO handshake
2744 */
2745
2746/*
2747 * processes the (local) addresses in the INIT-ACK chunk
2748 */
2749static void
2750sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m,
2751    unsigned int offset, unsigned int length)
2752{
2753	struct sctp_paramhdr tmp_param, *ph;
2754	uint16_t plen, ptype;
2755	struct sctp_ifa *sctp_ifa;
2756	struct sctp_ipv6addr_param addr_store;
2757	struct sockaddr_in6 sin6;
2758	struct sockaddr_in sin;
2759	struct sockaddr *sa;
2760	uint32_t vrf_id;
2761
2762	SCTPDBG(SCTP_DEBUG_ASCONF2, "processing init-ack addresses\n");
2763	if (stcb == NULL)	/* Un-needed check for SA */
2764		return;
2765
2766	/* convert to upper bound */
2767	length += offset;
2768
2769	if ((offset + sizeof(struct sctp_paramhdr)) > length) {
2770		return;
2771	}
2772	/* init the addresses */
2773	bzero(&sin6, sizeof(sin6));
2774	sin6.sin6_family = AF_INET6;
2775	sin6.sin6_len = sizeof(sin6);
2776	sin6.sin6_port = stcb->rport;
2777
2778	bzero(&sin, sizeof(sin));
2779	sin.sin_len = sizeof(sin);
2780	sin.sin_family = AF_INET;
2781	sin.sin_port = stcb->rport;
2782
2783	/* go through the addresses in the init-ack */
2784	ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
2785	    sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
2786	while (ph != NULL) {
2787		ptype = ntohs(ph->param_type);
2788		plen = ntohs(ph->param_length);
2789		if (ptype == SCTP_IPV6_ADDRESS) {
2790			struct sctp_ipv6addr_param *a6p;
2791
2792			/* get the entire IPv6 address param */
2793			a6p = (struct sctp_ipv6addr_param *)
2794			    sctp_m_getptr(m, offset,
2795			    sizeof(struct sctp_ipv6addr_param),
2796			    (uint8_t *) & addr_store);
2797			if (plen != sizeof(struct sctp_ipv6addr_param) ||
2798			    a6p == NULL) {
2799				return;
2800			}
2801			memcpy(&sin6.sin6_addr, a6p->addr,
2802			    sizeof(struct in6_addr));
2803			sa = (struct sockaddr *)&sin6;
2804		} else if (ptype == SCTP_IPV4_ADDRESS) {
2805			struct sctp_ipv4addr_param *a4p;
2806
2807			/* get the entire IPv4 address param */
2808			a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m, offset,
2809			    sizeof(struct sctp_ipv4addr_param),
2810			    (uint8_t *) & addr_store);
2811			if (plen != sizeof(struct sctp_ipv4addr_param) ||
2812			    a4p == NULL) {
2813				return;
2814			}
2815			sin.sin_addr.s_addr = a4p->addr;
2816			sa = (struct sockaddr *)&sin;
2817		} else {
2818			goto next_addr;
2819		}
2820
2821		/* see if this address really (still) exists */
2822		if (stcb) {
2823			vrf_id = stcb->asoc.vrf_id;
2824		} else {
2825			vrf_id = SCTP_DEFAULT_VRFID;
2826		}
2827		sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id,
2828		    SCTP_ADDR_NOT_LOCKED);
2829		if (sctp_ifa == NULL) {
2830			/* address doesn't exist anymore */
2831			int status;
2832
2833			/* are ASCONFs allowed ? */
2834			if ((sctp_is_feature_on(stcb->sctp_ep,
2835			    SCTP_PCB_FLAGS_DO_ASCONF)) &&
2836			    stcb->asoc.peer_supports_asconf) {
2837				/* queue an ASCONF DEL_IP_ADDRESS */
2838				status = sctp_asconf_queue_sa_delete(stcb, sa);
2839				/*
2840				 * if queued ok, and in correct state, send
2841				 * out the ASCONF.
2842				 */
2843				if (status == 0 &&
2844				    SCTP_GET_STATE(&stcb->asoc) ==
2845				    SCTP_STATE_OPEN) {
2846#ifdef SCTP_TIMER_BASED_ASCONF
2847					sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
2848					    stcb->sctp_ep, stcb,
2849					    stcb->asoc.primary_destination);
2850#else
2851					sctp_send_asconf(stcb, stcb->asoc.primary_destination,
2852					    SCTP_ADDR_NOT_LOCKED);
2853#endif
2854				}
2855			}
2856		}
2857next_addr:
2858		/*
2859		 * Sanity check:  Make sure the length isn't 0, otherwise
2860		 * we'll be stuck in this loop for a long time...
2861		 */
2862		if (SCTP_SIZE32(plen) == 0) {
2863			SCTP_PRINTF("process_initack_addrs: bad len (%d) type=%xh\n",
2864			    plen, ptype);
2865			return;
2866		}
2867		/* get next parameter */
2868		offset += SCTP_SIZE32(plen);
2869		if ((offset + sizeof(struct sctp_paramhdr)) > length)
2870			return;
2871		ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
2872		    sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
2873	}			/* while */
2874}
2875
2876/* FIX ME: need to verify return result for v6 address type if v6 disabled */
2877/*
2878 * checks to see if a specific address is in the initack address list returns
2879 * 1 if found, 0 if not
2880 */
2881static uint32_t
2882sctp_addr_in_initack(struct sctp_tcb *stcb, struct mbuf *m, uint32_t offset,
2883    uint32_t length, struct sockaddr *sa)
2884{
2885	struct sctp_paramhdr tmp_param, *ph;
2886	uint16_t plen, ptype;
2887	struct sctp_ipv6addr_param addr_store;
2888	struct sockaddr_in *sin;
2889	struct sctp_ipv4addr_param *a4p;
2890
2891#ifdef INET6
2892	struct sockaddr_in6 *sin6;
2893	struct sctp_ipv6addr_param *a6p;
2894	struct sockaddr_in6 sin6_tmp;
2895
2896#endif				/* INET6 */
2897
2898	if (
2899#ifdef INET6
2900	    (sa->sa_family != AF_INET6) &&
2901#endif				/* INET6 */
2902	    (sa->sa_family != AF_INET))
2903		return (0);
2904
2905	SCTPDBG(SCTP_DEBUG_ASCONF2, "find_initack_addr: starting search for ");
2906	SCTPDBG_ADDR(SCTP_DEBUG_ASCONF2, sa);
2907	/* convert to upper bound */
2908	length += offset;
2909
2910	if ((offset + sizeof(struct sctp_paramhdr)) > length) {
2911		SCTPDBG(SCTP_DEBUG_ASCONF1,
2912		    "find_initack_addr: invalid offset?\n");
2913		return (0);
2914	}
2915	/* go through the addresses in the init-ack */
2916	ph = (struct sctp_paramhdr *)sctp_m_getptr(m, offset,
2917	    sizeof(struct sctp_paramhdr), (uint8_t *) & tmp_param);
2918	while (ph != NULL) {
2919		ptype = ntohs(ph->param_type);
2920		plen = ntohs(ph->param_length);
2921#ifdef INET6
2922		if (ptype == SCTP_IPV6_ADDRESS && sa->sa_family == AF_INET6) {
2923			/* get the entire IPv6 address param */
2924			a6p = (struct sctp_ipv6addr_param *)
2925			    sctp_m_getptr(m, offset,
2926			    sizeof(struct sctp_ipv6addr_param),
2927			    (uint8_t *) & addr_store);
2928			if (plen != sizeof(struct sctp_ipv6addr_param) ||
2929			    (ph == NULL) ||
2930			    (a6p == NULL)) {
2931				return (0);
2932			}
2933			sin6 = (struct sockaddr_in6 *)sa;
2934			if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
2935				/* create a copy and clear scope */
2936				memcpy(&sin6_tmp, sin6,
2937				    sizeof(struct sockaddr_in6));
2938				sin6 = &sin6_tmp;
2939				in6_clearscope(&sin6->sin6_addr);
2940			}
2941			if (memcmp(&sin6->sin6_addr, a6p->addr,
2942			    sizeof(struct in6_addr)) == 0) {
2943				/* found it */
2944				return (1);
2945			}
2946		} else
2947#endif				/* INET6 */
2948
2949			if (ptype == SCTP_IPV4_ADDRESS &&
2950		    sa->sa_family == AF_INET) {
2951			/* get the entire IPv4 address param */
2952			a4p = (struct sctp_ipv4addr_param *)sctp_m_getptr(m,
2953			    offset, sizeof(struct sctp_ipv4addr_param),
2954			    (uint8_t *) & addr_store);
2955			if (plen != sizeof(struct sctp_ipv4addr_param) ||
2956			    (ph == NULL) ||
2957			    (a4p == NULL)) {
2958				return (0);
2959			}
2960			sin = (struct sockaddr_in *)sa;
2961			if (sin->sin_addr.s_addr == a4p->addr) {
2962				/* found it */
2963				return (1);
2964			}
2965		}
2966		/* get next parameter */
2967		offset += SCTP_SIZE32(plen);
2968		if (offset + sizeof(struct sctp_paramhdr) > length)
2969			return (0);
2970		ph = (struct sctp_paramhdr *)
2971		    sctp_m_getptr(m, offset, sizeof(struct sctp_paramhdr),
2972		    (uint8_t *) & tmp_param);
2973	}			/* while */
2974	/* not found! */
2975	return (0);
2976}
2977
2978/*
2979 * makes sure that the current endpoint local addr list is consistent with
2980 * the new association (eg. subset bound, asconf allowed) adds addresses as
2981 * necessary
2982 */
2983static void
2984sctp_check_address_list_ep(struct sctp_tcb *stcb, struct mbuf *m, int offset,
2985    int length, struct sockaddr *init_addr)
2986{
2987	struct sctp_laddr *laddr;
2988
2989	/* go through the endpoint list */
2990	LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
2991		/* be paranoid and validate the laddr */
2992		if (laddr->ifa == NULL) {
2993			SCTPDBG(SCTP_DEBUG_ASCONF1,
2994			    "check_addr_list_ep: laddr->ifa is NULL");
2995			continue;
2996		}
2997		if (laddr->ifa == NULL) {
2998			SCTPDBG(SCTP_DEBUG_ASCONF1, "check_addr_list_ep: laddr->ifa->ifa_addr is NULL");
2999			continue;
3000		}
3001		/* do i have it implicitly? */
3002		if (sctp_cmpaddr(&laddr->ifa->address.sa, init_addr)) {
3003			continue;
3004		}
3005		/* check to see if in the init-ack */
3006		if (!sctp_addr_in_initack(stcb, m, offset, length,
3007		    &laddr->ifa->address.sa)) {
3008			/* try to add it */
3009			sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb, laddr->ifa,
3010			    SCTP_ADD_IP_ADDRESS, SCTP_ADDR_NOT_LOCKED);
3011		}
3012	}
3013}
3014
3015/*
3016 * makes sure that the current kernel address list is consistent with the new
3017 * association (with all addrs bound) adds addresses as necessary
3018 */
3019static void
3020sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
3021    int length, struct sockaddr *init_addr,
3022    uint16_t local_scope, uint16_t site_scope,
3023    uint16_t ipv4_scope, uint16_t loopback_scope)
3024{
3025	struct sctp_vrf *vrf = NULL;
3026	struct sctp_ifn *sctp_ifn;
3027	struct sctp_ifa *sctp_ifa;
3028	uint32_t vrf_id;
3029
3030	if (stcb) {
3031		vrf_id = stcb->asoc.vrf_id;
3032	} else {
3033		return;
3034	}
3035	SCTP_IPI_ADDR_RLOCK();
3036	vrf = sctp_find_vrf(vrf_id);
3037	if (vrf == NULL) {
3038		SCTP_IPI_ADDR_RUNLOCK();
3039		return;
3040	}
3041	/* go through all our known interfaces */
3042	LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
3043		if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
3044			/* skip loopback interface */
3045			continue;
3046		}
3047		/* go through each interface address */
3048		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
3049			/* do i have it implicitly? */
3050			if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) {
3051				continue;
3052			}
3053			/* check to see if in the init-ack */
3054			if (!sctp_addr_in_initack(stcb, m, offset, length,
3055			    &sctp_ifa->address.sa)) {
3056				/* try to add it */
3057				sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb,
3058				    sctp_ifa, SCTP_ADD_IP_ADDRESS,
3059				    SCTP_ADDR_LOCKED);
3060			}
3061		}		/* end foreach ifa */
3062	}			/* end foreach ifn */
3063	SCTP_IPI_ADDR_RUNLOCK();
3064}
3065
3066/*
3067 * validates an init-ack chunk (from a cookie-echo) with current addresses
3068 * adds addresses from the init-ack into our local address list, if needed
3069 * queues asconf adds/deletes addresses as needed and makes appropriate list
3070 * changes for source address selection m, offset: points to the start of the
3071 * address list in an init-ack chunk length: total length of the address
3072 * params only init_addr: address where my INIT-ACK was sent from
3073 */
3074void
3075sctp_check_address_list(struct sctp_tcb *stcb, struct mbuf *m, int offset,
3076    int length, struct sockaddr *init_addr,
3077    uint16_t local_scope, uint16_t site_scope,
3078    uint16_t ipv4_scope, uint16_t loopback_scope)
3079{
3080	/* process the local addresses in the initack */
3081	sctp_process_initack_addresses(stcb, m, offset, length);
3082
3083	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3084		/* bound all case */
3085		sctp_check_address_list_all(stcb, m, offset, length, init_addr,
3086		    local_scope, site_scope, ipv4_scope, loopback_scope);
3087	} else {
3088		/* subset bound case */
3089		if (sctp_is_feature_on(stcb->sctp_ep,
3090		    SCTP_PCB_FLAGS_DO_ASCONF)) {
3091			/* asconf's allowed */
3092			sctp_check_address_list_ep(stcb, m, offset, length,
3093			    init_addr);
3094		}
3095		/* else, no asconfs allowed, so what we sent is what we get */
3096	}
3097}
3098
3099/*
3100 * sctp_bindx() support
3101 */
3102uint32_t
3103sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa,
3104    uint32_t type, uint32_t vrf_id, struct sctp_ifa *sctp_ifap)
3105{
3106	struct sctp_ifa *ifa;
3107
3108	if (sa->sa_len == 0) {
3109		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
3110		return (EINVAL);
3111	}
3112	if (sctp_ifap) {
3113		ifa = sctp_ifap;
3114	} else if (type == SCTP_ADD_IP_ADDRESS) {
3115		/* For an add the address MUST be on the system */
3116		ifa = sctp_find_ifa_by_addr(sa, vrf_id, SCTP_ADDR_NOT_LOCKED);
3117	} else if (type == SCTP_DEL_IP_ADDRESS) {
3118		/* For a delete we need to find it in the inp */
3119		ifa = sctp_find_ifa_in_ep(inp, sa, SCTP_ADDR_NOT_LOCKED);
3120	} else {
3121		ifa = NULL;
3122	}
3123	if (ifa != NULL) {
3124		if (type == SCTP_ADD_IP_ADDRESS) {
3125			sctp_add_local_addr_ep(inp, ifa, type);
3126		} else if (type == SCTP_DEL_IP_ADDRESS) {
3127			struct sctp_laddr *laddr;
3128
3129			if (inp->laddr_count < 2) {
3130				/* can't delete the last local address */
3131				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL);
3132				return (EINVAL);
3133			}
3134			LIST_FOREACH(laddr, &inp->sctp_addr_list,
3135			    sctp_nxt_addr) {
3136				if (ifa == laddr->ifa) {
3137					/* Mark in the delete */
3138					laddr->action = type;
3139				}
3140			}
3141		}
3142		if (!LIST_EMPTY(&inp->sctp_asoc_list)) {
3143			/*
3144			 * There is no need to start the iterator if the inp
3145			 * has no associations.
3146			 */
3147			struct sctp_asconf_iterator *asc;
3148			struct sctp_laddr *wi;
3149
3150			SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
3151			    sizeof(struct sctp_asconf_iterator),
3152			    SCTP_M_ASC_IT);
3153			if (asc == NULL) {
3154				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
3155				return (ENOMEM);
3156			}
3157			wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr);
3158			if (wi == NULL) {
3159				SCTP_FREE(asc, SCTP_M_ASC_IT);
3160				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM);
3161				return (ENOMEM);
3162			}
3163			LIST_INIT(&asc->list_of_work);
3164			asc->cnt = 1;
3165			SCTP_INCR_LADDR_COUNT();
3166			wi->ifa = ifa;
3167			wi->action = type;
3168			atomic_add_int(&ifa->refcount, 1);
3169			LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
3170			(void)sctp_initiate_iterator(sctp_asconf_iterator_ep,
3171			    sctp_asconf_iterator_stcb,
3172			    sctp_asconf_iterator_ep_end,
3173			    SCTP_PCB_ANY_FLAGS,
3174			    SCTP_PCB_ANY_FEATURES,
3175			    SCTP_ASOC_ANY_STATE,
3176			    (void *)asc, 0,
3177			    sctp_asconf_iterator_end, inp, 0);
3178		}
3179		return (0);
3180	} else {
3181		/* invalid address! */
3182		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL);
3183		return (EADDRNOTAVAIL);
3184	}
3185}
3186
3187void
3188sctp_asconf_send_nat_state_update(struct sctp_tcb *stcb,
3189    struct sctp_nets *net)
3190{
3191	struct sctp_asconf_addr *aa;
3192	struct sctp_ifa *sctp_ifap;
3193	struct sctp_asconf_tag_param *vtag;
3194	struct sockaddr_in *to;
3195
3196#ifdef INET6
3197	struct sockaddr_in6 *to6;
3198
3199#endif
3200	if (net == NULL) {
3201		SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing net\n");
3202		return;
3203	}
3204	if (stcb == NULL) {
3205		SCTPDBG(SCTP_DEBUG_ASCONF1, "sctp_asconf_send_nat_state_update: Missing stcb\n");
3206		return;
3207	}
3208	/*
3209	 * Need to have in the asconf: - vtagparam(my_vtag/peer_vtag) -
3210	 * add(0.0.0.0) - del(0.0.0.0) - Any global addresses add(addr)
3211	 */
3212	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
3213	    SCTP_M_ASC_ADDR);
3214	if (aa == NULL) {
3215		/* didn't get memory */
3216		SCTPDBG(SCTP_DEBUG_ASCONF1,
3217		    "sctp_asconf_send_nat_state_update: failed to get memory!\n");
3218		return;
3219	}
3220	aa->special_del = 0;
3221	/* fill in asconf address parameter fields */
3222	/* top level elements are "networked" during send */
3223	aa->ifa = NULL;
3224	aa->sent = 0;		/* clear sent flag */
3225	vtag = (struct sctp_asconf_tag_param *)&aa->ap.aph;
3226	vtag->aph.ph.param_type = SCTP_NAT_VTAGS;
3227	vtag->aph.ph.param_length = sizeof(struct sctp_asconf_tag_param);
3228	vtag->local_vtag = htonl(stcb->asoc.my_vtag);
3229	vtag->remote_vtag = htonl(stcb->asoc.peer_vtag);
3230	TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
3231
3232	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
3233	    SCTP_M_ASC_ADDR);
3234	if (aa == NULL) {
3235		/* didn't get memory */
3236		SCTPDBG(SCTP_DEBUG_ASCONF1,
3237		    "sctp_asconf_send_nat_state_update: failed to get memory!\n");
3238		return;
3239	}
3240	memset(aa, 0, sizeof(struct sctp_asconf_addr));
3241	/* fill in asconf address parameter fields */
3242	/* ADD(0.0.0.0) */
3243	if (net->ro._l_addr.sa.sa_family == AF_INET) {
3244		aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
3245		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
3246		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
3247		aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param);
3248		/* No need to add an address, we are using 0.0.0.0 */
3249		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
3250	}
3251#ifdef INET6
3252	else if (net->ro._l_addr.sa.sa_family == AF_INET6) {
3253		aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
3254		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
3255		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
3256		aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param);
3257		/* No need to add an address, we are using 0.0.0.0 */
3258		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
3259	}
3260#endif				/* INET6 */
3261	SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa),
3262	    SCTP_M_ASC_ADDR);
3263	if (aa == NULL) {
3264		/* didn't get memory */
3265		SCTPDBG(SCTP_DEBUG_ASCONF1,
3266		    "sctp_asconf_send_nat_state_update: failed to get memory!\n");
3267		return;
3268	}
3269	memset(aa, 0, sizeof(struct sctp_asconf_addr));
3270	/* fill in asconf address parameter fields */
3271	/* ADD(0.0.0.0) */
3272	if (net->ro._l_addr.sa.sa_family == AF_INET) {
3273		aa->ap.aph.ph.param_type = SCTP_ADD_IP_ADDRESS;
3274		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addrv4_param);
3275		aa->ap.addrp.ph.param_type = SCTP_IPV4_ADDRESS;
3276		aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv4addr_param);
3277		/* No need to add an address, we are using 0.0.0.0 */
3278		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
3279	}
3280#ifdef INET6
3281	else if (net->ro._l_addr.sa.sa_family == AF_INET6) {
3282		aa->ap.aph.ph.param_type = SCTP_DEL_IP_ADDRESS;
3283		aa->ap.aph.ph.param_length = sizeof(struct sctp_asconf_addr_param);
3284		aa->ap.addrp.ph.param_type = SCTP_IPV6_ADDRESS;
3285		aa->ap.addrp.ph.param_length = sizeof(struct sctp_ipv6addr_param);
3286		/* No need to add an address, we are using 0.0.0.0 */
3287		TAILQ_INSERT_TAIL(&stcb->asoc.asconf_queue, aa, next);
3288	}
3289#endif				/* INET6 */
3290	/* Now we must hunt the addresses and add all global addresses */
3291	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3292		struct sctp_vrf *vrf = NULL;
3293		struct sctp_ifn *sctp_ifnp;
3294		uint32_t vrf_id;
3295
3296		vrf_id = stcb->sctp_ep->def_vrf_id;
3297		vrf = sctp_find_vrf(vrf_id);
3298		if (vrf == NULL) {
3299			goto skip_rest;
3300		}
3301		SCTP_IPI_ADDR_RLOCK();
3302		LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
3303			LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
3304				if (sctp_ifap->address.sa.sa_family == AF_INET) {
3305					to = &sctp_ifap->address.sin;
3306
3307					if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
3308						continue;
3309					}
3310					if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
3311						continue;
3312					}
3313				}
3314#ifdef INET6
3315				else if (sctp_ifap->address.sa.sa_family == AF_INET6) {
3316					to6 = &sctp_ifap->address.sin6;
3317					if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
3318						continue;
3319					}
3320					if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
3321						continue;
3322					}
3323				}
3324#endif
3325				sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
3326			}
3327		}
3328		SCTP_IPI_ADDR_RUNLOCK();
3329	} else {
3330		struct sctp_laddr *laddr;
3331
3332		LIST_FOREACH(laddr, &stcb->sctp_ep->sctp_addr_list, sctp_nxt_addr) {
3333			if (laddr->ifa == NULL) {
3334				continue;
3335			}
3336			if (laddr->ifa->localifa_flags & SCTP_BEING_DELETED)
3337				/*
3338				 * Address being deleted by the system, dont
3339				 * list.
3340				 */
3341				continue;
3342			if (laddr->action == SCTP_DEL_IP_ADDRESS) {
3343				/*
3344				 * Address being deleted on this ep don't
3345				 * list.
3346				 */
3347				continue;
3348			}
3349			sctp_ifap = laddr->ifa;
3350			if (sctp_ifap->address.sa.sa_family == AF_INET) {
3351				to = &sctp_ifap->address.sin;
3352
3353				if (IN4_ISPRIVATE_ADDRESS(&to->sin_addr)) {
3354					continue;
3355				}
3356				if (IN4_ISLOOPBACK_ADDRESS(&to->sin_addr)) {
3357					continue;
3358				}
3359			}
3360#ifdef INET6
3361			else if (sctp_ifap->address.sa.sa_family == AF_INET6) {
3362				to6 = &sctp_ifap->address.sin6;
3363				if (IN6_IS_ADDR_LOOPBACK(&to6->sin6_addr)) {
3364					continue;
3365				}
3366				if (IN6_IS_ADDR_LINKLOCAL(&to6->sin6_addr)) {
3367					continue;
3368				}
3369			}
3370#endif
3371			sctp_asconf_queue_mgmt(stcb, sctp_ifap, SCTP_ADD_IP_ADDRESS);
3372		}
3373	}
3374skip_rest:
3375	/* Now we must send the asconf into the queue */
3376	sctp_send_asconf(stcb, net, 0);
3377}
3378