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