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