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