sctp_asconf.c revision 3448:aaf16568054b
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <sys/types.h>
30#include <sys/systm.h>
31#include <sys/stream.h>
32#include <sys/cmn_err.h>
33#include <sys/socket.h>
34#include <sys/kmem.h>
35#include <sys/strsubr.h>
36#include <sys/strsun.h>
37
38#include <netinet/in.h>
39#include <netinet/ip6.h>
40#include <netinet/sctp.h>
41
42#include <inet/common.h>
43#include <inet/ip.h>
44#include <inet/ip6.h>
45#include <inet/mib2.h>
46#include <inet/ipclassifier.h>
47#include "sctp_impl.h"
48#include "sctp_asconf.h"
49#include "sctp_addr.h"
50
51typedef struct sctp_asconf_s {
52	mblk_t		*head;
53	uint32_t 	cid;
54} sctp_asconf_t;
55
56/*
57 * This is only used on a clustered node to maintain pre-allocated buffer info.
58 * before sending an ASCONF chunk. The reason for pre-allocation is we don't
59 * want to fail allocating memory when we get then ASCONF-ACK in order to
60 * update the clustering subsystem's state for this assoc.
61 */
62typedef struct sctp_cl_ainfo_s {
63	uchar_t	*sctp_cl_alist;
64	size_t	sctp_cl_asize;
65	uchar_t	*sctp_cl_dlist;
66	size_t	sctp_cl_dsize;
67} sctp_cl_ainfo_t;
68
69/*
70 * The ASCONF chunk per-parameter request interface. ph is the
71 * parameter header for the parameter in the request, and cid
72 * is the parameters correlation ID. cont should be set to 1
73 * if the ASCONF framework should continue processing request
74 * parameters following this one, or 0 if it should stop. If
75 * cont is -1, this indicates complete memory depletion, which
76 * will cause the ASCONF framework to abort building a reply. If
77 * act is 1, the callback should take whatever action it needs
78 * to fulfil this request. If act is 0, this request has already
79 * been processed, so the callback should only verify and pass
80 * back error parameters, and not take any action.
81 *
82 * The callback should return an mblk with any reply enclosed,
83 * with the correlation ID in the first four bytes of the
84 * message. A NULL return implies implicit success to the
85 * requestor.
86 */
87typedef mblk_t *sctp_asconf_func_t(sctp_t *, sctp_parm_hdr_t *ph, uint32_t cid,
88    sctp_faddr_t *, int *cont, int act, in6_addr_t *addr);
89
90/*
91 * The ASCONF chunk per-parameter ACK interface. ph is the parameter
92 * header for the parameter returned in the ACK, and oph is the
93 * original parameter sent out in the ASCONF request.
94 * If the peer implicitly responded OK (by not including an
95 * explicit OK for the request), ph will be NULL.
96 * ph can also point to an Unrecognized Parameter parameter,
97 * in which case the peer did not understand the request
98 * parameter.
99 *
100 * ph and oph parameter headers are in host byte order. Encapsulated
101 * parameters will still be in network byte order.
102 */
103typedef void sctp_asconf_ack_func_t(sctp_t *, sctp_parm_hdr_t *ph,
104    sctp_parm_hdr_t *oph, sctp_faddr_t *, in6_addr_t *addr);
105
106typedef struct {
107	uint16_t id;
108	sctp_asconf_func_t *asconf;
109	sctp_asconf_ack_func_t *asconf_ack;
110} dispatch_t;
111
112static sctp_asconf_func_t sctp_addip_req, sctp_setprim_req,
113    sctp_asconf_unrec_parm;
114
115static sctp_asconf_ack_func_t sctp_addip_ack, sctp_setprim_ack,
116    sctp_asconf_ack_unrec_parm;
117
118static const dispatch_t sctp_asconf_dispatch_tbl[] = {
119/*	ID			ASCONF			ASCONF_ACK */
120	{ PARM_ADD_IP,		sctp_addip_req,		sctp_addip_ack },
121	{ PARM_DEL_IP,		sctp_addip_req,		sctp_addip_ack },
122	{ PARM_SET_PRIMARY,	sctp_setprim_req,	sctp_setprim_ack }
123};
124
125static const dispatch_t sctp_asconf_default_dispatch = {
126	0, sctp_asconf_unrec_parm, sctp_asconf_ack_unrec_parm
127};
128
129/*
130 * ASCONF framework
131 */
132
133static const dispatch_t *
134sctp_lookup_asconf_dispatch(int id)
135{
136	int i;
137
138	for (i = 0; i < A_CNT(sctp_asconf_dispatch_tbl); i++) {
139		if (sctp_asconf_dispatch_tbl[i].id == id) {
140			return (sctp_asconf_dispatch_tbl + i);
141		}
142	}
143
144	return (&sctp_asconf_default_dispatch);
145}
146
147/*
148 * Frees mp on failure
149 */
150static mblk_t *
151sctp_asconf_prepend_errwrap(mblk_t *mp, uint32_t cid)
152{
153	mblk_t		*wmp;
154	sctp_parm_hdr_t	*wph;
155
156	/* Prepend a wrapper err cause ind param */
157	wmp = allocb(sizeof (*wph) + sizeof (cid), BPRI_MED);
158	if (wmp == NULL) {
159		freemsg(mp);
160		return (NULL);
161	}
162	wmp->b_wptr += sizeof (*wph) + sizeof (cid);
163	wph = (sctp_parm_hdr_t *)wmp->b_rptr;
164	wph->sph_type = htons(PARM_ERROR_IND);
165	wph->sph_len = htons(msgdsize(mp) + sizeof (*wph) + sizeof (cid));
166	bcopy(&cid, wph + 1, sizeof (uint32_t));
167
168	wmp->b_cont = mp;
169	return (wmp);
170}
171
172/*ARGSUSED*/
173static mblk_t *
174sctp_asconf_unrec_parm(sctp_t *sctp, sctp_parm_hdr_t *ph, uint32_t cid,
175    sctp_faddr_t *fp, int *cont, int act, in6_addr_t *addr)
176{
177	mblk_t *mp = NULL;
178
179	/* Unrecognized param; check the high order bits */
180	if ((ph->sph_type & 0xc000) == 0xc000) {
181		/* report unrecognized param, and keep processing */
182		sctp_add_unrec_parm(ph, &mp);
183		if (mp == NULL) {
184			*cont = -1;
185			return (NULL);
186		}
187		/* Prepend a the CID and a wrapper err cause ind param */
188		mp = sctp_asconf_prepend_errwrap(mp, cid);
189		if (mp == NULL) {
190			*cont = -1;
191			return (NULL);
192		}
193
194		*cont = 1;
195		return (mp);
196	}
197	if (ph->sph_type & 0x4000) {
198		/* Stop processing and drop; report unrecognized param */
199		sctp_add_unrec_parm(ph, &mp);
200		if (mp == NULL) {
201			*cont = -1;
202			return (NULL);
203		}
204		/* Prepend a the CID and a wrapper err cause ind param */
205		mp = sctp_asconf_prepend_errwrap(mp, cid);
206		if (mp == NULL) {
207			*cont = -1;
208			return (NULL);
209		}
210
211		*cont = 0;
212		return (mp);
213	}
214	if (ph->sph_type & 0x8000) {
215		/* skip and continue processing */
216		*cont = 1;
217		return (NULL);
218	}
219
220	/* 2 high bits are clear; stop processing and drop packet */
221	*cont = 0;
222	return (NULL);
223}
224
225/*ARGSUSED*/
226static void
227sctp_asconf_ack_unrec_parm(sctp_t *sctp, sctp_parm_hdr_t *ph,
228    sctp_parm_hdr_t *oph, sctp_faddr_t *fp, in6_addr_t *laddr)
229{
230	ASSERT(ph);
231	sctp_error_event(sctp, (sctp_chunk_hdr_t *)ph);
232}
233
234static void
235sctp_asconf_init(sctp_asconf_t *asc)
236{
237	ASSERT(asc != NULL);
238
239	asc->head = NULL;
240	asc->cid = 0;
241}
242
243static int
244sctp_asconf_add(sctp_asconf_t *asc, mblk_t *mp)
245{
246	uint32_t *cp;
247
248	/* XXX can't exceed MTU */
249
250	cp = (uint32_t *)(mp->b_rptr + sizeof (sctp_parm_hdr_t));
251	*cp = asc->cid++;
252
253	if (asc->head == NULL)
254		asc->head = mp;
255	else
256		linkb(asc->head, mp);
257
258	return (0);
259}
260
261static void
262sctp_asconf_destroy(sctp_asconf_t *asc)
263{
264	if (asc->head != NULL) {
265		freemsg(asc->head);
266		asc->head = NULL;
267	}
268	asc->cid = 0;
269}
270
271static int
272sctp_asconf_send(sctp_t *sctp, sctp_asconf_t *asc, sctp_faddr_t *fp,
273    sctp_cl_ainfo_t *ainfo)
274{
275	mblk_t			*mp, *nmp;
276	sctp_chunk_hdr_t	*ch;
277	boolean_t		isv4;
278	size_t			msgsize;
279
280	ASSERT(asc != NULL && asc->head != NULL);
281
282	isv4 = (fp != NULL) ? fp->isv4 : sctp->sctp_current->isv4;
283
284	/* SCTP chunk header + Serial Number + Address Param TLV */
285	msgsize = sizeof (*ch) + sizeof (uint32_t) +
286	    (isv4 ? PARM_ADDR4_LEN : PARM_ADDR6_LEN);
287
288	mp = allocb(msgsize, BPRI_MED);
289	if (mp == NULL)
290		return (ENOMEM);
291
292	mp->b_wptr += msgsize;
293	mp->b_cont = asc->head;
294
295	ch = (sctp_chunk_hdr_t *)mp->b_rptr;
296	ch->sch_id = CHUNK_ASCONF;
297	ch->sch_flags = 0;
298	ch->sch_len = htons(msgdsize(mp));
299
300	nmp = msgpullup(mp, -1);
301	if (nmp == NULL) {
302		freeb(mp);
303		return (ENOMEM);
304	}
305
306	/*
307	 * Stash the address list and the count so that when the operation
308	 * completes, i.e. when as get an ACK, we can update the clustering's
309	 * state for this association.
310	 */
311	if (ainfo != NULL) {
312		ASSERT(cl_sctp_assoc_change != NULL);
313		ASSERT(nmp->b_prev == NULL);
314		nmp->b_prev = (mblk_t *)ainfo;
315	}
316	/* Clean up the temporary mblk chain */
317	freemsg(mp);
318	asc->head = NULL;
319	asc->cid = 0;
320
321	/* Queue it ... */
322	if (sctp->sctp_cxmit_list == NULL) {
323		sctp->sctp_cxmit_list = nmp;
324	} else {
325		linkb(sctp->sctp_cxmit_list, nmp);
326	}
327
328	BUMP_LOCAL(sctp->sctp_obchunks);
329
330	/* And try to send it. */
331	sctp_wput_asconf(sctp, fp);
332
333	return (0);
334}
335
336/*
337 * If the peer does not understand an ASCONF chunk, we simply
338 * clear out the cxmit_list, since we can send nothing further
339 * that the peer will understand.
340 *
341 * Assumes chunk length has already been checked.
342 */
343/*ARGSUSED*/
344void
345sctp_asconf_free_cxmit(sctp_t *sctp, sctp_chunk_hdr_t *ch)
346{
347	mblk_t		*mp;
348	mblk_t		*mp1;
349	sctp_cl_ainfo_t	*ainfo;
350
351	if (sctp->sctp_cxmit_list == NULL) {
352		/* Nothing pending */
353		return;
354	}
355
356	mp = sctp->sctp_cxmit_list;
357	while (mp != NULL) {
358		mp1 = mp->b_cont;
359		mp->b_cont = NULL;
360		if (mp->b_prev != NULL) {
361			ainfo = (sctp_cl_ainfo_t *)mp->b_prev;
362			mp->b_prev = NULL;
363			kmem_free(ainfo->sctp_cl_alist, ainfo->sctp_cl_asize);
364			kmem_free(ainfo->sctp_cl_dlist, ainfo->sctp_cl_dsize);
365			kmem_free(ainfo, sizeof (*ainfo));
366		}
367		freeb(mp);
368		mp = mp1;
369	}
370	sctp->sctp_cxmit_list = NULL;
371}
372
373void
374sctp_input_asconf(sctp_t *sctp, sctp_chunk_hdr_t *ch, sctp_faddr_t *fp)
375{
376	const dispatch_t	*dp;
377	mblk_t			*hmp;
378	mblk_t			*mp;
379	uint32_t		*idp;
380	uint32_t		*hidp;
381	ssize_t			rlen;
382	sctp_parm_hdr_t		*ph;
383	sctp_chunk_hdr_t	*ach;
384	int			cont;
385	int			act;
386	uint16_t		plen;
387	uchar_t			*alist = NULL;
388	size_t			asize = 0;
389	uchar_t			*dlist = NULL;
390	size_t			dsize = 0;
391	uchar_t			*aptr = NULL;
392	uchar_t			*dptr = NULL;
393	int			acount = 0;
394	int			dcount = 0;
395	sctp_stack_t		*sctps = sctp->sctp_sctps;
396
397	ASSERT(ch->sch_id == CHUNK_ASCONF);
398
399	idp = (uint32_t *)(ch + 1);
400	rlen = ntohs(ch->sch_len) - sizeof (*ch) - sizeof (*idp);
401
402	if (rlen < 0 || rlen < sizeof (*idp)) {
403		/* nothing there; bail out */
404		return;
405	}
406
407	/* Check for duplicates */
408	*idp = ntohl(*idp);
409	if (*idp == (sctp->sctp_fcsn + 1)) {
410		act = 1;
411	} else if (*idp == sctp->sctp_fcsn) {
412		act = 0;
413	} else {
414		/* stale or malicious packet; drop */
415		return;
416	}
417
418	/* Create the ASCONF_ACK header */
419	hmp = sctp_make_mp(sctp, fp, sizeof (*ach) + sizeof (*idp));
420	if (hmp == NULL) {
421		/* Let the peer retransmit */
422		SCTP_KSTAT(sctps, sctp_send_asconf_ack_failed);
423		return;
424	}
425	ach = (sctp_chunk_hdr_t *)hmp->b_wptr;
426	ach->sch_id = CHUNK_ASCONF_ACK;
427	ach->sch_flags = 0;
428	/* Set the length later */
429	hidp = (uint32_t *)(ach + 1);
430	*hidp = htonl(*idp);
431	hmp->b_wptr = (uchar_t *)(hidp + 1);
432
433	/* Move to the Address Parameter */
434	ph = (sctp_parm_hdr_t *)(idp + 1);
435	if (rlen <= ntohs(ph->sph_len)) {
436		freeb(hmp);
437		return;
438	}
439
440	/*
441	 * We already have the association here, so this address parameter
442	 * doesn't seem to be very useful, should we make sure this is part
443	 * of the association and send an error, if not?
444	 * Ignore it for now.
445	 */
446	rlen -= ntohs(ph->sph_len);
447	ph = (sctp_parm_hdr_t *)((char *)ph + ntohs(ph->sph_len));
448
449	/*
450	 * We need to pre-allocate buffer before processing the ASCONF
451	 * chunk. We don't want to fail allocating buffers after processing
452	 * the ASCONF chunk. So, we walk the list and get the number of
453	 * addresses added and/or deleted.
454	 */
455	if (cl_sctp_assoc_change != NULL) {
456		sctp_parm_hdr_t	*oph = ph;
457		ssize_t		orlen = rlen;
458
459		/*
460		 * This not very efficient, but there is no better way of
461		 * doing it.  It should be fine since normally the param list
462		 * will not be very long.
463		 */
464		while (orlen > 0) {
465			/* Sanity checks */
466			if (orlen < sizeof (*oph))
467				break;
468			plen = ntohs(oph->sph_len);
469			if (plen < sizeof (*oph) || plen > orlen)
470				break;
471			if (oph->sph_type == htons(PARM_ADD_IP))
472				acount++;
473			if (oph->sph_type == htons(PARM_DEL_IP))
474				dcount++;
475			oph = sctp_next_parm(oph, &orlen);
476			if (oph == NULL)
477				break;
478		}
479		if (acount > 0 || dcount > 0) {
480			if (acount > 0) {
481				asize = sizeof (in6_addr_t) * acount;
482				alist = kmem_alloc(asize, KM_NOSLEEP);
483				if (alist == NULL) {
484					freeb(hmp);
485					SCTP_KSTAT(sctps, sctp_cl_assoc_change);
486					return;
487				}
488			}
489			if (dcount > 0) {
490				dsize = sizeof (in6_addr_t) * dcount;
491				dlist = kmem_alloc(dsize, KM_NOSLEEP);
492				if (dlist == NULL) {
493					if (acount > 0)
494						kmem_free(alist, asize);
495					freeb(hmp);
496					SCTP_KSTAT(sctps, sctp_cl_assoc_change);
497					return;
498				}
499			}
500			aptr = alist;
501			dptr = dlist;
502			/*
503			 * We will get the actual count when we process
504			 * the chunk.
505			 */
506			acount = 0;
507			dcount = 0;
508		}
509	}
510	cont = 1;
511	while (rlen > 0 && cont) {
512		in6_addr_t	addr;
513
514		/* Sanity checks */
515		if (rlen < sizeof (*ph))
516			break;
517		plen = ntohs(ph->sph_len);
518		if (plen < sizeof (*ph) || plen > rlen) {
519			break;
520		}
521		idp = (uint32_t *)(ph + 1);
522		dp = sctp_lookup_asconf_dispatch(ntohs(ph->sph_type));
523		ASSERT(dp);
524		if (dp->asconf) {
525			mp = dp->asconf(sctp, ph, *idp, fp, &cont, act, &addr);
526			if (cont == -1) {
527				/*
528				 * Not even enough memory to create
529				 * an out-of-resources error. Free
530				 * everything and return; the peer
531				 * should retransmit.
532				 */
533				freemsg(hmp);
534				if (alist != NULL)
535					kmem_free(alist, asize);
536				if (dlist != NULL)
537					kmem_free(dlist, dsize);
538				return;
539			}
540			if (mp != NULL) {
541				linkb(hmp, mp);
542			} else if (act != 0) {
543				/* update the add/delete list */
544				if (cl_sctp_assoc_change != NULL) {
545					if (ph->sph_type ==
546					    htons(PARM_ADD_IP)) {
547						ASSERT(alist != NULL);
548						bcopy(&addr, aptr,
549						    sizeof (addr));
550						aptr += sizeof (addr);
551						acount++;
552					} else if (ph->sph_type ==
553					    htons(PARM_DEL_IP)) {
554						ASSERT(dlist != NULL);
555						bcopy(&addr, dptr,
556						    sizeof (addr));
557						dptr += sizeof (addr);
558						dcount++;
559					}
560				}
561			}
562		}
563		ph = sctp_next_parm(ph, &rlen);
564		if (ph == NULL)
565			break;
566	}
567
568	/*
569	 * Update clustering's state for this assoc. Note acount/dcount
570	 * could be zero (i.e. if the add/delete address(es) were not
571	 * processed successfully). Regardless, if the ?size is > 0,
572	 * it is the clustering module's responsibility to free the lists.
573	 */
574	if (cl_sctp_assoc_change != NULL) {
575		(*cl_sctp_assoc_change)(sctp->sctp_family, alist, asize,
576		    acount, dlist, dsize, dcount, SCTP_CL_PADDR,
577		    (cl_sctp_handle_t)sctp);
578		/* alist and dlist will be freed by the clustering module */
579	}
580	/* Now that the params have been processed, increment the fcsn */
581	if (act) {
582		sctp->sctp_fcsn++;
583	}
584	BUMP_LOCAL(sctp->sctp_obchunks);
585
586	if (fp->isv4)
587		ach->sch_len = htons(msgdsize(hmp) - sctp->sctp_hdr_len);
588	else
589		ach->sch_len = htons(msgdsize(hmp) - sctp->sctp_hdr6_len);
590	sctp_set_iplen(sctp, hmp);
591
592	sctp_add_sendq(sctp, hmp);
593	sctp_validate_peer(sctp);
594}
595
596static sctp_parm_hdr_t *
597sctp_lookup_asconf_param(sctp_parm_hdr_t *ph, uint32_t cid, ssize_t rlen)
598{
599	uint32_t *idp;
600
601	while (rlen > 0) {
602		idp = (uint32_t *)(ph + 1);
603		if (*idp == cid) {
604			return (ph);
605		}
606		ph = sctp_next_parm(ph, &rlen);
607		if (ph == NULL)
608			break;
609	}
610	return (NULL);
611}
612
613void
614sctp_input_asconf_ack(sctp_t *sctp, sctp_chunk_hdr_t *ch, sctp_faddr_t *fp)
615{
616	const dispatch_t	*dp;
617	uint32_t		*idp;
618	uint32_t		*snp;
619	ssize_t			rlen;
620	ssize_t			plen;
621	sctp_parm_hdr_t		*ph;
622	sctp_parm_hdr_t		*oph;
623	sctp_parm_hdr_t		*fph;
624	mblk_t			*mp;
625	sctp_chunk_hdr_t	*och;
626	int			redosrcs = 0;
627	uint16_t		param_len;
628	uchar_t			*alist;
629	uchar_t			*dlist;
630	uint_t			acount = 0;
631	uint_t			dcount = 0;
632	uchar_t			*aptr;
633	uchar_t			*dptr;
634	sctp_cl_ainfo_t		*ainfo;
635	in6_addr_t		addr;
636
637	ASSERT(ch->sch_id == CHUNK_ASCONF_ACK);
638
639	snp = (uint32_t *)(ch + 1);
640	rlen = ntohs(ch->sch_len) - sizeof (*ch) - sizeof (*snp);
641	if (rlen < 0) {
642		return;
643	}
644
645	/* Accept only an ACK for the current serial number */
646	*snp = ntohl(*snp);
647	if (sctp->sctp_cxmit_list == NULL || *snp != (sctp->sctp_lcsn - 1)) {
648		/* Need to send an abort */
649		return;
650	}
651	sctp->sctp_cchunk_pend = 0;
652	SCTP_FADDR_RC_TIMER_STOP(fp);
653
654	mp = sctp->sctp_cxmit_list;
655	/*
656	 * We fill in the addresses here to update the clustering's state for
657	 * this assoc.
658	 */
659	if (mp != NULL && cl_sctp_assoc_change != NULL) {
660		ASSERT(mp->b_prev != NULL);
661		ainfo = (sctp_cl_ainfo_t *)mp->b_prev;
662		alist = ainfo->sctp_cl_alist;
663		dlist = ainfo->sctp_cl_dlist;
664		aptr = alist;
665		dptr = dlist;
666	}
667
668	/*
669	 * Pass explicit replies to callbacks:
670	 * For each reply in the ACK, look up the corresponding
671	 * original parameter in the request using the correlation
672	 * ID, and pass it to the right callback.
673	 */
674	och = (sctp_chunk_hdr_t *)sctp->sctp_cxmit_list->b_rptr;
675
676	plen = ntohs(och->sch_len) - sizeof (*och) - sizeof (*idp);
677	idp = (uint32_t *)(och + 1);
678
679	/* Get to the 1st ASCONF param, need to skip Address TLV parm */
680	fph = (sctp_parm_hdr_t *)(idp + 1);
681	plen -= ntohs(fph->sph_len);
682	fph = (sctp_parm_hdr_t *)((char *)fph + ntohs(fph->sph_len));
683	ph = (sctp_parm_hdr_t *)(snp + 1);
684	while (rlen > 0) {
685		/* Sanity checks */
686		if (rlen < sizeof (*ph)) {
687			break;
688		}
689		param_len = ntohs(ph->sph_len);
690		if (param_len < sizeof (*ph) || param_len > rlen) {
691			break;
692		}
693		idp = (uint32_t *)(ph + 1);
694		oph = sctp_lookup_asconf_param(fph, *idp, plen);
695		if (oph != NULL) {
696			dp = sctp_lookup_asconf_dispatch(ntohs(oph->sph_type));
697			ASSERT(dp);
698			if (dp->asconf_ack) {
699				dp->asconf_ack(sctp, ph, oph, fp, &addr);
700
701				/* hack. see below */
702				if (oph->sph_type == htons(PARM_ADD_IP) ||
703				    oph->sph_type == htons(PARM_DEL_IP)) {
704					redosrcs = 1;
705					/*
706					 * If the address was sucessfully
707					 * processed, add it to the add/delete
708					 * list to send to the clustering
709					 * module.
710					 */
711					if (cl_sctp_assoc_change != NULL &&
712					    !IN6_IS_ADDR_UNSPECIFIED(&addr)) {
713						if (oph->sph_type ==
714						    htons(PARM_ADD_IP)) {
715							bcopy(&addr, aptr,
716							    sizeof (addr));
717							aptr += sizeof (addr);
718							acount++;
719						} else {
720							bcopy(&addr, dptr,
721							    sizeof (addr));
722							dptr += sizeof (addr);
723							dcount++;
724						}
725					}
726				}
727			}
728		}
729
730		ph = sctp_next_parm(ph, &rlen);
731		if (ph == NULL)
732			break;
733	}
734
735	/*
736	 * Pass implicit replies to callbacks:
737	 * For each original request, look up its parameter
738	 * in the ACK. If there is no corresponding reply,
739	 * call the callback with a NULL parameter, indicating
740	 * success.
741	 */
742	rlen = plen;
743	plen = ntohs(ch->sch_len) - sizeof (*ch) - sizeof (*idp);
744	oph = fph;
745	fph = (sctp_parm_hdr_t *)((char *)ch + sizeof (sctp_chunk_hdr_t) +
746	    sizeof (uint32_t));
747	while (rlen > 0) {
748		idp = (uint32_t *)(oph + 1);
749		ph = sctp_lookup_asconf_param(fph, *idp, plen);
750		if (ph == NULL) {
751			dp = sctp_lookup_asconf_dispatch(ntohs(oph->sph_type));
752			ASSERT(dp);
753			if (dp->asconf_ack) {
754				dp->asconf_ack(sctp, NULL, oph, fp, &addr);
755
756				/* hack. see below */
757				if (oph->sph_type == htons(PARM_ADD_IP) ||
758				    oph->sph_type == htons(PARM_DEL_IP)) {
759					redosrcs = 1;
760					/*
761					 * If the address was sucessfully
762					 * processed, add it to the add/delete
763					 * list to send to the clustering
764					 * module.
765					 */
766					if (cl_sctp_assoc_change != NULL &&
767					    !IN6_IS_ADDR_UNSPECIFIED(&addr)) {
768						if (oph->sph_type ==
769						    htons(PARM_ADD_IP)) {
770							bcopy(&addr, aptr,
771							    sizeof (addr));
772							aptr += sizeof (addr);
773							acount++;
774						} else {
775							bcopy(&addr, dptr,
776							    sizeof (addr));
777							dptr += sizeof (addr);
778							dcount++;
779						}
780					}
781				}
782			}
783		}
784		oph = sctp_next_parm(oph, &rlen);
785		if (oph == NULL) {
786			break;
787		}
788	}
789
790	/* We can now free up the first chunk in the cxmit list */
791	sctp->sctp_cxmit_list = mp->b_cont;
792	mp->b_cont = NULL;
793
794	fp = SCTP_CHUNK_DEST(mp);
795	ASSERT(fp != NULL && fp->suna >= MBLKL(mp));
796	fp->suna -= MBLKL(mp);
797
798	/*
799	 * Update clustering's state for this assoc. Note acount/dcount
800	 * could be zero (i.e. if the add/delete address(es) did not
801	 * succeed). Regardless, if the ?size is > 0, it is the clustering
802	 * module's responsibility to free the lists.
803	 */
804	if (cl_sctp_assoc_change != NULL) {
805		ASSERT(mp->b_prev != NULL);
806		mp->b_prev = NULL;
807		ainfo->sctp_cl_alist = NULL;
808		ainfo->sctp_cl_dlist = NULL;
809		(*cl_sctp_assoc_change)(sctp->sctp_family, alist,
810		    ainfo->sctp_cl_asize, acount, dlist, ainfo->sctp_cl_dsize,
811		    dcount, SCTP_CL_LADDR, (cl_sctp_handle_t)sctp);
812		/* alist and dlist will be freed by the clustering module */
813		ainfo->sctp_cl_asize = 0;
814		ainfo->sctp_cl_dsize = 0;
815		kmem_free(ainfo, sizeof (*ainfo));
816	}
817	freeb(mp);
818
819	/* can now send the next control chunk */
820	if (sctp->sctp_cxmit_list != NULL)
821		sctp_wput_asconf(sctp, NULL);
822
823	/*
824	 * If an add-ip or del-ip has completed (successfully or
825	 * unsuccessfully), the pool of available source addresses
826	 * may have changed, so we need to redo faddr source
827	 * address selections. This is a bit of a hack since
828	 * this really belongs in the add/del-ip code. However,
829	 * that code consists of callbacks called for *each*
830	 * add/del-ip parameter, and sctp_redo_faddr_srcs() is
831	 * expensive enough that we really don't want to be
832	 * doing it for each one. So we do it once here.
833	 */
834	if (redosrcs)
835		sctp_redo_faddr_srcs(sctp);
836}
837
838static void
839sctp_rc_timer(sctp_t *sctp, sctp_faddr_t *fp)
840{
841#define	SCTP_CLR_SENT_FLAG(mp)	((mp)->b_flag &= ~SCTP_CHUNK_FLAG_SENT)
842	sctp_faddr_t	*nfp;
843	sctp_faddr_t	*ofp;
844	sctp_stack_t	*sctps = sctp->sctp_sctps;
845
846	ASSERT(fp != NULL);
847
848	fp->rc_timer_running = 0;
849
850	if (sctp->sctp_state != SCTPS_ESTABLISHED ||
851	    sctp->sctp_cxmit_list == NULL) {
852		return;
853	}
854	/*
855	 * Not a retransmission, this was deferred due to some error
856	 * condition
857	 */
858	if (!SCTP_CHUNK_ISSENT(sctp->sctp_cxmit_list)) {
859		sctp_wput_asconf(sctp, fp);
860		return;
861	}
862	/*
863	 * The sent flag indicates if the msg has been sent on this fp.
864	 */
865	SCTP_CLR_SENT_FLAG(sctp->sctp_cxmit_list);
866	/* Retransmission */
867	if (sctp->sctp_strikes >= sctp->sctp_pa_max_rxt) {
868		/* time to give up */
869		BUMP_MIB(&sctps->sctps_mib, sctpAborted);
870		sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL);
871		sctp_clean_death(sctp, ETIMEDOUT);
872		return;
873	}
874	if (fp->strikes >= fp->max_retr) {
875		if (sctp_faddr_dead(sctp, fp, SCTP_FADDRS_DOWN) == -1)
876			return;
877	}
878
879	fp->strikes++;
880	sctp->sctp_strikes++;
881	SCTP_CALC_RXT(fp, sctp->sctp_rto_max);
882
883	nfp = sctp_rotate_faddr(sctp, fp);
884	sctp->sctp_cchunk_pend = 0;
885	ofp = SCTP_CHUNK_DEST(sctp->sctp_cxmit_list);
886	SCTP_SET_CHUNK_DEST(sctp->sctp_cxmit_list, NULL);
887	ASSERT(ofp != NULL && ofp == fp);
888	ASSERT(ofp->suna >= MBLKL(sctp->sctp_cxmit_list));
889	/*
890	 * Enter slow start for this destination.
891	 * XXX anything in the data path that needs to be considered?
892	 */
893	ofp->ssthresh = ofp->cwnd / 2;
894	if (ofp->ssthresh < 2 * ofp->sfa_pmss)
895		ofp->ssthresh = 2 * ofp->sfa_pmss;
896	ofp->cwnd = ofp->sfa_pmss;
897	ofp->pba = 0;
898	ofp->suna -= MBLKL(sctp->sctp_cxmit_list);
899	/*
900	 * The rexmit flags is used to determine if a serial number needs to
901	 * be assigned or not, so once set we leave it there.
902	 */
903	if (!SCTP_CHUNK_WANT_REXMIT(sctp->sctp_cxmit_list))
904		SCTP_CHUNK_REXMIT(sctp->sctp_cxmit_list);
905	sctp_wput_asconf(sctp, nfp);
906#undef	SCTP_CLR_SENT_FLAG
907}
908
909void
910sctp_wput_asconf(sctp_t *sctp, sctp_faddr_t *fp)
911{
912#define	SCTP_SET_SENT_FLAG(mp)	((mp)->b_flag = SCTP_CHUNK_FLAG_SENT)
913
914	mblk_t 			*mp;
915	mblk_t			*ipmp;
916	uint32_t 		*snp;
917	sctp_parm_hdr_t		*ph;
918	boolean_t		isv4;
919	sctp_stack_t		*sctps = sctp->sctp_sctps;
920
921	if (sctp->sctp_cchunk_pend || sctp->sctp_cxmit_list == NULL ||
922	    /* Queue it for later transmission if not yet established */
923	    sctp->sctp_state < SCTPS_ESTABLISHED) {
924		ip2dbg(("sctp_wput_asconf: cchunk pending? (%d) or null "\
925		    "sctp_cxmit_list? (%s) or incorrect state? (%x)\n",
926		    sctp->sctp_cchunk_pend, sctp->sctp_cxmit_list == NULL ?
927		    "yes" : "no", sctp->sctp_state));
928		return;
929	}
930
931	if (fp == NULL)
932		fp = sctp->sctp_current;
933
934	/* OK to send */
935	ipmp = sctp_make_mp(sctp, fp, 0);
936	if (ipmp == NULL) {
937		SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->rto);
938		SCTP_KSTAT(sctps, sctp_send_asconf_failed);
939		return;
940	}
941	mp = sctp->sctp_cxmit_list;
942	/* Fill in the mandatory  Address Parameter TLV */
943	isv4 = (fp != NULL) ? fp->isv4 : sctp->sctp_current->isv4;
944	ph = (sctp_parm_hdr_t *)(mp->b_rptr + sizeof (sctp_chunk_hdr_t) +
945	    sizeof (uint32_t));
946	if (isv4) {
947		ipha_t		*ipha = (ipha_t *)ipmp->b_rptr;
948		in6_addr_t	ipaddr;
949		ipaddr_t	addr4;
950
951		ph->sph_type = htons(PARM_ADDR4);
952		ph->sph_len = htons(PARM_ADDR4_LEN);
953		if (ipha->ipha_src != INADDR_ANY) {
954			bcopy(&ipha->ipha_src, ph + 1, IP_ADDR_LEN);
955		} else {
956			ipaddr = sctp_get_valid_addr(sctp, B_FALSE);
957			/*
958			 * All the addresses are down.
959			 * Maybe we might have better luck next time.
960			 */
961			if (IN6_IS_ADDR_V4MAPPED_ANY(&ipaddr)) {
962				SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->rto);
963				freeb(ipmp);
964				return;
965			}
966			IN6_V4MAPPED_TO_IPADDR(&ipaddr, addr4);
967			bcopy(&addr4, ph + 1, IP_ADDR_LEN);
968		}
969	} else {
970		ip6_t		*ip6 = (ip6_t *)ipmp->b_rptr;
971		in6_addr_t	ipaddr;
972
973		ph->sph_type = htons(PARM_ADDR6);
974		ph->sph_len = htons(PARM_ADDR6_LEN);
975		if (!IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
976			bcopy(&ip6->ip6_src, ph + 1, IPV6_ADDR_LEN);
977		} else {
978			ipaddr = sctp_get_valid_addr(sctp, B_TRUE);
979			/*
980			 * All the addresses are down.
981			 * Maybe we might have better luck next time.
982			 */
983			if (IN6_IS_ADDR_UNSPECIFIED(&ipaddr)) {
984				SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->rto);
985				freeb(ipmp);
986				return;
987			}
988			bcopy(&ipaddr, ph + 1, IPV6_ADDR_LEN);
989		}
990	}
991
992	/* Don't exceed CWND */
993	if ((MBLKL(mp) > (fp->cwnd - fp->suna)) ||
994	    ((mp = dupb(sctp->sctp_cxmit_list)) == NULL)) {
995		SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->rto);
996		freeb(ipmp);
997		return;
998	}
999
1000	/* Set the serial number now, if sending for the first time */
1001	if (!SCTP_CHUNK_WANT_REXMIT(mp)) {
1002		snp = (uint32_t *)(mp->b_rptr + sizeof (sctp_chunk_hdr_t));
1003		*snp = htonl(sctp->sctp_lcsn++);
1004	}
1005	SCTP_CHUNK_CLEAR_FLAGS(mp);
1006	fp->suna += MBLKL(mp);
1007	/* Attach the header and send the chunk */
1008	ipmp->b_cont = mp;
1009	sctp_set_iplen(sctp, ipmp);
1010	sctp->sctp_cchunk_pend = 1;
1011
1012	SCTP_SET_SENT_FLAG(sctp->sctp_cxmit_list);
1013	SCTP_SET_CHUNK_DEST(sctp->sctp_cxmit_list, fp);
1014	sctp_add_sendq(sctp, ipmp);
1015	SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->rto);
1016#undef	SCTP_SET_SENT_FLAG
1017}
1018
1019/*
1020 * Generate ASCONF error param, include errph, if present.
1021 */
1022static mblk_t *
1023sctp_asconf_adderr(int err, sctp_parm_hdr_t *errph, uint32_t cid)
1024{
1025	mblk_t		*mp;
1026	sctp_parm_hdr_t	*eph;
1027	sctp_parm_hdr_t	*wph;
1028	size_t		len;
1029	size_t		elen = 0;
1030
1031	len = sizeof (*wph) + sizeof (*eph) + sizeof (cid);
1032	if (errph != NULL) {
1033		elen = ntohs(errph->sph_len);
1034		len += elen;
1035	}
1036	mp = allocb(len, BPRI_MED);
1037	if (mp == NULL) {
1038		return (NULL);
1039	}
1040	wph = (sctp_parm_hdr_t *)mp->b_rptr;
1041	/* error cause wrapper */
1042	wph->sph_type = htons(PARM_ERROR_IND);
1043	wph->sph_len = htons(len);
1044	bcopy(&cid, wph + 1, sizeof (uint32_t));
1045
1046	/* error cause */
1047	eph = (sctp_parm_hdr_t *)((char *)wph + sizeof (sctp_parm_hdr_t) +
1048	    sizeof (cid));
1049	eph->sph_type = htons(err);
1050	eph->sph_len = htons(len - sizeof (*wph) - sizeof (cid));
1051	mp->b_wptr = (uchar_t *)(eph + 1);
1052
1053	/* details */
1054	if (elen > 0) {
1055		bcopy(errph, mp->b_wptr, elen);
1056		mp->b_wptr += elen;
1057	}
1058	return (mp);
1059}
1060
1061static mblk_t *
1062sctp_check_addip_addr(sctp_parm_hdr_t *ph, sctp_parm_hdr_t *oph, int *cont,
1063    uint32_t cid, in6_addr_t *raddr)
1064{
1065	uint16_t	atype;
1066	uint16_t	alen;
1067	mblk_t		*mp;
1068	in6_addr_t	addr;
1069	ipaddr_t	*addr4;
1070
1071	atype = ntohs(ph->sph_type);
1072	alen = ntohs(ph->sph_len);
1073
1074	if (atype != PARM_ADDR4 && atype != PARM_ADDR6) {
1075		mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph, cid);
1076		if (mp == NULL) {
1077			*cont = -1;
1078		}
1079		return (mp);
1080	}
1081	if ((atype == PARM_ADDR4 && alen < PARM_ADDR4_LEN) ||
1082	    (atype == PARM_ADDR6 && alen < PARM_ADDR6_LEN)) {
1083		mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph, cid);
1084		if (mp == NULL) {
1085			*cont = -1;
1086		}
1087		return (mp);
1088	}
1089
1090	/* Address parameter is present; extract and screen it */
1091	if (atype == PARM_ADDR4) {
1092		addr4 = (ipaddr_t *)(ph + 1);
1093		IN6_IPADDR_TO_V4MAPPED(*addr4, &addr);
1094
1095		/* screen XXX loopback to scoping */
1096		if (*addr4 == 0 || *addr4 == INADDR_BROADCAST ||
1097		    *addr4 == htonl(INADDR_LOOPBACK) || IN_MULTICAST(*addr4)) {
1098			dprint(1, ("addip: addr not unicast: %x:%x:%x:%x\n",
1099			    SCTP_PRINTADDR(addr)));
1100			mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph,
1101			    cid);
1102			if (mp == NULL) {
1103				*cont = -1;
1104			}
1105			return (mp);
1106		}
1107		/*
1108		 * XXX also need to check for subnet
1109		 * broadcasts. This should probably
1110		 * wait until we have full access
1111		 * to the ILL tables.
1112		 */
1113
1114	} else {
1115		bcopy(ph + 1, &addr, sizeof (addr));
1116
1117		/* screen XXX loopback to scoping */
1118		if (IN6_IS_ADDR_LINKLOCAL(&addr) ||
1119		    IN6_IS_ADDR_MULTICAST(&addr) ||
1120		    IN6_IS_ADDR_LOOPBACK(&addr)) {
1121			dprint(1, ("addip: addr not unicast: %x:%x:%x:%x\n",
1122			    SCTP_PRINTADDR(addr)));
1123			mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph,
1124			    cid);
1125			if (mp == NULL) {
1126				*cont = -1;
1127			}
1128			return (mp);
1129		}
1130
1131	}
1132
1133	/* OK */
1134	*raddr = addr;
1135	return (NULL);
1136}
1137
1138/*
1139 * Handles both add and delete address requests.
1140 */
1141static mblk_t *
1142sctp_addip_req(sctp_t *sctp, sctp_parm_hdr_t *ph, uint32_t cid,
1143    sctp_faddr_t *fp, int *cont, int act, in6_addr_t *raddr)
1144{
1145	in6_addr_t	addr;
1146	uint16_t	type;
1147	mblk_t		*mp;
1148	sctp_faddr_t	*nfp;
1149	sctp_parm_hdr_t	*oph = ph;
1150	int		err;
1151	sctp_stack_t	*sctps = sctp->sctp_sctps;
1152
1153	*cont = 1;
1154
1155	/* Send back an authorization error if addip is disabled */
1156	if (!sctps->sctps_addip_enabled) {
1157		err = SCTP_ERR_UNAUTHORIZED;
1158		goto error_handler;
1159	}
1160	/* Check input */
1161	if (ntohs(ph->sph_len) < (sizeof (*ph) * 2)) {
1162		err = SCTP_ERR_BAD_MANDPARM;
1163		goto error_handler;
1164	}
1165
1166	type = ntohs(ph->sph_type);
1167	ph = (sctp_parm_hdr_t *)((char *)ph + sizeof (sctp_parm_hdr_t) +
1168	    sizeof (cid));
1169	mp = sctp_check_addip_addr(ph, oph, cont, cid, &addr);
1170	if (mp != NULL)
1171		return (mp);
1172	if (raddr != NULL)
1173		*raddr = addr;
1174	if (type == PARM_ADD_IP) {
1175		if (sctp_lookup_faddr(sctp, &addr) != NULL) {
1176			/* Address is already part of association */
1177			dprint(1, ("addip: addr already here: %x:%x:%x:%x\n",
1178			    SCTP_PRINTADDR(addr)));
1179			err = SCTP_ERR_BAD_MANDPARM;
1180			goto error_handler;
1181		}
1182
1183		if (!act) {
1184			return (NULL);
1185		}
1186		/* Add the new address */
1187		mutex_enter(&sctp->sctp_conn_tfp->tf_lock);
1188		err = sctp_add_faddr(sctp, &addr, KM_NOSLEEP, B_FALSE);
1189		mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
1190		if (err == ENOMEM) {
1191			/* no memory */
1192			*cont = -1;
1193			return (NULL);
1194		}
1195		if (err != 0) {
1196			err = SCTP_ERR_BAD_MANDPARM;
1197			goto error_handler;
1198		}
1199		sctp_intf_event(sctp, addr, SCTP_ADDR_ADDED, 0);
1200	} else if (type == PARM_DEL_IP) {
1201		nfp = sctp_lookup_faddr(sctp, &addr);
1202		if (nfp == NULL) {
1203			/*
1204			 * Peer is trying to delete an address that is not
1205			 * part of the association.
1206			 */
1207			dprint(1, ("delip: addr not here: %x:%x:%x:%x\n",
1208			    SCTP_PRINTADDR(addr)));
1209			err = SCTP_ERR_BAD_MANDPARM;
1210			goto error_handler;
1211		}
1212		if (sctp->sctp_faddrs == nfp && nfp->next == NULL) {
1213			/* Peer is trying to delete last address */
1214			dprint(1, ("delip: del last addr: %x:%x:%x:%x\n",
1215			    SCTP_PRINTADDR(addr)));
1216			err = SCTP_ERR_DEL_LAST_ADDR;
1217			goto error_handler;
1218		}
1219		if (nfp == fp) {
1220			/* Peer is trying to delete source address */
1221			dprint(1, ("delip: del src addr: %x:%x:%x:%x\n",
1222			    SCTP_PRINTADDR(addr)));
1223			err = SCTP_ERR_DEL_SRC_ADDR;
1224			goto error_handler;
1225		}
1226		if (!act) {
1227			return (NULL);
1228		}
1229
1230		sctp_unlink_faddr(sctp, nfp);
1231		/* Update all references to the deleted faddr */
1232		if (sctp->sctp_primary == nfp) {
1233			sctp->sctp_primary = fp;
1234		}
1235		if (sctp->sctp_current == nfp) {
1236			sctp_set_faddr_current(sctp, fp);
1237		}
1238		if (sctp->sctp_lastdata == nfp) {
1239			sctp->sctp_lastdata = fp;
1240		}
1241		if (sctp->sctp_shutdown_faddr == nfp) {
1242			sctp->sctp_shutdown_faddr = nfp;
1243		}
1244		if (sctp->sctp_lastfaddr == nfp) {
1245			for (fp = sctp->sctp_faddrs; fp->next; fp = fp->next)
1246				;
1247			sctp->sctp_lastfaddr = fp;
1248		}
1249		sctp_intf_event(sctp, addr, SCTP_ADDR_REMOVED, 0);
1250	} else {
1251		ASSERT(0);
1252	}
1253
1254	/* Successful, don't need to return anything. */
1255	return (NULL);
1256
1257error_handler:
1258	mp = sctp_asconf_adderr(err, oph, cid);
1259	if (mp == NULL)
1260		*cont = -1;
1261	return (mp);
1262}
1263
1264/*
1265 * Handles both add and delete IP ACKs.
1266 */
1267/*ARGSUSED*/
1268static void
1269sctp_addip_ack(sctp_t *sctp, sctp_parm_hdr_t *ph, sctp_parm_hdr_t *oph,
1270    sctp_faddr_t *fp, in6_addr_t *laddr)
1271{
1272	in6_addr_t		addr;
1273	sctp_saddr_ipif_t	*sp;
1274	ipaddr_t		*addr4;
1275	boolean_t		backout = B_FALSE;
1276	uint16_t		type;
1277	uint32_t		*cid;
1278
1279	/* could be an ASSERT */
1280	if (laddr != NULL)
1281		IN6_IPADDR_TO_V4MAPPED(0, laddr);
1282
1283	/* If the peer doesn't understand Add-IP, remember it */
1284	if (ph != NULL && ph->sph_type == htons(PARM_UNRECOGNIZED)) {
1285		sctp->sctp_understands_addip = B_FALSE;
1286		backout = B_TRUE;
1287	}
1288
1289	/*
1290	 * If OK, continue with the add / delete action, otherwise
1291	 * back out the action.
1292	 */
1293	if (ph != NULL && ph->sph_type != htons(PARM_SUCCESS)) {
1294		backout = B_TRUE;
1295		sctp_error_event(sctp, (sctp_chunk_hdr_t *)ph);
1296	}
1297
1298	type = ntohs(oph->sph_type);
1299	cid = (uint32_t *)(oph + 1);
1300	oph = (sctp_parm_hdr_t *)(cid + 1);
1301	if (oph->sph_type == htons(PARM_ADDR4)) {
1302		addr4 = (ipaddr_t *)(oph + 1);
1303		IN6_IPADDR_TO_V4MAPPED(*addr4, &addr);
1304	} else {
1305		bcopy(oph + 1, &addr, sizeof (addr));
1306	}
1307
1308	/* Signifies that the address was sucessfully processed */
1309	if (!backout && laddr != NULL)
1310		*laddr = addr;
1311
1312	sp = sctp_saddr_lookup(sctp, &addr, 0);
1313	ASSERT(sp != NULL);
1314
1315	if (type == PARM_ADD_IP) {
1316		if (backout) {
1317			sctp_del_saddr(sctp, sp);
1318		} else {
1319			sp->saddr_ipif_dontsrc = 0;
1320		}
1321	} else if (type == PARM_DEL_IP) {
1322		if (backout) {
1323			sp->saddr_ipif_delete_pending = 0;
1324			sp->saddr_ipif_dontsrc = 0;
1325		} else {
1326			sctp_del_saddr(sctp, sp);
1327		}
1328	} else {
1329		/* Must be either PARM_ADD_IP or PARM_DEL_IP */
1330		ASSERT(0);
1331	}
1332}
1333
1334/*ARGSUSED*/
1335static mblk_t *
1336sctp_setprim_req(sctp_t *sctp, sctp_parm_hdr_t *ph, uint32_t cid,
1337    sctp_faddr_t *fp, int *cont, int act, in6_addr_t *raddr)
1338{
1339	mblk_t *mp;
1340	sctp_parm_hdr_t *oph;
1341	sctp_faddr_t *nfp;
1342	in6_addr_t addr;
1343
1344	*cont = 1;
1345
1346	/* Check input */
1347	if (ntohs(ph->sph_len) < (sizeof (*ph) * 2)) {
1348		mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, ph, cid);
1349		if (mp == NULL) {
1350			*cont = -1;
1351		}
1352		return (mp);
1353	}
1354
1355	oph = ph;
1356	ph = (sctp_parm_hdr_t *)((char *)ph + sizeof (sctp_parm_hdr_t) +
1357	    sizeof (cid));
1358	mp = sctp_check_addip_addr(ph, oph, cont, cid, &addr);
1359	if (mp != NULL) {
1360		return (mp);
1361	}
1362
1363	nfp = sctp_lookup_faddr(sctp, &addr);
1364	if (nfp == NULL) {
1365		/*
1366		 * Peer is trying to set an address that is not
1367		 * part of the association.
1368		 */
1369		dprint(1, ("setprim: addr not here: %x:%x:%x:%x\n",
1370		    SCTP_PRINTADDR(addr)));
1371		mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph, cid);
1372		if (mp == NULL) {
1373			*cont = -1;
1374		}
1375		return (mp);
1376	}
1377
1378	sctp_intf_event(sctp, addr, SCTP_ADDR_MADE_PRIM, 0);
1379	sctp->sctp_primary = nfp;
1380	if (nfp->state != SCTP_FADDRS_ALIVE || nfp == sctp->sctp_current) {
1381		return (NULL);
1382	}
1383	sctp_set_faddr_current(sctp, nfp);
1384	return (NULL);
1385}
1386
1387/*ARGSUSED*/
1388static void
1389sctp_setprim_ack(sctp_t *sctp, sctp_parm_hdr_t *ph, sctp_parm_hdr_t *oph,
1390    sctp_faddr_t *fp, in6_addr_t *laddr)
1391{
1392	if (ph != NULL && ph->sph_type != htons(PARM_SUCCESS)) {
1393		/* If the peer doesn't understand Add-IP, remember it */
1394		if (ph->sph_type == htons(PARM_UNRECOGNIZED)) {
1395			sctp->sctp_understands_addip = B_FALSE;
1396		}
1397		sctp_error_event(sctp, (sctp_chunk_hdr_t *)ph);
1398	}
1399
1400	/* On success we do nothing */
1401}
1402
1403int
1404sctp_add_ip(sctp_t *sctp, const void *addrs, uint32_t cnt)
1405{
1406	struct sockaddr_in	*sin4;
1407	struct sockaddr_in6	*sin6;
1408	mblk_t			*mp;
1409	int			error = 0;
1410	int			i;
1411	sctp_addip4_t		*ad4;
1412	sctp_addip6_t		*ad6;
1413	sctp_asconf_t		asc[1];
1414	uint16_t		type = htons(PARM_ADD_IP);
1415	boolean_t		v4mapped = B_FALSE;
1416	sctp_cl_ainfo_t		*ainfo = NULL;
1417
1418	/* Does the peer understand ASCONF and Add-IP? */
1419	if (!sctp->sctp_understands_asconf || !sctp->sctp_understands_addip)
1420		return (EOPNOTSUPP);
1421
1422	/*
1423	 * On a clustered node, we need to pass this list when
1424	 * we get an ASCONF-ACK. We only pre-allocate memory for the
1425	 * list, but fill in the addresses when it is processed
1426	 * successfully after we get an ASCONF-ACK.
1427	 */
1428	if (cl_sctp_assoc_change != NULL) {
1429		ainfo = kmem_zalloc(sizeof (*ainfo), KM_SLEEP);
1430		/*
1431		 * Reserve space for the list of new addresses
1432		 */
1433		ainfo->sctp_cl_asize = sizeof (in6_addr_t) * cnt;
1434		ainfo->sctp_cl_alist = kmem_alloc(ainfo->sctp_cl_asize,
1435		    KM_SLEEP);
1436	}
1437
1438	sctp_asconf_init(asc);
1439
1440	/*
1441	 * Screen addresses:
1442	 * If adding:
1443	 *   o Must not already be a part of the association
1444	 *   o Must be AF_INET or AF_INET6
1445	 *   o XXX Must be valid source address for this node
1446	 *   o Must be unicast
1447	 *   o XXX Must fit scoping rules
1448	 * If deleting:
1449	 *   o Must be part of the association
1450	 */
1451	for (i = 0; i < cnt; i++) {
1452		switch (sctp->sctp_family) {
1453		case AF_INET:
1454			sin4 = (struct sockaddr_in *)addrs + i;
1455			v4mapped = B_TRUE;
1456			break;
1457
1458		case AF_INET6:
1459			sin6 = (struct sockaddr_in6 *)addrs + i;
1460			break;
1461		}
1462
1463		if (v4mapped) {
1464			mp = allocb(sizeof (*ad4), BPRI_MED);
1465			if (mp == NULL) {
1466				error = ENOMEM;
1467				goto fail;
1468			}
1469			mp->b_wptr += sizeof (*ad4);
1470			ad4 = (sctp_addip4_t *)mp->b_rptr;
1471			ad4->sad4_addip_ph.sph_type = type;
1472			ad4->sad4_addip_ph.sph_len =
1473			    htons(sizeof (sctp_parm_hdr_t) +
1474			    PARM_ADDR4_LEN + sizeof (ad4->asconf_req_cid));
1475			ad4->sad4_addr4_ph.sph_type = htons(PARM_ADDR4);
1476			ad4->sad4_addr4_ph.sph_len = htons(PARM_ADDR4_LEN);
1477			ad4->sad4_addr = sin4->sin_addr.s_addr;
1478		} else {
1479			mp = allocb(sizeof (*ad6), BPRI_MED);
1480			if (mp == NULL) {
1481				error = ENOMEM;
1482				goto fail;
1483			}
1484			mp->b_wptr += sizeof (*ad6);
1485			ad6 = (sctp_addip6_t *)mp->b_rptr;
1486			ad6->sad6_addip_ph.sph_type = type;
1487			ad6->sad6_addip_ph.sph_len =
1488			    htons(sizeof (sctp_parm_hdr_t) +
1489			    PARM_ADDR6_LEN + sizeof (ad6->asconf_req_cid));
1490			ad6->sad6_addr6_ph.sph_type = htons(PARM_ADDR6);
1491			ad6->sad6_addr6_ph.sph_len = htons(PARM_ADDR6_LEN);
1492			ad6->sad6_addr = sin6->sin6_addr;
1493		}
1494		error = sctp_asconf_add(asc, mp);
1495		if (error != 0)
1496			goto fail;
1497	}
1498	error = sctp_asconf_send(sctp, asc, sctp->sctp_current, ainfo);
1499	if (error != 0)
1500		goto fail;
1501
1502	return (0);
1503
1504fail:
1505	if (ainfo != NULL) {
1506		kmem_free(ainfo->sctp_cl_alist, ainfo->sctp_cl_asize);
1507		ainfo->sctp_cl_asize = 0;
1508		kmem_free(ainfo, sizeof (*ainfo));
1509	}
1510	sctp_asconf_destroy(asc);
1511	return (error);
1512}
1513
1514int
1515sctp_del_ip(sctp_t *sctp, const void *addrs, uint32_t cnt, uchar_t *ulist,
1516    size_t usize)
1517{
1518	struct sockaddr_in	*sin4;
1519	struct sockaddr_in6	*sin6;
1520	mblk_t			*mp;
1521	int			error = 0;
1522	int			i;
1523	int			addrcnt = 0;
1524	sctp_addip4_t		*ad4;
1525	sctp_addip6_t		*ad6;
1526	sctp_asconf_t		asc[1];
1527	sctp_saddr_ipif_t	*nsp;
1528	uint16_t		type = htons(PARM_DEL_IP);
1529	boolean_t		v4mapped = B_FALSE;
1530	in6_addr_t		addr;
1531	boolean_t		asconf = B_TRUE;
1532	uint_t			ifindex;
1533	sctp_cl_ainfo_t		*ainfo = NULL;
1534	uchar_t			*p = ulist;
1535	boolean_t		check_lport = B_FALSE;
1536	sctp_stack_t		*sctps = sctp->sctp_sctps;
1537
1538	/* Does the peer understand ASCONF and Add-IP? */
1539	if (sctp->sctp_state <= SCTPS_LISTEN || !sctps->sctps_addip_enabled ||
1540	    !sctp->sctp_understands_asconf || !sctp->sctp_understands_addip) {
1541		asconf = B_FALSE;
1542	}
1543
1544	if (sctp->sctp_state > SCTPS_BOUND)
1545		check_lport = B_TRUE;
1546
1547	if (asconf) {
1548		/*
1549		 * On a clustered node, we need to pass this list when
1550		 * we get an ASCONF-ACK. We only pre-allocate memory for the
1551		 * list, but fill in the addresses when it is processed
1552		 * successfully after we get an ASCONF-ACK.
1553		 */
1554		if (cl_sctp_assoc_change != NULL) {
1555			ainfo = kmem_alloc(sizeof (*ainfo), KM_SLEEP);
1556			ainfo->sctp_cl_dsize = sizeof (in6_addr_t) * cnt;
1557			ainfo->sctp_cl_dlist = kmem_alloc(ainfo->sctp_cl_dsize,
1558			    KM_SLEEP);
1559		}
1560		sctp_asconf_init(asc);
1561	}
1562	/*
1563	 * Screen addresses:
1564	 * If adding:
1565	 *   o Must not already be a part of the association
1566	 *   o Must be AF_INET or AF_INET6
1567	 *   o XXX Must be valid source address for this node
1568	 *   o Must be unicast
1569	 *   o XXX Must fit scoping rules
1570	 * If deleting:
1571	 *   o Must be part of the association
1572	 */
1573	for (i = 0; i < cnt; i++) {
1574		ifindex = 0;
1575
1576		switch (sctp->sctp_family) {
1577		case AF_INET:
1578			sin4 = (struct sockaddr_in *)addrs + i;
1579			if (check_lport && sin4->sin_port != sctp->sctp_lport) {
1580				error = EINVAL;
1581				goto fail;
1582			}
1583			v4mapped = B_TRUE;
1584			IN6_IPADDR_TO_V4MAPPED(sin4->sin_addr.s_addr, &addr);
1585			break;
1586
1587		case AF_INET6:
1588			sin6 = (struct sockaddr_in6 *)addrs + i;
1589			if (check_lport &&
1590			    sin6->sin6_port != sctp->sctp_lport) {
1591				error = EINVAL;
1592				goto fail;
1593			}
1594			addr = sin6->sin6_addr;
1595			ifindex = sin6->sin6_scope_id;
1596			break;
1597		}
1598		nsp = sctp_saddr_lookup(sctp, &addr, ifindex);
1599		if (nsp == NULL) {
1600			error = EADDRNOTAVAIL;
1601			goto fail;
1602		}
1603
1604		/* Collect the list of addresses, if required */
1605		if (usize >= sizeof (addr)) {
1606			bcopy(&addr, p, sizeof (addr));
1607			p += sizeof (addr);
1608			usize -= sizeof (addr);
1609		}
1610		if (!asconf)
1611			continue;
1612
1613		nsp->saddr_ipif_delete_pending = 1;
1614		nsp->saddr_ipif_dontsrc = 1;
1615		addrcnt++;
1616		if (v4mapped) {
1617			mp = allocb(sizeof (*ad4), BPRI_MED);
1618			if (mp == NULL) {
1619				error = ENOMEM;
1620				goto fail;
1621			}
1622			mp->b_wptr += sizeof (*ad4);
1623			ad4 = (sctp_addip4_t *)mp->b_rptr;
1624			ad4->sad4_addip_ph.sph_type = type;
1625			ad4->sad4_addip_ph.sph_len =
1626			    htons(sizeof (sctp_parm_hdr_t) +
1627			    PARM_ADDR4_LEN + sizeof (ad4->asconf_req_cid));
1628			ad4->sad4_addr4_ph.sph_type = htons(PARM_ADDR4);
1629			ad4->sad4_addr4_ph.sph_len = htons(PARM_ADDR4_LEN);
1630			ad4->sad4_addr = sin4->sin_addr.s_addr;
1631		} else {
1632			mp = allocb(sizeof (*ad6), BPRI_MED);
1633			if (mp == NULL) {
1634				error = ENOMEM;
1635				goto fail;
1636			}
1637			mp->b_wptr += sizeof (*ad6);
1638			ad6 = (sctp_addip6_t *)mp->b_rptr;
1639			ad6->sad6_addip_ph.sph_type = type;
1640			ad6->sad6_addip_ph.sph_len =
1641			    htons(sizeof (sctp_parm_hdr_t) + PARM_ADDR6_LEN +
1642			    sizeof (ad6->asconf_req_cid));
1643			ad6->sad6_addr6_ph.sph_type = htons(PARM_ADDR6);
1644			ad6->sad6_addr6_ph.sph_len = htons(PARM_ADDR6_LEN);
1645			ad6->sad6_addr = addr;
1646		}
1647
1648		error = sctp_asconf_add(asc, mp);
1649		if (error != 0)
1650			goto fail;
1651	}
1652
1653	if (!asconf) {
1654		sctp_del_saddr_list(sctp, addrs, cnt, B_FALSE);
1655		return (0);
1656	}
1657	error = sctp_asconf_send(sctp, asc, sctp->sctp_current, ainfo);
1658	if (error != 0)
1659		goto fail;
1660	sctp_redo_faddr_srcs(sctp);
1661	return (0);
1662
1663fail:
1664	if (ainfo != NULL) {
1665		kmem_free(ainfo->sctp_cl_dlist, ainfo->sctp_cl_dsize);
1666		ainfo->sctp_cl_dsize = 0;
1667		kmem_free(ainfo, sizeof (*ainfo));
1668	}
1669	if (!asconf)
1670		return (error);
1671	for (i = 0; i < addrcnt; i++) {
1672		ifindex = 0;
1673
1674		switch (sctp->sctp_family) {
1675		case AF_INET:
1676			sin4 = (struct sockaddr_in *)addrs + i;
1677			IN6_INADDR_TO_V4MAPPED(&(sin4->sin_addr), &addr);
1678			break;
1679		case AF_INET6:
1680			sin6 = (struct sockaddr_in6 *)addrs + i;
1681			addr = sin6->sin6_addr;
1682			ifindex = sin6->sin6_scope_id;
1683			break;
1684		}
1685		nsp = sctp_saddr_lookup(sctp, &addr, ifindex);
1686		ASSERT(nsp != NULL);
1687		nsp->saddr_ipif_delete_pending = 0;
1688		nsp->saddr_ipif_dontsrc = 0;
1689	}
1690	sctp_asconf_destroy(asc);
1691
1692	return (error);
1693}
1694
1695int
1696sctp_set_peerprim(sctp_t *sctp, const void *inp, uint_t inlen)
1697{
1698	const struct sctp_setprim	*prim = inp;
1699	const struct sockaddr_storage	*ss;
1700	struct sockaddr_in *sin;
1701	struct sockaddr_in6 *sin6;
1702	in6_addr_t addr;
1703	mblk_t *mp;
1704	sctp_saddr_ipif_t *sp;
1705	sctp_addip4_t *ad4;
1706	sctp_addip6_t *ad6;
1707	sctp_asconf_t asc[1];
1708	int error = 0;
1709	uint_t	ifindex = 0;
1710
1711	/* Does the peer understand ASCONF and Add-IP? */
1712	if (!sctp->sctp_understands_asconf || !sctp->sctp_understands_addip) {
1713		return (EOPNOTSUPP);
1714	}
1715
1716	if (inlen < sizeof (*prim))
1717		return (EINVAL);
1718
1719	/* Don't do anything if we are not connected */
1720	if (sctp->sctp_state != SCTPS_ESTABLISHED)
1721		return (EINVAL);
1722
1723	ss = &prim->ssp_addr;
1724	sin = NULL;
1725	sin6 = NULL;
1726	if (ss->ss_family == AF_INET) {
1727		sin = (struct sockaddr_in *)ss;
1728		IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &addr);
1729	} else if (ss->ss_family == AF_INET6) {
1730		sin6 = (struct sockaddr_in6 *)ss;
1731		addr = sin6->sin6_addr;
1732		ifindex = sin6->sin6_scope_id;
1733	} else {
1734		return (EAFNOSUPPORT);
1735	}
1736	sp = sctp_saddr_lookup(sctp, &addr, ifindex);
1737	if (sp == NULL)
1738		return (EADDRNOTAVAIL);
1739	sctp_asconf_init(asc);
1740	if (sin) {
1741		mp = allocb(sizeof (*ad4), BPRI_MED);
1742		if (mp == NULL) {
1743			error = ENOMEM;
1744			goto fail;
1745		}
1746		mp->b_wptr += sizeof (*ad4);
1747		ad4 = (sctp_addip4_t *)mp->b_rptr;
1748		ad4->sad4_addip_ph.sph_type = htons(PARM_SET_PRIMARY);
1749		ad4->sad4_addip_ph.sph_len = htons(sizeof (sctp_parm_hdr_t) +
1750		    PARM_ADDR4_LEN + sizeof (ad4->asconf_req_cid));
1751		ad4->sad4_addr4_ph.sph_type = htons(PARM_ADDR4);
1752		ad4->sad4_addr4_ph.sph_len = htons(PARM_ADDR4_LEN);
1753		ad4->sad4_addr = sin->sin_addr.s_addr;
1754	} else {
1755		mp = allocb(sizeof (*ad6), BPRI_MED);
1756		if (mp == NULL) {
1757			error = ENOMEM;
1758			goto fail;
1759		}
1760		mp->b_wptr += sizeof (*ad6);
1761		ad6 = (sctp_addip6_t *)mp->b_rptr;
1762		ad6->sad6_addip_ph.sph_type = htons(PARM_SET_PRIMARY);
1763		ad6->sad6_addip_ph.sph_len = htons(sizeof (sctp_parm_hdr_t) +
1764		    PARM_ADDR6_LEN + sizeof (ad6->asconf_req_cid));
1765		ad6->sad6_addr6_ph.sph_type = htons(PARM_ADDR6);
1766		ad6->sad6_addr6_ph.sph_len = htons(PARM_ADDR6_LEN);
1767		ad6->sad6_addr = sin6->sin6_addr;
1768	}
1769
1770	error = sctp_asconf_add(asc, mp);
1771	if (error != 0) {
1772		goto fail;
1773	}
1774
1775	error = sctp_asconf_send(sctp, asc, sctp->sctp_current, NULL);
1776	if (error == 0) {
1777		return (0);
1778	}
1779
1780fail:
1781	sctp_asconf_destroy(asc);
1782	return (error);
1783}
1784