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