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