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 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 !SCTP_IS_ADDR_UNSPEC(
713 IN6_IS_ADDR_V4MAPPED(&addr),
714 addr)) {
715 if (oph->sph_type ==
716 htons(PARM_ADD_IP)) {
717 bcopy(&addr, aptr,
718 sizeof (addr));
719 aptr += sizeof (addr);
720 acount++;
721 } else {
722 bcopy(&addr, dptr,
723 sizeof (addr));
724 dptr += sizeof (addr);
725 dcount++;
726 }
727 }
728 }
729 }
730 }
731
732 ph = sctp_next_parm(ph, &rlen);
733 if (ph == NULL)
734 break;
735 }
736
737 /*
738 * Pass implicit replies to callbacks:
739 * For each original request, look up its parameter
740 * in the ACK. If there is no corresponding reply,
741 * call the callback with a NULL parameter, indicating
742 * success.
743 */
744 rlen = plen;
745 plen = ntohs(ch->sch_len) - sizeof (*ch) - sizeof (*idp);
746 oph = fph;
747 fph = (sctp_parm_hdr_t *)((char *)ch + sizeof (sctp_chunk_hdr_t) +
748 sizeof (uint32_t));
749 while (rlen > 0) {
750 idp = (uint32_t *)(oph + 1);
751 ph = sctp_lookup_asconf_param(fph, *idp, plen);
752 if (ph == NULL) {
753 dp = sctp_lookup_asconf_dispatch(ntohs(oph->sph_type));
754 ASSERT(dp);
755 if (dp->asconf_ack) {
756 dp->asconf_ack(sctp, NULL, oph, fp, &addr);
757
758 /* hack. see below */
759 if (oph->sph_type == htons(PARM_ADD_IP) ||
760 oph->sph_type == htons(PARM_DEL_IP)) {
761 redosrcs = 1;
762 /*
763 * If the address was sucessfully
764 * processed, add it to the add/delete
765 * list to send to the clustering
766 * module.
767 */
768 if (cl_sctp_assoc_change != NULL &&
769 !SCTP_IS_ADDR_UNSPEC(
770 IN6_IS_ADDR_V4MAPPED(&addr),
771 addr)) {
772 if (oph->sph_type ==
773 htons(PARM_ADD_IP)) {
774 bcopy(&addr, aptr,
775 sizeof (addr));
776 aptr += sizeof (addr);
777 acount++;
778 } else {
779 bcopy(&addr, dptr,
780 sizeof (addr));
781 dptr += sizeof (addr);
782 dcount++;
783 }
784 }
785 }
786 }
787 }
788 oph = sctp_next_parm(oph, &rlen);
789 if (oph == NULL) {
790 break;
791 }
792 }
793
794 /* We can now free up the first chunk in the cxmit list */
795 sctp->sctp_cxmit_list = mp->b_cont;
796 mp->b_cont = NULL;
797
798 fp = SCTP_CHUNK_DEST(mp);
799 ASSERT(fp != NULL && fp->sf_suna >= MBLKL(mp));
800 fp->sf_suna -= MBLKL(mp);
801
802 /*
803 * Update clustering's state for this assoc. Note acount/dcount
804 * could be zero (i.e. if the add/delete address(es) did not
805 * succeed). Regardless, if the ?size is > 0, it is the clustering
806 * module's responsibility to free the lists.
807 */
808 if (cl_sctp_assoc_change != NULL) {
809 ASSERT(mp->b_prev != NULL);
810 mp->b_prev = NULL;
811 ainfo->sctp_cl_alist = NULL;
812 ainfo->sctp_cl_dlist = NULL;
813 (*cl_sctp_assoc_change)(sctp->sctp_connp->conn_family, alist,
814 ainfo->sctp_cl_asize, acount, dlist, ainfo->sctp_cl_dsize,
815 dcount, SCTP_CL_LADDR, (cl_sctp_handle_t)sctp);
816 /* alist and dlist will be freed by the clustering module */
817 ainfo->sctp_cl_asize = 0;
818 ainfo->sctp_cl_dsize = 0;
819 kmem_free(ainfo, sizeof (*ainfo));
820 }
821 freeb(mp);
822
823 /* can now send the next control chunk */
824 if (sctp->sctp_cxmit_list != NULL)
825 sctp_wput_asconf(sctp, NULL);
826
827 /*
828 * If an add-ip or del-ip has completed (successfully or
829 * unsuccessfully), the pool of available source addresses
830 * may have changed, so we need to redo faddr source
831 * address selections. This is a bit of a hack since
832 * this really belongs in the add/del-ip code. However,
833 * that code consists of callbacks called for *each*
834 * add/del-ip parameter, and sctp_redo_faddr_srcs() is
835 * expensive enough that we really don't want to be
836 * doing it for each one. So we do it once here.
837 */
838 if (redosrcs)
839 sctp_redo_faddr_srcs(sctp);
840 }
841
842 static void
sctp_rc_timer(sctp_t * sctp,sctp_faddr_t * fp)843 sctp_rc_timer(sctp_t *sctp, sctp_faddr_t *fp)
844 {
845 #define SCTP_CLR_SENT_FLAG(mp) ((mp)->b_flag &= ~SCTP_CHUNK_FLAG_SENT)
846 sctp_faddr_t *nfp;
847 sctp_faddr_t *ofp;
848 sctp_stack_t *sctps = sctp->sctp_sctps;
849
850 ASSERT(fp != NULL);
851
852 fp->sf_rc_timer_running = 0;
853
854 if (sctp->sctp_state != SCTPS_ESTABLISHED ||
855 sctp->sctp_cxmit_list == NULL) {
856 return;
857 }
858 /*
859 * Not a retransmission, this was deferred due to some error
860 * condition
861 */
862 if (!SCTP_CHUNK_ISSENT(sctp->sctp_cxmit_list)) {
863 sctp_wput_asconf(sctp, fp);
864 return;
865 }
866 /*
867 * The sent flag indicates if the msg has been sent on this fp.
868 */
869 SCTP_CLR_SENT_FLAG(sctp->sctp_cxmit_list);
870 /* Retransmission */
871 if (sctp->sctp_strikes >= sctp->sctp_pa_max_rxt) {
872 /* time to give up */
873 SCTPS_BUMP_MIB(sctps, sctpAborted);
874 sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL);
875 sctp_clean_death(sctp, ETIMEDOUT);
876 return;
877 }
878 if (fp->sf_strikes >= fp->sf_max_retr) {
879 if (sctp_faddr_dead(sctp, fp, SCTP_FADDRS_DOWN) == -1)
880 return;
881 }
882
883 fp->sf_strikes++;
884 sctp->sctp_strikes++;
885 SCTP_CALC_RXT(sctp, fp, sctp->sctp_rto_max);
886
887 nfp = sctp_rotate_faddr(sctp, fp);
888 sctp->sctp_cchunk_pend = 0;
889 ofp = SCTP_CHUNK_DEST(sctp->sctp_cxmit_list);
890 SCTP_SET_CHUNK_DEST(sctp->sctp_cxmit_list, NULL);
891 ASSERT(ofp != NULL && ofp == fp);
892 ASSERT(ofp->sf_suna >= MBLKL(sctp->sctp_cxmit_list));
893 /*
894 * Enter slow start for this destination.
895 * XXX anything in the data path that needs to be considered?
896 */
897 ofp->sf_ssthresh = ofp->sf_cwnd / 2;
898 if (ofp->sf_ssthresh < 2 * ofp->sf_pmss)
899 ofp->sf_ssthresh = 2 * ofp->sf_pmss;
900 ofp->sf_cwnd = ofp->sf_pmss;
901 ofp->sf_pba = 0;
902 ofp->sf_suna -= MBLKL(sctp->sctp_cxmit_list);
903 /*
904 * The rexmit flags is used to determine if a serial number needs to
905 * be assigned or not, so once set we leave it there.
906 */
907 if (!SCTP_CHUNK_WANT_REXMIT(sctp->sctp_cxmit_list))
908 SCTP_CHUNK_REXMIT(sctp, sctp->sctp_cxmit_list);
909 sctp_wput_asconf(sctp, nfp);
910 #undef SCTP_CLR_SENT_FLAG
911 }
912
913 void
sctp_wput_asconf(sctp_t * sctp,sctp_faddr_t * fp)914 sctp_wput_asconf(sctp_t *sctp, sctp_faddr_t *fp)
915 {
916 #define SCTP_SET_SENT_FLAG(mp) ((mp)->b_flag = SCTP_CHUNK_FLAG_SENT)
917
918 mblk_t *mp;
919 mblk_t *ipmp;
920 uint32_t *snp;
921 sctp_parm_hdr_t *ph;
922 boolean_t isv4;
923 sctp_stack_t *sctps = sctp->sctp_sctps;
924 boolean_t saddr_set;
925
926 if (sctp->sctp_cchunk_pend || sctp->sctp_cxmit_list == NULL ||
927 /* Queue it for later transmission if not yet established */
928 sctp->sctp_state < SCTPS_ESTABLISHED) {
929 ip2dbg(("sctp_wput_asconf: cchunk pending? (%d) or null "\
930 "sctp_cxmit_list? (%s) or incorrect state? (%x)\n",
931 sctp->sctp_cchunk_pend, sctp->sctp_cxmit_list == NULL ?
932 "yes" : "no", sctp->sctp_state));
933 return;
934 }
935
936 if (fp == NULL)
937 fp = sctp->sctp_current;
938
939 /* OK to send */
940 ipmp = sctp_make_mp(sctp, fp, 0);
941 if (ipmp == NULL) {
942 SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->sf_rto);
943 SCTP_KSTAT(sctps, sctp_send_asconf_failed);
944 return;
945 }
946 mp = sctp->sctp_cxmit_list;
947 /* Fill in the mandatory Address Parameter TLV */
948 isv4 = (fp != NULL) ? fp->sf_isv4 : sctp->sctp_current->sf_isv4;
949 ph = (sctp_parm_hdr_t *)(mp->b_rptr + sizeof (sctp_chunk_hdr_t) +
950 sizeof (uint32_t));
951 if (isv4) {
952 ipha_t *ipha = (ipha_t *)ipmp->b_rptr;
953 in6_addr_t ipaddr;
954 ipaddr_t addr4;
955
956 ph->sph_type = htons(PARM_ADDR4);
957 ph->sph_len = htons(PARM_ADDR4_LEN);
958 if (ipha->ipha_src != INADDR_ANY) {
959 bcopy(&ipha->ipha_src, ph + 1, IP_ADDR_LEN);
960 } else {
961 ipaddr = sctp_get_valid_addr(sctp, B_FALSE, &saddr_set);
962 /*
963 * All the addresses are down.
964 * Maybe we might have better luck next time.
965 */
966 if (!saddr_set) {
967 SCTP_FADDR_RC_TIMER_RESTART(sctp, fp,
968 fp->sf_rto);
969 freeb(ipmp);
970 return;
971 }
972 IN6_V4MAPPED_TO_IPADDR(&ipaddr, addr4);
973 bcopy(&addr4, ph + 1, IP_ADDR_LEN);
974 }
975 } else {
976 ip6_t *ip6 = (ip6_t *)ipmp->b_rptr;
977 in6_addr_t ipaddr;
978
979 ph->sph_type = htons(PARM_ADDR6);
980 ph->sph_len = htons(PARM_ADDR6_LEN);
981 if (!IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) {
982 bcopy(&ip6->ip6_src, ph + 1, IPV6_ADDR_LEN);
983 } else {
984 ipaddr = sctp_get_valid_addr(sctp, B_TRUE, &saddr_set);
985 /*
986 * All the addresses are down.
987 * Maybe we might have better luck next time.
988 */
989 if (!saddr_set) {
990 SCTP_FADDR_RC_TIMER_RESTART(sctp, fp,
991 fp->sf_rto);
992 freeb(ipmp);
993 return;
994 }
995 bcopy(&ipaddr, ph + 1, IPV6_ADDR_LEN);
996 }
997 }
998
999 /* Don't exceed CWND */
1000 if ((MBLKL(mp) > (fp->sf_cwnd - fp->sf_suna)) ||
1001 ((mp = dupb(sctp->sctp_cxmit_list)) == NULL)) {
1002 SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->sf_rto);
1003 freeb(ipmp);
1004 return;
1005 }
1006
1007 /* Set the serial number now, if sending for the first time */
1008 if (!SCTP_CHUNK_WANT_REXMIT(mp)) {
1009 snp = (uint32_t *)(mp->b_rptr + sizeof (sctp_chunk_hdr_t));
1010 *snp = htonl(sctp->sctp_lcsn++);
1011 }
1012 SCTP_CHUNK_CLEAR_FLAGS(mp);
1013 fp->sf_suna += MBLKL(mp);
1014 /* Attach the header and send the chunk */
1015 ipmp->b_cont = mp;
1016 sctp->sctp_cchunk_pend = 1;
1017
1018 SCTP_SET_SENT_FLAG(sctp->sctp_cxmit_list);
1019 SCTP_SET_CHUNK_DEST(sctp->sctp_cxmit_list, fp);
1020 sctp_set_iplen(sctp, ipmp, fp->sf_ixa);
1021 (void) conn_ip_output(ipmp, fp->sf_ixa);
1022 BUMP_LOCAL(sctp->sctp_opkts);
1023 SCTP_FADDR_RC_TIMER_RESTART(sctp, fp, fp->sf_rto);
1024 #undef SCTP_SET_SENT_FLAG
1025 }
1026
1027 /*
1028 * Generate ASCONF error param, include errph, if present.
1029 */
1030 static mblk_t *
sctp_asconf_adderr(int err,sctp_parm_hdr_t * errph,uint32_t cid)1031 sctp_asconf_adderr(int err, sctp_parm_hdr_t *errph, uint32_t cid)
1032 {
1033 mblk_t *mp;
1034 sctp_parm_hdr_t *eph;
1035 sctp_parm_hdr_t *wph;
1036 size_t len;
1037 size_t elen = 0;
1038
1039 len = sizeof (*wph) + sizeof (*eph) + sizeof (cid);
1040 if (errph != NULL) {
1041 elen = ntohs(errph->sph_len);
1042 len += elen;
1043 }
1044 mp = allocb(len, BPRI_MED);
1045 if (mp == NULL) {
1046 return (NULL);
1047 }
1048 wph = (sctp_parm_hdr_t *)mp->b_rptr;
1049 /* error cause wrapper */
1050 wph->sph_type = htons(PARM_ERROR_IND);
1051 wph->sph_len = htons(len);
1052 bcopy(&cid, wph + 1, sizeof (uint32_t));
1053
1054 /* error cause */
1055 eph = (sctp_parm_hdr_t *)((char *)wph + sizeof (sctp_parm_hdr_t) +
1056 sizeof (cid));
1057 eph->sph_type = htons(err);
1058 eph->sph_len = htons(len - sizeof (*wph) - sizeof (cid));
1059 mp->b_wptr = (uchar_t *)(eph + 1);
1060
1061 /* details */
1062 if (elen > 0) {
1063 bcopy(errph, mp->b_wptr, elen);
1064 mp->b_wptr += elen;
1065 }
1066 return (mp);
1067 }
1068
1069 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)1070 sctp_check_addip_addr(sctp_parm_hdr_t *ph, sctp_parm_hdr_t *oph, int *cont,
1071 uint32_t cid, in6_addr_t *raddr)
1072 {
1073 uint16_t atype;
1074 uint16_t alen;
1075 mblk_t *mp;
1076 in6_addr_t addr;
1077 ipaddr_t *addr4;
1078
1079 atype = ntohs(ph->sph_type);
1080 alen = ntohs(ph->sph_len);
1081
1082 if (atype != PARM_ADDR4 && atype != PARM_ADDR6) {
1083 mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph, cid);
1084 if (mp == NULL) {
1085 *cont = -1;
1086 }
1087 return (mp);
1088 }
1089 if ((atype == PARM_ADDR4 && alen < PARM_ADDR4_LEN) ||
1090 (atype == PARM_ADDR6 && alen < PARM_ADDR6_LEN)) {
1091 mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph, cid);
1092 if (mp == NULL) {
1093 *cont = -1;
1094 }
1095 return (mp);
1096 }
1097
1098 /* Address parameter is present; extract and screen it */
1099 if (atype == PARM_ADDR4) {
1100 addr4 = (ipaddr_t *)(ph + 1);
1101 IN6_IPADDR_TO_V4MAPPED(*addr4, &addr);
1102
1103 /* screen XXX loopback to scoping */
1104 if (*addr4 == 0 || *addr4 == INADDR_BROADCAST ||
1105 *addr4 == htonl(INADDR_LOOPBACK) || CLASSD(*addr4)) {
1106 dprint(1, ("addip: addr not unicast: %x:%x:%x:%x\n",
1107 SCTP_PRINTADDR(addr)));
1108 mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph,
1109 cid);
1110 if (mp == NULL) {
1111 *cont = -1;
1112 }
1113 return (mp);
1114 }
1115 /*
1116 * XXX also need to check for subnet
1117 * broadcasts. This should probably
1118 * wait until we have full access
1119 * to the ILL tables.
1120 */
1121
1122 } else {
1123 bcopy(ph + 1, &addr, sizeof (addr));
1124
1125 /* screen XXX loopback to scoping */
1126 if (IN6_IS_ADDR_LINKLOCAL(&addr) ||
1127 IN6_IS_ADDR_MULTICAST(&addr) ||
1128 IN6_IS_ADDR_LOOPBACK(&addr)) {
1129 dprint(1, ("addip: addr not unicast: %x:%x:%x:%x\n",
1130 SCTP_PRINTADDR(addr)));
1131 mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph,
1132 cid);
1133 if (mp == NULL) {
1134 *cont = -1;
1135 }
1136 return (mp);
1137 }
1138
1139 }
1140
1141 /* OK */
1142 *raddr = addr;
1143 return (NULL);
1144 }
1145
1146 /*
1147 * Handles both add and delete address requests.
1148 */
1149 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)1150 sctp_addip_req(sctp_t *sctp, sctp_parm_hdr_t *ph, uint32_t cid,
1151 sctp_faddr_t *fp, int *cont, int act, in6_addr_t *raddr)
1152 {
1153 in6_addr_t addr;
1154 uint16_t type;
1155 mblk_t *mp;
1156 sctp_faddr_t *nfp;
1157 sctp_parm_hdr_t *oph = ph;
1158 int err;
1159 sctp_stack_t *sctps = sctp->sctp_sctps;
1160
1161 *cont = 1;
1162
1163 /* Send back an authorization error if addip is disabled */
1164 if (!sctps->sctps_addip_enabled) {
1165 err = SCTP_ERR_UNAUTHORIZED;
1166 goto error_handler;
1167 }
1168 /* Check input */
1169 if (ntohs(ph->sph_len) < (sizeof (*ph) * 2)) {
1170 err = SCTP_ERR_BAD_MANDPARM;
1171 goto error_handler;
1172 }
1173
1174 type = ntohs(ph->sph_type);
1175 ph = (sctp_parm_hdr_t *)((char *)ph + sizeof (sctp_parm_hdr_t) +
1176 sizeof (cid));
1177 mp = sctp_check_addip_addr(ph, oph, cont, cid, &addr);
1178 if (mp != NULL)
1179 return (mp);
1180 if (raddr != NULL)
1181 *raddr = addr;
1182 if (type == PARM_ADD_IP) {
1183 if (sctp_lookup_faddr(sctp, &addr) != NULL) {
1184 /* Address is already part of association */
1185 dprint(1, ("addip: addr already here: %x:%x:%x:%x\n",
1186 SCTP_PRINTADDR(addr)));
1187 err = SCTP_ERR_BAD_MANDPARM;
1188 goto error_handler;
1189 }
1190
1191 if (!act) {
1192 return (NULL);
1193 }
1194 /* Add the new address */
1195 mutex_enter(&sctp->sctp_conn_tfp->tf_lock);
1196 err = sctp_add_faddr(sctp, &addr, KM_NOSLEEP, B_FALSE);
1197 mutex_exit(&sctp->sctp_conn_tfp->tf_lock);
1198 if (err == ENOMEM) {
1199 /* no memory */
1200 *cont = -1;
1201 return (NULL);
1202 }
1203 if (err != 0) {
1204 err = SCTP_ERR_BAD_MANDPARM;
1205 goto error_handler;
1206 }
1207 sctp_intf_event(sctp, addr, SCTP_ADDR_ADDED, 0);
1208 } else if (type == PARM_DEL_IP) {
1209 nfp = sctp_lookup_faddr(sctp, &addr);
1210 if (nfp == NULL) {
1211 /*
1212 * Peer is trying to delete an address that is not
1213 * part of the association.
1214 */
1215 dprint(1, ("delip: addr not here: %x:%x:%x:%x\n",
1216 SCTP_PRINTADDR(addr)));
1217 err = SCTP_ERR_BAD_MANDPARM;
1218 goto error_handler;
1219 }
1220 if (sctp->sctp_faddrs == nfp && nfp->sf_next == NULL) {
1221 /* Peer is trying to delete last address */
1222 dprint(1, ("delip: del last addr: %x:%x:%x:%x\n",
1223 SCTP_PRINTADDR(addr)));
1224 err = SCTP_ERR_DEL_LAST_ADDR;
1225 goto error_handler;
1226 }
1227 if (nfp == fp) {
1228 /* Peer is trying to delete source address */
1229 dprint(1, ("delip: del src addr: %x:%x:%x:%x\n",
1230 SCTP_PRINTADDR(addr)));
1231 err = SCTP_ERR_DEL_SRC_ADDR;
1232 goto error_handler;
1233 }
1234 if (!act) {
1235 return (NULL);
1236 }
1237
1238 sctp_unlink_faddr(sctp, nfp);
1239 /* Update all references to the deleted faddr */
1240 if (sctp->sctp_primary == nfp) {
1241 sctp->sctp_primary = fp;
1242 }
1243 if (sctp->sctp_current == nfp) {
1244 sctp_set_faddr_current(sctp, fp);
1245 }
1246 if (sctp->sctp_lastdata == nfp) {
1247 sctp->sctp_lastdata = fp;
1248 }
1249 if (sctp->sctp_shutdown_faddr == nfp) {
1250 sctp->sctp_shutdown_faddr = nfp;
1251 }
1252 if (sctp->sctp_lastfaddr == nfp) {
1253 for (fp = sctp->sctp_faddrs; fp->sf_next;
1254 fp = fp->sf_next)
1255 ;
1256 sctp->sctp_lastfaddr = fp;
1257 }
1258 sctp_intf_event(sctp, addr, SCTP_ADDR_REMOVED, 0);
1259 } else {
1260 ASSERT(0);
1261 }
1262
1263 /* Successful, don't need to return anything. */
1264 return (NULL);
1265
1266 error_handler:
1267 mp = sctp_asconf_adderr(err, oph, cid);
1268 if (mp == NULL)
1269 *cont = -1;
1270 return (mp);
1271 }
1272
1273 /*
1274 * Handles both add and delete IP ACKs.
1275 */
1276 /*ARGSUSED*/
1277 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)1278 sctp_addip_ack(sctp_t *sctp, sctp_parm_hdr_t *ph, sctp_parm_hdr_t *oph,
1279 sctp_faddr_t *fp, in6_addr_t *laddr)
1280 {
1281 in6_addr_t addr;
1282 sctp_saddr_ipif_t *sp;
1283 ipaddr_t *addr4;
1284 boolean_t backout = B_FALSE;
1285 uint16_t type;
1286 uint32_t *cid;
1287
1288 /* could be an ASSERT */
1289 if (laddr != NULL)
1290 IN6_IPADDR_TO_V4MAPPED(0, laddr);
1291
1292 /* If the peer doesn't understand Add-IP, remember it */
1293 if (ph != NULL && ph->sph_type == htons(PARM_UNRECOGNIZED)) {
1294 sctp->sctp_understands_addip = B_FALSE;
1295 backout = B_TRUE;
1296 }
1297
1298 /*
1299 * If OK, continue with the add / delete action, otherwise
1300 * back out the action.
1301 */
1302 if (ph != NULL && ph->sph_type != htons(PARM_SUCCESS)) {
1303 backout = B_TRUE;
1304 sctp_error_event(sctp, (sctp_chunk_hdr_t *)ph, B_TRUE);
1305 }
1306
1307 type = ntohs(oph->sph_type);
1308 cid = (uint32_t *)(oph + 1);
1309 oph = (sctp_parm_hdr_t *)(cid + 1);
1310 if (oph->sph_type == htons(PARM_ADDR4)) {
1311 addr4 = (ipaddr_t *)(oph + 1);
1312 IN6_IPADDR_TO_V4MAPPED(*addr4, &addr);
1313 } else {
1314 bcopy(oph + 1, &addr, sizeof (addr));
1315 }
1316
1317 /* Signifies that the address was sucessfully processed */
1318 if (!backout && laddr != NULL)
1319 *laddr = addr;
1320
1321 sp = sctp_saddr_lookup(sctp, &addr, 0);
1322 ASSERT(sp != NULL);
1323
1324 if (type == PARM_ADD_IP) {
1325 if (backout) {
1326 sctp_del_saddr(sctp, sp);
1327 } else {
1328 sp->saddr_ipif_dontsrc = 0;
1329 }
1330 } else if (type == PARM_DEL_IP) {
1331 if (backout) {
1332 sp->saddr_ipif_delete_pending = 0;
1333 sp->saddr_ipif_dontsrc = 0;
1334 } else {
1335 sctp_del_saddr(sctp, sp);
1336 }
1337 } else {
1338 /* Must be either PARM_ADD_IP or PARM_DEL_IP */
1339 ASSERT(0);
1340 }
1341 }
1342
1343 /*ARGSUSED*/
1344 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)1345 sctp_setprim_req(sctp_t *sctp, sctp_parm_hdr_t *ph, uint32_t cid,
1346 sctp_faddr_t *fp, int *cont, int act, in6_addr_t *raddr)
1347 {
1348 mblk_t *mp;
1349 sctp_parm_hdr_t *oph;
1350 sctp_faddr_t *nfp;
1351 in6_addr_t addr;
1352
1353 *cont = 1;
1354
1355 /* Does the peer understand ASCONF and Add-IP? */
1356 if (!sctp->sctp_understands_asconf || !sctp->sctp_understands_addip) {
1357 mp = sctp_asconf_adderr(SCTP_ERR_UNAUTHORIZED, ph, cid);
1358 if (mp == NULL) {
1359 *cont = -1;
1360 }
1361 return (mp);
1362 }
1363
1364 /* Check input */
1365 if (ntohs(ph->sph_len) < (sizeof (*ph) * 2)) {
1366 mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, ph, cid);
1367 if (mp == NULL) {
1368 *cont = -1;
1369 }
1370 return (mp);
1371 }
1372
1373 oph = ph;
1374 ph = (sctp_parm_hdr_t *)((char *)ph + sizeof (sctp_parm_hdr_t) +
1375 sizeof (cid));
1376 mp = sctp_check_addip_addr(ph, oph, cont, cid, &addr);
1377 if (mp != NULL) {
1378 return (mp);
1379 }
1380
1381 nfp = sctp_lookup_faddr(sctp, &addr);
1382 if (nfp == NULL) {
1383 /*
1384 * Peer is trying to set an address that is not
1385 * part of the association.
1386 */
1387 dprint(1, ("setprim: addr not here: %x:%x:%x:%x\n",
1388 SCTP_PRINTADDR(addr)));
1389 mp = sctp_asconf_adderr(SCTP_ERR_BAD_MANDPARM, oph, cid);
1390 if (mp == NULL) {
1391 *cont = -1;
1392 }
1393 return (mp);
1394 }
1395
1396 sctp_intf_event(sctp, addr, SCTP_ADDR_MADE_PRIM, 0);
1397 sctp->sctp_primary = nfp;
1398 if (nfp->sf_state != SCTP_FADDRS_ALIVE || nfp == sctp->sctp_current) {
1399 return (NULL);
1400 }
1401 sctp_set_faddr_current(sctp, nfp);
1402 return (NULL);
1403 }
1404
1405 /*ARGSUSED*/
1406 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)1407 sctp_setprim_ack(sctp_t *sctp, sctp_parm_hdr_t *ph, sctp_parm_hdr_t *oph,
1408 sctp_faddr_t *fp, in6_addr_t *laddr)
1409 {
1410 if (ph != NULL && ph->sph_type != htons(PARM_SUCCESS)) {
1411 /* If the peer doesn't understand Add-IP, remember it */
1412 if (ph->sph_type == htons(PARM_UNRECOGNIZED)) {
1413 sctp->sctp_understands_addip = B_FALSE;
1414 }
1415 sctp_error_event(sctp, (sctp_chunk_hdr_t *)ph, B_TRUE);
1416 }
1417
1418 /* On success we do nothing */
1419 }
1420
1421 int
sctp_add_ip(sctp_t * sctp,const void * addrs,uint32_t cnt)1422 sctp_add_ip(sctp_t *sctp, const void *addrs, uint32_t cnt)
1423 {
1424 struct sockaddr_in *sin4;
1425 struct sockaddr_in6 *sin6;
1426 mblk_t *mp;
1427 int error = 0;
1428 int i;
1429 sctp_addip4_t *ad4;
1430 sctp_addip6_t *ad6;
1431 sctp_asconf_t asc[1];
1432 uint16_t type = htons(PARM_ADD_IP);
1433 boolean_t v4mapped = B_FALSE;
1434 sctp_cl_ainfo_t *ainfo = NULL;
1435 conn_t *connp = sctp->sctp_connp;
1436
1437 /* Does the peer understand ASCONF and Add-IP? */
1438 if (!sctp->sctp_understands_asconf || !sctp->sctp_understands_addip)
1439 return (EOPNOTSUPP);
1440
1441 /*
1442 * On a clustered node, we need to pass this list when
1443 * we get an ASCONF-ACK. We only pre-allocate memory for the
1444 * list, but fill in the addresses when it is processed
1445 * successfully after we get an ASCONF-ACK.
1446 */
1447 if (cl_sctp_assoc_change != NULL) {
1448 ainfo = kmem_zalloc(sizeof (*ainfo), KM_SLEEP);
1449 /*
1450 * Reserve space for the list of new addresses
1451 */
1452 ainfo->sctp_cl_asize = sizeof (in6_addr_t) * cnt;
1453 ainfo->sctp_cl_alist = kmem_alloc(ainfo->sctp_cl_asize,
1454 KM_SLEEP);
1455 }
1456
1457 sctp_asconf_init(asc);
1458
1459 /*
1460 * Screen addresses:
1461 * If adding:
1462 * o Must not already be a part of the association
1463 * o Must be AF_INET or AF_INET6
1464 * o XXX Must be valid source address for this node
1465 * o Must be unicast
1466 * o XXX Must fit scoping rules
1467 * If deleting:
1468 * o Must be part of the association
1469 */
1470 for (i = 0; i < cnt; i++) {
1471 switch (connp->conn_family) {
1472 case AF_INET:
1473 sin4 = (struct sockaddr_in *)addrs + i;
1474 v4mapped = B_TRUE;
1475 break;
1476
1477 case AF_INET6:
1478 sin6 = (struct sockaddr_in6 *)addrs + i;
1479 break;
1480 }
1481
1482 if (v4mapped) {
1483 mp = allocb(sizeof (*ad4), BPRI_MED);
1484 if (mp == NULL) {
1485 error = ENOMEM;
1486 goto fail;
1487 }
1488 mp->b_wptr += sizeof (*ad4);
1489 ad4 = (sctp_addip4_t *)mp->b_rptr;
1490 ad4->sad4_addip_ph.sph_type = type;
1491 ad4->sad4_addip_ph.sph_len =
1492 htons(sizeof (sctp_parm_hdr_t) +
1493 PARM_ADDR4_LEN + sizeof (ad4->asconf_req_cid));
1494 ad4->sad4_addr4_ph.sph_type = htons(PARM_ADDR4);
1495 ad4->sad4_addr4_ph.sph_len = htons(PARM_ADDR4_LEN);
1496 ad4->sad4_addr = sin4->sin_addr.s_addr;
1497 } else {
1498 mp = allocb(sizeof (*ad6), BPRI_MED);
1499 if (mp == NULL) {
1500 error = ENOMEM;
1501 goto fail;
1502 }
1503 mp->b_wptr += sizeof (*ad6);
1504 ad6 = (sctp_addip6_t *)mp->b_rptr;
1505 ad6->sad6_addip_ph.sph_type = type;
1506 ad6->sad6_addip_ph.sph_len =
1507 htons(sizeof (sctp_parm_hdr_t) +
1508 PARM_ADDR6_LEN + sizeof (ad6->asconf_req_cid));
1509 ad6->sad6_addr6_ph.sph_type = htons(PARM_ADDR6);
1510 ad6->sad6_addr6_ph.sph_len = htons(PARM_ADDR6_LEN);
1511 ad6->sad6_addr = sin6->sin6_addr;
1512 }
1513 error = sctp_asconf_add(asc, mp);
1514 if (error != 0)
1515 goto fail;
1516 }
1517 error = sctp_asconf_send(sctp, asc, sctp->sctp_current, ainfo);
1518 if (error != 0)
1519 goto fail;
1520
1521 return (0);
1522
1523 fail:
1524 if (ainfo != NULL) {
1525 kmem_free(ainfo->sctp_cl_alist, ainfo->sctp_cl_asize);
1526 ainfo->sctp_cl_asize = 0;
1527 kmem_free(ainfo, sizeof (*ainfo));
1528 }
1529 sctp_asconf_destroy(asc);
1530 return (error);
1531 }
1532
1533 int
sctp_del_ip(sctp_t * sctp,const void * addrs,uint32_t cnt,uchar_t * ulist,size_t usize)1534 sctp_del_ip(sctp_t *sctp, const void *addrs, uint32_t cnt, uchar_t *ulist,
1535 size_t usize)
1536 {
1537 struct sockaddr_in *sin4;
1538 struct sockaddr_in6 *sin6;
1539 mblk_t *mp;
1540 int error = 0;
1541 int i;
1542 int addrcnt = 0;
1543 sctp_addip4_t *ad4;
1544 sctp_addip6_t *ad6;
1545 sctp_asconf_t asc[1];
1546 sctp_saddr_ipif_t *nsp;
1547 uint16_t type = htons(PARM_DEL_IP);
1548 boolean_t v4mapped = B_FALSE;
1549 in6_addr_t addr;
1550 boolean_t asconf = B_TRUE;
1551 uint_t ifindex;
1552 sctp_cl_ainfo_t *ainfo = NULL;
1553 uchar_t *p = ulist;
1554 boolean_t check_lport = B_FALSE;
1555 sctp_stack_t *sctps = sctp->sctp_sctps;
1556 conn_t *connp = sctp->sctp_connp;
1557
1558 /* Does the peer understand ASCONF and Add-IP? */
1559 if (sctp->sctp_state <= SCTPS_LISTEN || !sctps->sctps_addip_enabled ||
1560 !sctp->sctp_understands_asconf || !sctp->sctp_understands_addip) {
1561 asconf = B_FALSE;
1562 }
1563
1564 if (sctp->sctp_state > SCTPS_BOUND)
1565 check_lport = B_TRUE;
1566
1567 if (asconf) {
1568 /*
1569 * On a clustered node, we need to pass this list when
1570 * we get an ASCONF-ACK. We only pre-allocate memory for the
1571 * list, but fill in the addresses when it is processed
1572 * successfully after we get an ASCONF-ACK.
1573 */
1574 if (cl_sctp_assoc_change != NULL) {
1575 ainfo = kmem_alloc(sizeof (*ainfo), KM_SLEEP);
1576 ainfo->sctp_cl_dsize = sizeof (in6_addr_t) * cnt;
1577 ainfo->sctp_cl_dlist = kmem_alloc(ainfo->sctp_cl_dsize,
1578 KM_SLEEP);
1579 }
1580 sctp_asconf_init(asc);
1581 }
1582 /*
1583 * Screen addresses:
1584 * If adding:
1585 * o Must not already be a part of the association
1586 * o Must be AF_INET or AF_INET6
1587 * o XXX Must be valid source address for this node
1588 * o Must be unicast
1589 * o XXX Must fit scoping rules
1590 * If deleting:
1591 * o Must be part of the association
1592 */
1593 for (i = 0; i < cnt; i++) {
1594 ifindex = 0;
1595
1596 switch (connp->conn_family) {
1597 case AF_INET:
1598 sin4 = (struct sockaddr_in *)addrs + i;
1599 if (check_lport &&
1600 sin4->sin_port != connp->conn_lport) {
1601 error = EINVAL;
1602 goto fail;
1603 }
1604 v4mapped = B_TRUE;
1605 IN6_IPADDR_TO_V4MAPPED(sin4->sin_addr.s_addr, &addr);
1606 break;
1607
1608 case AF_INET6:
1609 sin6 = (struct sockaddr_in6 *)addrs + i;
1610 if (check_lport &&
1611 sin6->sin6_port != connp->conn_lport) {
1612 error = EINVAL;
1613 goto fail;
1614 }
1615 addr = sin6->sin6_addr;
1616 ifindex = sin6->sin6_scope_id;
1617 break;
1618 }
1619 nsp = sctp_saddr_lookup(sctp, &addr, ifindex);
1620 if (nsp == NULL) {
1621 error = EADDRNOTAVAIL;
1622 goto fail;
1623 }
1624
1625 /* Collect the list of addresses, if required */
1626 if (usize >= sizeof (addr)) {
1627 bcopy(&addr, p, sizeof (addr));
1628 p += sizeof (addr);
1629 usize -= sizeof (addr);
1630 }
1631 if (!asconf)
1632 continue;
1633
1634 nsp->saddr_ipif_delete_pending = 1;
1635 nsp->saddr_ipif_dontsrc = 1;
1636 addrcnt++;
1637 if (v4mapped) {
1638 mp = allocb(sizeof (*ad4), BPRI_MED);
1639 if (mp == NULL) {
1640 error = ENOMEM;
1641 goto fail;
1642 }
1643 mp->b_wptr += sizeof (*ad4);
1644 ad4 = (sctp_addip4_t *)mp->b_rptr;
1645 ad4->sad4_addip_ph.sph_type = type;
1646 ad4->sad4_addip_ph.sph_len =
1647 htons(sizeof (sctp_parm_hdr_t) +
1648 PARM_ADDR4_LEN + sizeof (ad4->asconf_req_cid));
1649 ad4->sad4_addr4_ph.sph_type = htons(PARM_ADDR4);
1650 ad4->sad4_addr4_ph.sph_len = htons(PARM_ADDR4_LEN);
1651 ad4->sad4_addr = sin4->sin_addr.s_addr;
1652 } else {
1653 mp = allocb(sizeof (*ad6), BPRI_MED);
1654 if (mp == NULL) {
1655 error = ENOMEM;
1656 goto fail;
1657 }
1658 mp->b_wptr += sizeof (*ad6);
1659 ad6 = (sctp_addip6_t *)mp->b_rptr;
1660 ad6->sad6_addip_ph.sph_type = type;
1661 ad6->sad6_addip_ph.sph_len =
1662 htons(sizeof (sctp_parm_hdr_t) + PARM_ADDR6_LEN +
1663 sizeof (ad6->asconf_req_cid));
1664 ad6->sad6_addr6_ph.sph_type = htons(PARM_ADDR6);
1665 ad6->sad6_addr6_ph.sph_len = htons(PARM_ADDR6_LEN);
1666 ad6->sad6_addr = addr;
1667 }
1668
1669 error = sctp_asconf_add(asc, mp);
1670 if (error != 0)
1671 goto fail;
1672 }
1673
1674 if (!asconf) {
1675 sctp_del_saddr_list(sctp, addrs, cnt, B_FALSE);
1676 return (0);
1677 }
1678 error = sctp_asconf_send(sctp, asc, sctp->sctp_current, ainfo);
1679 if (error != 0)
1680 goto fail;
1681 sctp_redo_faddr_srcs(sctp);
1682 return (0);
1683
1684 fail:
1685 if (ainfo != NULL) {
1686 kmem_free(ainfo->sctp_cl_dlist, ainfo->sctp_cl_dsize);
1687 ainfo->sctp_cl_dsize = 0;
1688 kmem_free(ainfo, sizeof (*ainfo));
1689 }
1690 if (!asconf)
1691 return (error);
1692 for (i = 0; i < addrcnt; i++) {
1693 ifindex = 0;
1694
1695 switch (connp->conn_family) {
1696 case AF_INET:
1697 sin4 = (struct sockaddr_in *)addrs + i;
1698 IN6_INADDR_TO_V4MAPPED(&(sin4->sin_addr), &addr);
1699 break;
1700 case AF_INET6:
1701 sin6 = (struct sockaddr_in6 *)addrs + i;
1702 addr = sin6->sin6_addr;
1703 ifindex = sin6->sin6_scope_id;
1704 break;
1705 }
1706 nsp = sctp_saddr_lookup(sctp, &addr, ifindex);
1707 ASSERT(nsp != NULL);
1708 nsp->saddr_ipif_delete_pending = 0;
1709 nsp->saddr_ipif_dontsrc = 0;
1710 }
1711 sctp_asconf_destroy(asc);
1712
1713 return (error);
1714 }
1715
1716 int
sctp_set_peerprim(sctp_t * sctp,const void * inp)1717 sctp_set_peerprim(sctp_t *sctp, const void *inp)
1718 {
1719 const struct sctp_setprim *prim = inp;
1720 const struct sockaddr_storage *ss;
1721 struct sockaddr_in *sin;
1722 struct sockaddr_in6 *sin6;
1723 in6_addr_t addr;
1724 mblk_t *mp;
1725 sctp_saddr_ipif_t *sp;
1726 sctp_addip4_t *ad4;
1727 sctp_addip6_t *ad6;
1728 sctp_asconf_t asc[1];
1729 int error = 0;
1730 uint_t ifindex = 0;
1731
1732 /* Does the peer understand ASCONF and Add-IP? */
1733 if (!sctp->sctp_understands_asconf || !sctp->sctp_understands_addip) {
1734 return (EOPNOTSUPP);
1735 }
1736
1737 /* Don't do anything if we are not connected */
1738 if (sctp->sctp_state != SCTPS_ESTABLISHED)
1739 return (EINVAL);
1740
1741 ss = &prim->ssp_addr;
1742 sin = NULL;
1743 sin6 = NULL;
1744 if (ss->ss_family == AF_INET) {
1745 sin = (struct sockaddr_in *)ss;
1746 IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &addr);
1747 } else if (ss->ss_family == AF_INET6) {
1748 sin6 = (struct sockaddr_in6 *)ss;
1749 addr = sin6->sin6_addr;
1750 ifindex = sin6->sin6_scope_id;
1751 } else {
1752 return (EAFNOSUPPORT);
1753 }
1754 sp = sctp_saddr_lookup(sctp, &addr, ifindex);
1755 if (sp == NULL)
1756 return (EADDRNOTAVAIL);
1757 sctp_asconf_init(asc);
1758 if (sin) {
1759 mp = allocb(sizeof (*ad4), BPRI_MED);
1760 if (mp == NULL) {
1761 error = ENOMEM;
1762 goto fail;
1763 }
1764 mp->b_wptr += sizeof (*ad4);
1765 ad4 = (sctp_addip4_t *)mp->b_rptr;
1766 ad4->sad4_addip_ph.sph_type = htons(PARM_SET_PRIMARY);
1767 ad4->sad4_addip_ph.sph_len = htons(sizeof (sctp_parm_hdr_t) +
1768 PARM_ADDR4_LEN + sizeof (ad4->asconf_req_cid));
1769 ad4->sad4_addr4_ph.sph_type = htons(PARM_ADDR4);
1770 ad4->sad4_addr4_ph.sph_len = htons(PARM_ADDR4_LEN);
1771 ad4->sad4_addr = sin->sin_addr.s_addr;
1772 } else {
1773 mp = allocb(sizeof (*ad6), BPRI_MED);
1774 if (mp == NULL) {
1775 error = ENOMEM;
1776 goto fail;
1777 }
1778 mp->b_wptr += sizeof (*ad6);
1779 ad6 = (sctp_addip6_t *)mp->b_rptr;
1780 ad6->sad6_addip_ph.sph_type = htons(PARM_SET_PRIMARY);
1781 ad6->sad6_addip_ph.sph_len = htons(sizeof (sctp_parm_hdr_t) +
1782 PARM_ADDR6_LEN + sizeof (ad6->asconf_req_cid));
1783 ad6->sad6_addr6_ph.sph_type = htons(PARM_ADDR6);
1784 ad6->sad6_addr6_ph.sph_len = htons(PARM_ADDR6_LEN);
1785 ad6->sad6_addr = sin6->sin6_addr;
1786 }
1787
1788 error = sctp_asconf_add(asc, mp);
1789 if (error != 0) {
1790 goto fail;
1791 }
1792
1793 error = sctp_asconf_send(sctp, asc, sctp->sctp_current, NULL);
1794 if (error == 0) {
1795 return (0);
1796 }
1797
1798 fail:
1799 sctp_asconf_destroy(asc);
1800 return (error);
1801 }
1802