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/stream.h> 31 #define _SUN_TPI_VERSION 2 32 #include <sys/tihdr.h> 33 #include <sys/socket.h> 34 #include <sys/xti_inet.h> 35 #include <sys/systm.h> 36 #include <sys/ddi.h> 37 #include <sys/sunddi.h> 38 #include <sys/kmem.h> 39 #include <sys/strsubr.h> 40 #include <sys/strsun.h> 41 #include <sys/policy.h> 42 43 #include <inet/common.h> 44 #include <netinet/ip6.h> 45 #include <inet/ip.h> 46 #include <inet/ip_ire.h> 47 #include <inet/ip_if.h> 48 #include <inet/ipclassifier.h> 49 #include <inet/ipsec_impl.h> 50 51 #include <netinet/in.h> 52 #include <netinet/ip.h> 53 #include <netinet/tcp.h> 54 55 #include <inet/common.h> 56 #include <inet/ip.h> 57 #include <inet/ip6.h> 58 #include <inet/sctp_itf.h> 59 #include "sctp_impl.h" 60 #include "sctp_asconf.h" 61 #include "sctp_addr.h" 62 63 static int sctp_getpeeraddrs(sctp_t *, void *, int *); 64 65 /* 66 * Set optbuf and optlen for the option. 67 * Allocate memory (if not already present). 68 * Otherwise just point optbuf and optlen at invalp and inlen. 69 * Returns failure if memory can not be allocated. 70 */ 71 static int 72 sctp_pkt_set(uchar_t *invalp, uint_t inlen, uchar_t **optbufp, uint_t *optlenp) 73 { 74 uchar_t *optbuf; 75 76 if (inlen == *optlenp) { 77 /* Unchanged length - no need to realocate */ 78 bcopy(invalp, *optbufp, inlen); 79 return (0); 80 } 81 if (inlen != 0) { 82 /* Allocate new buffer before free */ 83 optbuf = kmem_zalloc(inlen, KM_NOSLEEP); 84 if (optbuf == NULL) 85 return (ENOMEM); 86 } else { 87 optbuf = NULL; 88 } 89 /* Free old buffer */ 90 if (*optlenp != 0) 91 kmem_free(*optbufp, *optlenp); 92 93 bcopy(invalp, optbuf, inlen); 94 *optbufp = optbuf; 95 *optlenp = inlen; 96 return (0); 97 } 98 99 /* 100 * Use the outgoing IP header to create an IP_OPTIONS option the way 101 * it was passed down from the application. 102 */ 103 static int 104 sctp_opt_get_user(ipha_t *ipha, uchar_t *buf) 105 { 106 uchar_t *opt; 107 int totallen; 108 uint32_t optval; 109 uint32_t optlen; 110 uint32_t len = 0; 111 uchar_t *buf1 = buf; 112 113 buf += IP_ADDR_LEN; /* Leave room for final destination */ 114 len += IP_ADDR_LEN; 115 bzero(buf1, IP_ADDR_LEN); 116 117 totallen = ipha->ipha_version_and_hdr_length - 118 (uint8_t)((IP_VERSION << 4) + IP_SIMPLE_HDR_LENGTH_IN_WORDS); 119 opt = (uchar_t *)&ipha[1]; 120 totallen <<= 2; 121 while (totallen != 0) { 122 switch (optval = opt[IPOPT_OPTVAL]) { 123 case IPOPT_EOL: 124 goto done; 125 case IPOPT_NOP: 126 optlen = 1; 127 break; 128 default: 129 optlen = opt[IPOPT_OLEN]; 130 } 131 if (optlen == 0 || optlen > totallen) 132 break; 133 134 switch (optval) { 135 int off; 136 case IPOPT_SSRR: 137 case IPOPT_LSRR: 138 139 /* 140 * Insert ipha_dst as the first entry in the source 141 * route and move down the entries on step. 142 * The last entry gets placed at buf1. 143 */ 144 buf[IPOPT_OPTVAL] = optval; 145 buf[IPOPT_OLEN] = optlen; 146 buf[IPOPT_OFFSET] = optlen; 147 148 off = optlen - IP_ADDR_LEN; 149 if (off < 0) { 150 /* No entries in source route */ 151 break; 152 } 153 /* Last entry in source route */ 154 bcopy(opt + off, buf1, IP_ADDR_LEN); 155 off -= IP_ADDR_LEN; 156 157 while (off > 0) { 158 bcopy(opt + off, 159 buf + off + IP_ADDR_LEN, 160 IP_ADDR_LEN); 161 off -= IP_ADDR_LEN; 162 } 163 /* ipha_dst into first slot */ 164 bcopy(&ipha->ipha_dst, 165 buf + off + IP_ADDR_LEN, 166 IP_ADDR_LEN); 167 buf += optlen; 168 len += optlen; 169 break; 170 default: 171 bcopy(opt, buf, optlen); 172 buf += optlen; 173 len += optlen; 174 break; 175 } 176 totallen -= optlen; 177 opt += optlen; 178 } 179 done: 180 /* Pad the resulting options */ 181 while (len & 0x3) { 182 *buf++ = IPOPT_EOL; 183 len++; 184 } 185 return (len); 186 } 187 188 189 /* 190 * Copy the standard header into its new location, 191 * lay in the new options and then update the relevant 192 * fields in both sctp_t and the standard header. 193 * NOTE: this could be simpler if we trusted bcopy() 194 * with overlapping src/dst. 195 */ 196 static int 197 sctp_opt_set_header(sctp_t *sctp, boolean_t checkonly, const void *ptr, 198 uint_t len) 199 { 200 char buf[SCTP_MAX_HDR_LENGTH]; 201 uint_t sctph_len; 202 203 if (checkonly) { 204 /* 205 * do not really set, just pretend to - T_CHECK 206 */ 207 if (len != 0) { 208 /* 209 * there is value supplied, validate it as if 210 * for a real set operation. 211 */ 212 if ((len > SCTP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3)) 213 return (EINVAL); 214 } 215 return (0); 216 } 217 218 if ((len > SCTP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3)) 219 return (EINVAL); 220 sctph_len = sizeof (sctp_hdr_t); 221 bcopy(sctp->sctp_sctph, buf, sctph_len); 222 bcopy(ptr, (char *)sctp->sctp_ipha + IP_SIMPLE_HDR_LENGTH, len); 223 len += IP_SIMPLE_HDR_LENGTH; 224 sctp->sctp_sctph = (sctp_hdr_t *)((char *)sctp->sctp_ipha + len); 225 bcopy(buf, sctp->sctp_sctph, sctph_len); 226 sctp->sctp_ip_hdr_len = len; 227 sctp->sctp_ipha->ipha_version_and_hdr_length = 228 (IP_VERSION << 4) | (len >> 2); 229 len += sctph_len; 230 sctp->sctp_hdr_len = len; 231 232 if (sctp->sctp_current) { 233 /* 234 * Could be setting options before setting up connection. 235 */ 236 sctp_set_ulp_prop(sctp); 237 } 238 return (0); 239 } 240 241 static int 242 sctp_get_status(sctp_t *sctp, void *ptr) 243 { 244 struct sctp_status *sstat = ptr; 245 sctp_faddr_t *fp; 246 struct sockaddr_in *sin; 247 struct sockaddr_in6 *sin6; 248 struct sctp_paddrinfo *sp; 249 mblk_t *meta, *mp; 250 int i; 251 252 sstat->sstat_state = sctp->sctp_state; 253 sstat->sstat_rwnd = sctp->sctp_frwnd; 254 255 sp = &sstat->sstat_primary; 256 if (!sctp->sctp_primary) { 257 bzero(sp, sizeof (*sp)); 258 goto noprim; 259 } 260 fp = sctp->sctp_primary; 261 262 if (fp->isv4) { 263 sin = (struct sockaddr_in *)&sp->spinfo_address; 264 sin->sin_family = AF_INET; 265 sin->sin_port = sctp->sctp_fport; 266 IN6_V4MAPPED_TO_INADDR(&fp->faddr, &sin->sin_addr); 267 sp->spinfo_mtu = sctp->sctp_hdr_len; 268 } else { 269 sin6 = (struct sockaddr_in6 *)&sp->spinfo_address; 270 sin6->sin6_family = AF_INET6; 271 sin6->sin6_port = sctp->sctp_fport; 272 sin6->sin6_addr = fp->faddr; 273 sp->spinfo_mtu = sctp->sctp_hdr6_len; 274 } 275 sp->spinfo_state = fp->state == SCTP_FADDRS_ALIVE ? SCTP_ACTIVE : 276 SCTP_INACTIVE; 277 sp->spinfo_cwnd = fp->cwnd; 278 sp->spinfo_srtt = fp->srtt; 279 sp->spinfo_rto = fp->rto; 280 sp->spinfo_mtu += fp->sfa_pmss; 281 282 noprim: 283 sstat->sstat_unackdata = 0; 284 sstat->sstat_penddata = 0; 285 sstat->sstat_instrms = sctp->sctp_num_istr; 286 sstat->sstat_outstrms = sctp->sctp_num_ostr; 287 sstat->sstat_fragmentation_point = sctp->sctp_mss - 288 sizeof (sctp_data_hdr_t); 289 290 /* count unack'd */ 291 for (meta = sctp->sctp_xmit_head; meta; meta = meta->b_next) { 292 for (mp = meta->b_cont; mp; mp = mp->b_next) { 293 if (!SCTP_CHUNK_ISSENT(mp)) { 294 break; 295 } 296 if (!SCTP_CHUNK_ISACKED(mp)) { 297 sstat->sstat_unackdata++; 298 } 299 } 300 } 301 302 /* 303 * Count penddata chunks. We can only count chunks in SCTP (not 304 * data already delivered to socket layer). 305 */ 306 if (sctp->sctp_instr != NULL) { 307 for (i = 0; i < sctp->sctp_num_istr; i++) { 308 for (meta = sctp->sctp_instr[i].istr_reass; 309 meta != NULL; meta = meta->b_next) { 310 for (mp = meta->b_cont; mp; mp = mp->b_cont) { 311 if (DB_TYPE(mp) != M_CTL) { 312 sstat->sstat_penddata++; 313 } 314 } 315 } 316 } 317 } 318 /* Un-Ordered Frag list */ 319 for (meta = sctp->sctp_uo_frags; meta != NULL; meta = meta->b_next) 320 sstat->sstat_penddata++; 321 322 return (sizeof (*sstat)); 323 } 324 325 /* 326 * SCTP_GET_PEER_ADDR_INFO 327 */ 328 static int 329 sctp_get_paddrinfo(sctp_t *sctp, void *ptr, socklen_t *optlen) 330 { 331 struct sctp_paddrinfo *infop = ptr; 332 struct sockaddr_in *sin4; 333 struct sockaddr_in6 *sin6; 334 in6_addr_t faddr; 335 sctp_faddr_t *fp; 336 337 switch (infop->spinfo_address.ss_family) { 338 case AF_INET: 339 sin4 = (struct sockaddr_in *)&infop->spinfo_address; 340 IN6_INADDR_TO_V4MAPPED(&sin4->sin_addr, &faddr); 341 break; 342 case AF_INET6: 343 sin6 = (struct sockaddr_in6 *)&infop->spinfo_address; 344 faddr = sin6->sin6_addr; 345 break; 346 default: 347 return (EAFNOSUPPORT); 348 } 349 350 if ((fp = sctp_lookup_faddr(sctp, &faddr)) == NULL) 351 return (EINVAL); 352 353 infop->spinfo_state = (fp->state == SCTP_FADDRS_ALIVE) ? SCTP_ACTIVE : 354 SCTP_INACTIVE; 355 infop->spinfo_cwnd = fp->cwnd; 356 infop->spinfo_srtt = TICK_TO_MSEC(fp->srtt); 357 infop->spinfo_rto = TICK_TO_MSEC(fp->rto); 358 infop->spinfo_mtu = fp->sfa_pmss; 359 360 *optlen = sizeof (struct sctp_paddrinfo); 361 return (0); 362 } 363 364 /* 365 * SCTP_RTOINFO 366 */ 367 static int 368 sctp_get_rtoinfo(sctp_t *sctp, void *ptr) 369 { 370 struct sctp_rtoinfo *srto = ptr; 371 372 srto->srto_initial = TICK_TO_MSEC(sctp->sctp_rto_initial); 373 srto->srto_max = TICK_TO_MSEC(sctp->sctp_rto_max); 374 srto->srto_min = TICK_TO_MSEC(sctp->sctp_rto_min); 375 376 return (sizeof (*srto)); 377 } 378 379 static int 380 sctp_set_rtoinfo(sctp_t *sctp, const void *invalp, uint_t inlen) 381 { 382 const struct sctp_rtoinfo *srto; 383 boolean_t ispriv; 384 385 if (inlen < sizeof (*srto)) { 386 return (EINVAL); 387 } 388 srto = invalp; 389 390 ispriv = secpolicy_net_config(CRED(), B_TRUE) == 0; 391 392 /* 393 * Bounds checking. Priviledged user can set the RTO initial 394 * outside the ndd boundary. 395 */ 396 if (srto->srto_initial != 0 && 397 (!ispriv && (srto->srto_initial < sctp_rto_initialg_low || 398 srto->srto_initial > sctp_rto_initialg_high))) { 399 return (EINVAL); 400 } 401 if (srto->srto_max != 0 && 402 (!ispriv && (srto->srto_max < sctp_rto_maxg_low || 403 srto->srto_max > sctp_rto_maxg_high))) { 404 return (EINVAL); 405 } 406 if (srto->srto_min != 0 && 407 (!ispriv && (srto->srto_min < sctp_rto_ming_low || 408 srto->srto_min > sctp_rto_ming_high))) { 409 return (EINVAL); 410 } 411 412 if (srto->srto_initial != 0) { 413 sctp->sctp_rto_initial = MSEC_TO_TICK(srto->srto_initial); 414 } 415 if (srto->srto_max != 0) { 416 sctp->sctp_rto_max = MSEC_TO_TICK(srto->srto_max); 417 } 418 if (srto->srto_min != 0) { 419 sctp->sctp_rto_min = MSEC_TO_TICK(srto->srto_min); 420 } 421 422 return (0); 423 } 424 425 /* 426 * SCTP_ASSOCINFO 427 */ 428 static int 429 sctp_get_assocparams(sctp_t *sctp, void *ptr) 430 { 431 struct sctp_assocparams *sap = ptr; 432 sctp_faddr_t *fp; 433 uint16_t i; 434 435 sap->sasoc_asocmaxrxt = sctp->sctp_pa_max_rxt; 436 437 /* 438 * Count the number of peer addresses 439 */ 440 for (i = 0, fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { 441 i++; 442 } 443 sap->sasoc_number_peer_destinations = i; 444 sap->sasoc_peer_rwnd = sctp->sctp_frwnd; 445 sap->sasoc_local_rwnd = sctp->sctp_rwnd; 446 sap->sasoc_cookie_life = TICK_TO_MSEC(sctp->sctp_cookie_lifetime); 447 448 return (sizeof (*sap)); 449 } 450 451 static int 452 sctp_set_assocparams(sctp_t *sctp, const void *invalp, uint_t inlen) 453 { 454 const struct sctp_assocparams *sap = invalp; 455 uint32_t sum = 0; 456 sctp_faddr_t *fp; 457 458 if (inlen < sizeof (*sap)) { 459 return (EINVAL); 460 } 461 462 if (sap->sasoc_asocmaxrxt) { 463 if (sctp->sctp_faddrs) { 464 /* 465 * Bounds check: as per rfc2960, assoc max retr cannot 466 * exceed the sum of all individual path max retr's. 467 */ 468 for (fp = sctp->sctp_faddrs; fp; fp = fp->next) { 469 sum += fp->max_retr; 470 } 471 if (sap->sasoc_asocmaxrxt > sum) { 472 return (EINVAL); 473 } 474 } 475 if (sap->sasoc_asocmaxrxt < sctp_pa_max_retr_low || 476 sap->sasoc_asocmaxrxt > sctp_pa_max_retr_high) { 477 /* 478 * Out of bounds. 479 */ 480 return (EINVAL); 481 } 482 } 483 if (sap->sasoc_cookie_life != 0 && 484 (sap->sasoc_cookie_life < sctp_cookie_life_low || 485 sap->sasoc_cookie_life > sctp_cookie_life_high)) { 486 return (EINVAL); 487 } 488 489 if (sap->sasoc_asocmaxrxt > 0) { 490 sctp->sctp_pa_max_rxt = sap->sasoc_asocmaxrxt; 491 } 492 if (sap->sasoc_cookie_life > 0) { 493 sctp->sctp_cookie_lifetime = MSEC_TO_TICK( 494 sap->sasoc_cookie_life); 495 } 496 return (0); 497 } 498 499 /* 500 * SCTP_INITMSG 501 */ 502 static int 503 sctp_get_initmsg(sctp_t *sctp, void *ptr) 504 { 505 struct sctp_initmsg *si = ptr; 506 507 si->sinit_num_ostreams = sctp->sctp_num_ostr; 508 si->sinit_max_instreams = sctp->sctp_num_istr; 509 si->sinit_max_attempts = sctp->sctp_max_init_rxt; 510 si->sinit_max_init_timeo = TICK_TO_MSEC(sctp->sctp_init_rto_max); 511 512 return (sizeof (*si)); 513 } 514 515 static int 516 sctp_set_initmsg(sctp_t *sctp, const void *invalp, uint_t inlen) 517 { 518 const struct sctp_initmsg *si = invalp; 519 520 if (sctp->sctp_state > SCTPS_LISTEN) { 521 return (EINVAL); 522 } 523 if (inlen < sizeof (*si)) { 524 return (EINVAL); 525 } 526 if (si->sinit_num_ostreams != 0 && 527 (si->sinit_num_ostreams < sctp_initial_out_streams_low || 528 si->sinit_num_ostreams > sctp_initial_out_streams_high)) { 529 /* 530 * Out of bounds. 531 */ 532 return (EINVAL); 533 } 534 if (si->sinit_max_instreams != 0 && 535 (si->sinit_max_instreams < sctp_max_in_streams_low || 536 si->sinit_max_instreams > sctp_max_in_streams_high)) { 537 return (EINVAL); 538 } 539 if (si->sinit_max_attempts != 0 && 540 (si->sinit_max_attempts < sctp_max_init_retr_low || 541 si->sinit_max_attempts > sctp_max_init_retr_high)) { 542 return (EINVAL); 543 } 544 if (si->sinit_max_init_timeo != 0 && 545 (secpolicy_net_config(CRED(), B_TRUE) != 0 && 546 (si->sinit_max_init_timeo < sctp_rto_maxg_low || 547 si->sinit_max_init_timeo > sctp_rto_maxg_high))) { 548 return (EINVAL); 549 } 550 if (si->sinit_num_ostreams != 0) 551 sctp->sctp_num_ostr = si->sinit_num_ostreams; 552 553 if (si->sinit_max_instreams != 0) 554 sctp->sctp_num_istr = si->sinit_max_instreams; 555 556 if (si->sinit_max_attempts != 0) 557 sctp->sctp_max_init_rxt = si->sinit_max_attempts; 558 559 if (si->sinit_max_init_timeo != 0) { 560 sctp->sctp_init_rto_max = 561 MSEC_TO_TICK(si->sinit_max_init_timeo); 562 } 563 return (0); 564 } 565 566 /* 567 * SCTP_PEER_ADDR_PARAMS 568 */ 569 static int 570 sctp_find_peer_fp(sctp_t *sctp, const struct sockaddr_storage *ss, 571 sctp_faddr_t **fpp) 572 { 573 struct sockaddr_in *sin; 574 struct sockaddr_in6 *sin6; 575 in6_addr_t addr; 576 577 if (ss->ss_family == AF_INET) { 578 sin = (struct sockaddr_in *)ss; 579 IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &addr); 580 } else if (ss->ss_family == AF_INET6) { 581 sin6 = (struct sockaddr_in6 *)ss; 582 addr = sin6->sin6_addr; 583 } else if (ss->ss_family) { 584 return (EAFNOSUPPORT); 585 } 586 587 if (!ss->ss_family || 588 SCTP_IS_ADDR_UNSPEC(IN6_IS_ADDR_V4MAPPED(&addr), addr)) { 589 *fpp = NULL; 590 } else { 591 *fpp = sctp_lookup_faddr(sctp, &addr); 592 if (*fpp == NULL) { 593 return (EINVAL); 594 } 595 } 596 return (0); 597 } 598 599 static int 600 sctp_get_peer_addr_params(sctp_t *sctp, void *ptr) 601 { 602 struct sctp_paddrparams *spp = ptr; 603 sctp_faddr_t *fp; 604 int retval; 605 606 retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp); 607 if (retval) { 608 return (retval); 609 } 610 if (fp) { 611 spp->spp_hbinterval = TICK_TO_MSEC(fp->hb_interval); 612 spp->spp_pathmaxrxt = fp->max_retr; 613 } else { 614 spp->spp_hbinterval = TICK_TO_MSEC(sctp->sctp_hb_interval); 615 spp->spp_pathmaxrxt = sctp->sctp_pp_max_rxt; 616 } 617 return (sizeof (*spp)); 618 } 619 620 static int 621 sctp_set_peer_addr_params(sctp_t *sctp, const void *invalp, uint_t inlen) 622 { 623 const struct sctp_paddrparams *spp = invalp; 624 sctp_faddr_t *fp, *fp2; 625 int retval; 626 uint32_t sum = 0; 627 int64_t now; 628 629 if (inlen < sizeof (*spp)) { 630 return (EINVAL); 631 } 632 633 retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp); 634 if (retval != 0) { 635 return (retval); 636 } 637 638 if (spp->spp_hbinterval && spp->spp_hbinterval != UINT32_MAX && 639 (spp->spp_hbinterval < sctp_heartbeat_interval_low || 640 spp->spp_hbinterval > sctp_heartbeat_interval_high)) { 641 return (EINVAL); 642 } 643 if (spp->spp_pathmaxrxt && 644 (spp->spp_pathmaxrxt < sctp_pp_max_retr_low || 645 spp->spp_pathmaxrxt > sctp_pp_max_retr_high)) { 646 return (EINVAL); 647 } 648 if (spp->spp_pathmaxrxt && sctp->sctp_faddrs) { 649 for (fp2 = sctp->sctp_faddrs; fp2; fp2 = fp2->next) { 650 if (!fp || fp2 == fp) { 651 sum += spp->spp_pathmaxrxt; 652 } else { 653 sum += fp2->max_retr; 654 } 655 } 656 if (sctp->sctp_pa_max_rxt > sum) { 657 return (EINVAL); 658 } 659 } 660 661 now = lbolt64; 662 if (fp != NULL) { 663 if (spp->spp_hbinterval == UINT32_MAX) { 664 /* 665 * Send heartbeat immediatelly, don't modify the 666 * current setting. 667 */ 668 sctp_send_heartbeat(sctp, fp); 669 } else { 670 fp->hb_interval = MSEC_TO_TICK(spp->spp_hbinterval); 671 fp->hb_expiry = now + SET_HB_INTVL(fp); 672 /* 673 * Restart the heartbeat timer using the new intrvl. 674 * We need to call sctp_heartbeat_timer() to set 675 * the earliest heartbeat expiry time. 676 */ 677 sctp_heartbeat_timer(sctp); 678 } 679 if (spp->spp_pathmaxrxt) { 680 fp->max_retr = spp->spp_pathmaxrxt; 681 } 682 } else { 683 for (fp2 = sctp->sctp_faddrs; fp2 != NULL; fp2 = fp2->next) { 684 if (spp->spp_hbinterval == UINT32_MAX) { 685 /* 686 * Send heartbeat immediatelly, don't modify 687 * the current setting. 688 */ 689 sctp_send_heartbeat(sctp, fp2); 690 } else { 691 fp2->hb_interval = MSEC_TO_TICK( 692 spp->spp_hbinterval); 693 fp2->hb_expiry = now + SET_HB_INTVL(fp2); 694 } 695 if (spp->spp_pathmaxrxt) { 696 fp2->max_retr = spp->spp_pathmaxrxt; 697 } 698 } 699 if (spp->spp_hbinterval != UINT32_MAX) { 700 sctp->sctp_hb_interval = MSEC_TO_TICK( 701 spp->spp_hbinterval); 702 /* Restart the heartbeat timer using the new intrvl. */ 703 sctp_timer(sctp, sctp->sctp_heartbeat_mp, 704 sctp->sctp_hb_interval); 705 } 706 if (spp->spp_pathmaxrxt) { 707 sctp->sctp_pp_max_rxt = spp->spp_pathmaxrxt; 708 } 709 } 710 return (0); 711 } 712 713 /* 714 * SCTP_DEFAULT_SEND_PARAM 715 */ 716 static int 717 sctp_get_def_send_params(sctp_t *sctp, void *ptr) 718 { 719 struct sctp_sndrcvinfo *sinfo = ptr; 720 721 sinfo->sinfo_stream = sctp->sctp_def_stream; 722 sinfo->sinfo_ssn = 0; 723 sinfo->sinfo_flags = sctp->sctp_def_flags; 724 sinfo->sinfo_ppid = sctp->sctp_def_ppid; 725 sinfo->sinfo_context = sctp->sctp_def_context; 726 sinfo->sinfo_timetolive = sctp->sctp_def_timetolive; 727 sinfo->sinfo_tsn = 0; 728 sinfo->sinfo_cumtsn = 0; 729 730 return (sizeof (*sinfo)); 731 } 732 733 static int 734 sctp_set_def_send_params(sctp_t *sctp, const void *invalp, uint_t inlen) 735 { 736 const struct sctp_sndrcvinfo *sinfo = invalp; 737 738 if (inlen < sizeof (*sinfo)) { 739 return (EINVAL); 740 } 741 if (sinfo->sinfo_stream >= sctp->sctp_num_ostr) { 742 return (EINVAL); 743 } 744 745 sctp->sctp_def_stream = sinfo->sinfo_stream; 746 sctp->sctp_def_flags = sinfo->sinfo_flags; 747 sctp->sctp_def_ppid = sinfo->sinfo_ppid; 748 sctp->sctp_def_context = sinfo->sinfo_context; 749 sctp->sctp_def_timetolive = sinfo->sinfo_timetolive; 750 751 return (0); 752 } 753 754 static int 755 sctp_set_prim(sctp_t *sctp, const void *invalp, uint_t inlen) 756 { 757 const struct sctp_setpeerprim *pp = invalp; 758 int retval; 759 sctp_faddr_t *fp; 760 761 if (inlen < sizeof (*pp)) { 762 return (EINVAL); 763 } 764 765 retval = sctp_find_peer_fp(sctp, &pp->sspp_addr, &fp); 766 if (retval) 767 return (retval); 768 769 if (fp == NULL) 770 return (EINVAL); 771 if (fp == sctp->sctp_primary) 772 return (0); 773 sctp->sctp_primary = fp; 774 775 /* Only switch current if fp is alive */ 776 if (fp->state != SCTP_FADDRS_ALIVE || fp == sctp->sctp_current) { 777 return (0); 778 } 779 sctp->sctp_current = fp; 780 sctp->sctp_mss = fp->sfa_pmss; 781 /* Reset the addrs in the composite header */ 782 sctp_faddr2hdraddr(fp, sctp); 783 sctp_set_ulp_prop(sctp); 784 785 return (0); 786 } 787 788 /* Handy on off switch for socket option processing. */ 789 #define ONOFF(x) ((x) == 0 ? 0 : 1) 790 791 /* 792 * SCTP routine to get the values of options. 793 */ 794 int 795 sctp_get_opt(sctp_t *sctp, int level, int name, void *ptr, socklen_t *optlen) 796 { 797 int *i1 = (int *)ptr; 798 int retval = 0; 799 int buflen = *optlen; 800 conn_t *connp = sctp->sctp_connp; 801 ip6_pkt_t *ipp = &sctp->sctp_sticky_ipp; 802 /* In most cases, the return buffer is just an int */ 803 *optlen = sizeof (int32_t); 804 805 RUN_SCTP(sctp); 806 807 switch (level) { 808 case SOL_SOCKET: 809 switch (name) { 810 case SO_LINGER: { 811 struct linger *lgr = (struct linger *)ptr; 812 813 lgr->l_onoff = sctp->sctp_linger ? SO_LINGER : 0; 814 lgr->l_linger = TICK_TO_MSEC(sctp->sctp_lingertime); 815 *optlen = sizeof (struct linger); 816 break; 817 } 818 case SO_DEBUG: 819 *i1 = sctp->sctp_debug ? SO_DEBUG : 0; 820 break; 821 case SO_DONTROUTE: 822 *i1 = sctp->sctp_dontroute ? SO_DONTROUTE : 0; 823 break; 824 case SO_USELOOPBACK: 825 *i1 = sctp->sctp_useloopback ? SO_USELOOPBACK : 0; 826 break; 827 case SO_BROADCAST: 828 *i1 = sctp->sctp_broadcast ? SO_BROADCAST : 0; 829 break; 830 case SO_REUSEADDR: 831 *i1 = sctp->sctp_reuseaddr ? SO_REUSEADDR : 0; 832 break; 833 case SO_DGRAM_ERRIND: 834 *i1 = sctp->sctp_dgram_errind ? SO_DGRAM_ERRIND : 0; 835 break; 836 case SO_SNDBUF: 837 *i1 = sctp->sctp_xmit_hiwater; 838 break; 839 case SO_RCVBUF: 840 *i1 = sctp->sctp_rwnd; 841 break; 842 default: 843 retval = EINVAL; 844 break; 845 } 846 break; 847 848 case IPPROTO_SCTP: 849 switch (name) { 850 case SCTP_RTOINFO: 851 if (buflen < sizeof (struct sctp_rtoinfo)) { 852 retval = EINVAL; 853 break; 854 } 855 *optlen = sctp_get_rtoinfo(sctp, ptr); 856 break; 857 case SCTP_ASSOCINFO: 858 if (buflen < sizeof (struct sctp_assocparams)) { 859 retval = EINVAL; 860 break; 861 } 862 *optlen = sctp_get_assocparams(sctp, ptr); 863 break; 864 case SCTP_INITMSG: 865 if (buflen < sizeof (struct sctp_initmsg)) { 866 retval = EINVAL; 867 break; 868 } 869 *optlen = sctp_get_initmsg(sctp, ptr); 870 break; 871 case SCTP_NODELAY: 872 *i1 = sctp->sctp_ndelay; 873 break; 874 case SCTP_AUTOCLOSE: 875 *i1 = TICK_TO_SEC(sctp->sctp_autoclose); 876 break; 877 case SCTP_ADAPTION_LAYER: 878 if (buflen < sizeof (struct sctp_setadaption)) { 879 retval = EINVAL; 880 break; 881 } 882 ((struct sctp_setadaption *)ptr)->ssb_adaption_ind = 883 sctp->sctp_tx_adaption_code; 884 break; 885 case SCTP_PEER_ADDR_PARAMS: 886 if (buflen < sizeof (struct sctp_paddrparams)) { 887 retval = EINVAL; 888 break; 889 } 890 *optlen = sctp_get_peer_addr_params(sctp, ptr); 891 break; 892 case SCTP_DEFAULT_SEND_PARAM: 893 if (buflen < sizeof (struct sctp_sndrcvinfo)) { 894 retval = EINVAL; 895 break; 896 } 897 *optlen = sctp_get_def_send_params(sctp, ptr); 898 break; 899 case SCTP_EVENTS: { 900 struct sctp_event_subscribe *ev; 901 902 if (buflen < sizeof (struct sctp_event_subscribe)) { 903 retval = EINVAL; 904 break; 905 } 906 ev = (struct sctp_event_subscribe *)ptr; 907 ev->sctp_data_io_event = 908 ONOFF(sctp->sctp_recvsndrcvinfo); 909 ev->sctp_association_event = 910 ONOFF(sctp->sctp_recvassocevnt); 911 ev->sctp_address_event = 912 ONOFF(sctp->sctp_recvpathevnt); 913 ev->sctp_send_failure_event = 914 ONOFF(sctp->sctp_recvsendfailevnt); 915 ev->sctp_peer_error_event = 916 ONOFF(sctp->sctp_recvpeererr); 917 ev->sctp_shutdown_event = 918 ONOFF(sctp->sctp_recvshutdownevnt); 919 ev->sctp_partial_delivery_event = 920 ONOFF(sctp->sctp_recvpdevnt); 921 ev->sctp_adaption_layer_event = 922 ONOFF(sctp->sctp_recvalevnt); 923 *optlen = sizeof (struct sctp_event_subscribe); 924 break; 925 } 926 case SCTP_STATUS: 927 if (buflen < sizeof (struct sctp_status)) { 928 retval = EINVAL; 929 break; 930 } 931 *optlen = sctp_get_status(sctp, ptr); 932 break; 933 case SCTP_GET_PEER_ADDR_INFO: 934 if (buflen < sizeof (struct sctp_paddrinfo)) { 935 retval = EINVAL; 936 break; 937 } 938 retval = sctp_get_paddrinfo(sctp, ptr, optlen); 939 break; 940 case SCTP_GET_NLADDRS: 941 *(int32_t *)ptr = sctp->sctp_nsaddrs; 942 break; 943 case SCTP_GET_LADDRS: { 944 int addr_cnt; 945 int addr_size; 946 947 if (sctp->sctp_family == AF_INET) 948 addr_size = sizeof (struct sockaddr_in); 949 else 950 addr_size = sizeof (struct sockaddr_in6); 951 addr_cnt = buflen / addr_size; 952 retval = sctp_getmyaddrs(sctp, ptr, &addr_cnt); 953 if (retval == 0) 954 *optlen = addr_cnt * addr_size; 955 break; 956 } 957 case SCTP_GET_NPADDRS: { 958 int i; 959 sctp_faddr_t *fp; 960 961 for (i = 0, fp = sctp->sctp_faddrs; fp != NULL; 962 i++, fp = fp->next) 963 ; 964 *(int32_t *)ptr = i; 965 break; 966 } 967 case SCTP_GET_PADDRS: { 968 int addr_cnt; 969 int addr_size; 970 971 if (sctp->sctp_family == AF_INET) 972 addr_size = sizeof (struct sockaddr_in); 973 else 974 addr_size = sizeof (struct sockaddr_in6); 975 addr_cnt = buflen / addr_size; 976 retval = sctp_getpeeraddrs(sctp, ptr, &addr_cnt); 977 if (retval == 0) 978 *optlen = addr_cnt * addr_size; 979 break; 980 } 981 case SCTP_PRSCTP: 982 *i1 = sctp->sctp_prsctp_aware ? 1 : 0; 983 break; 984 case SCTP_I_WANT_MAPPED_V4_ADDR: 985 case SCTP_MAXSEG: 986 case SCTP_DISABLE_FRAGMENTS: 987 /* Not yet supported. */ 988 default: 989 retval = EINVAL; 990 break; 991 } 992 break; 993 994 case IPPROTO_IP: 995 if (sctp->sctp_family != AF_INET) { 996 retval = EINVAL; 997 break; 998 } 999 switch (name) { 1000 case IP_OPTIONS: 1001 case T_IP_OPTIONS: { 1002 /* 1003 * This is compatible with BSD in that in only return 1004 * the reverse source route with the final destination 1005 * as the last entry. The first 4 bytes of the option 1006 * will contain the final destination. Allocate a 1007 * buffer large enough to hold all the options, we 1008 * add IP_ADDR_LEN to SCTP_MAX_IP_OPTIONS_LENGTH since 1009 * sctp_opt_get_user() adds the final destination 1010 * at the start. 1011 */ 1012 char *opt_ptr; 1013 int opt_len; 1014 uchar_t obuf[SCTP_MAX_IP_OPTIONS_LENGTH + IP_ADDR_LEN]; 1015 1016 opt_ptr = (char *)sctp->sctp_ipha + 1017 IP_SIMPLE_HDR_LENGTH; 1018 opt_len = (char *)sctp->sctp_sctph - opt_ptr; 1019 /* Caller ensures enough space */ 1020 if (opt_len > 0) { 1021 /* 1022 * TODO: Do we have to handle getsockopt on an 1023 * initiator as well? 1024 */ 1025 opt_len = sctp_opt_get_user(sctp->sctp_ipha, 1026 obuf); 1027 ASSERT(opt_len <= sizeof (obuf)); 1028 } else { 1029 opt_len = 0; 1030 } 1031 if (buflen < opt_len) { 1032 /* Silently truncate */ 1033 opt_len = buflen; 1034 } 1035 *optlen = opt_len; 1036 bcopy(obuf, ptr, opt_len); 1037 break; 1038 } 1039 case IP_TOS: 1040 case T_IP_TOS: 1041 *i1 = (int)sctp->sctp_ipha->ipha_type_of_service; 1042 break; 1043 case IP_TTL: 1044 *i1 = (int)sctp->sctp_ipha->ipha_ttl; 1045 break; 1046 case IP_NEXTHOP: 1047 if (connp->conn_nexthop_set) { 1048 *(ipaddr_t *)ptr = connp->conn_nexthop_v4; 1049 *optlen = sizeof (ipaddr_t); 1050 } else { 1051 *optlen = 0; 1052 } 1053 break; 1054 default: 1055 retval = EINVAL; 1056 break; 1057 } 1058 break; 1059 case IPPROTO_IPV6: 1060 if (sctp->sctp_family != AF_INET6) { 1061 retval = EINVAL; 1062 break; 1063 } 1064 switch (name) { 1065 case IPV6_UNICAST_HOPS: 1066 *i1 = (unsigned int) sctp->sctp_ip6h->ip6_hops; 1067 break; /* goto sizeof (int) option return */ 1068 case IPV6_RECVPKTINFO: 1069 if (sctp->sctp_ipv6_recvancillary & 1070 SCTP_IPV6_RECVPKTINFO) { 1071 *i1 = 1; 1072 } else { 1073 *i1 = 0; 1074 } 1075 break; /* goto sizeof (int) option return */ 1076 case IPV6_RECVHOPLIMIT: 1077 if (sctp->sctp_ipv6_recvancillary & 1078 SCTP_IPV6_RECVHOPLIMIT) { 1079 *i1 = 1; 1080 } else { 1081 *i1 = 0; 1082 } 1083 break; /* goto sizeof (int) option return */ 1084 case IPV6_RECVHOPOPTS: 1085 if (sctp->sctp_ipv6_recvancillary & 1086 SCTP_IPV6_RECVHOPOPTS) { 1087 *i1 = 1; 1088 } else { 1089 *i1 = 0; 1090 } 1091 break; /* goto sizeof (int) option return */ 1092 case IPV6_RECVDSTOPTS: 1093 if (sctp->sctp_ipv6_recvancillary & 1094 SCTP_IPV6_RECVDSTOPTS) { 1095 *i1 = 1; 1096 } else { 1097 *i1 = 0; 1098 } 1099 break; /* goto sizeof (int) option return */ 1100 case IPV6_RECVRTHDR: 1101 if (sctp->sctp_ipv6_recvancillary & 1102 SCTP_IPV6_RECVRTHDR) { 1103 *i1 = 1; 1104 } else { 1105 *i1 = 0; 1106 } 1107 break; /* goto sizeof (int) option return */ 1108 case IPV6_RECVRTHDRDSTOPTS: 1109 if (sctp->sctp_ipv6_recvancillary & 1110 SCTP_IPV6_RECVRTDSTOPTS) { 1111 *i1 = 1; 1112 } else { 1113 *i1 = 0; 1114 } 1115 break; /* goto sizeof (int) option return */ 1116 case IPV6_PKTINFO: { 1117 struct in6_pktinfo *pkti; 1118 1119 if (buflen < sizeof (struct in6_pktinfo)) { 1120 retval = EINVAL; 1121 break; 1122 } 1123 pkti = (struct in6_pktinfo *)ptr; 1124 if (ipp->ipp_fields & IPPF_IFINDEX) 1125 pkti->ipi6_ifindex = ipp->ipp_ifindex; 1126 else 1127 pkti->ipi6_ifindex = 0; 1128 if (ipp->ipp_fields & IPPF_ADDR) 1129 pkti->ipi6_addr = ipp->ipp_addr; 1130 else 1131 pkti->ipi6_addr = ipv6_all_zeros; 1132 *optlen = sizeof (struct in6_pktinfo); 1133 break; 1134 } 1135 case IPV6_NEXTHOP: { 1136 sin6_t *sin6; 1137 1138 if (buflen < sizeof (sin6_t)) { 1139 retval = EINVAL; 1140 break; 1141 } 1142 sin6 = (sin6_t *)ptr; 1143 if (!(ipp->ipp_fields & IPPF_NEXTHOP)) 1144 break; 1145 *sin6 = sctp_sin6_null; 1146 sin6->sin6_family = AF_INET6; 1147 sin6->sin6_addr = ipp->ipp_nexthop; 1148 *optlen = sizeof (sin6_t); 1149 break; 1150 } 1151 case IPV6_HOPOPTS: 1152 if (!(ipp->ipp_fields & IPPF_HOPOPTS)) 1153 break; 1154 if (buflen < ipp->ipp_hopoptslen) { 1155 retval = EINVAL; 1156 break; 1157 } 1158 bcopy(ipp->ipp_hopopts, ptr, ipp->ipp_hopoptslen); 1159 *optlen = ipp->ipp_hopoptslen; 1160 break; 1161 case IPV6_RTHDRDSTOPTS: 1162 if (!(ipp->ipp_fields & IPPF_RTDSTOPTS)) 1163 break; 1164 if (buflen < ipp->ipp_rtdstoptslen) { 1165 retval = EINVAL; 1166 break; 1167 } 1168 bcopy(ipp->ipp_rtdstopts, ptr, ipp->ipp_rtdstoptslen); 1169 *optlen = ipp->ipp_rtdstoptslen; 1170 break; 1171 case IPV6_RTHDR: 1172 if (!(ipp->ipp_fields & IPPF_RTHDR)) 1173 break; 1174 if (buflen < ipp->ipp_rthdrlen) { 1175 retval = EINVAL; 1176 break; 1177 } 1178 bcopy(ipp->ipp_rthdr, ptr, ipp->ipp_rthdrlen); 1179 *optlen = ipp->ipp_rthdrlen; 1180 break; 1181 case IPV6_DSTOPTS: 1182 if (!(ipp->ipp_fields & IPPF_DSTOPTS)) 1183 break; 1184 if (buflen < ipp->ipp_dstoptslen) { 1185 retval = EINVAL; 1186 break; 1187 } 1188 bcopy(ipp->ipp_dstopts, ptr, ipp->ipp_dstoptslen); 1189 *optlen = ipp->ipp_dstoptslen; 1190 break; 1191 case IPV6_V6ONLY: 1192 *i1 = sctp->sctp_connp->conn_ipv6_v6only; 1193 break; 1194 default: 1195 retval = EINVAL; 1196 break; 1197 } 1198 break; 1199 1200 default: 1201 retval = EINVAL; 1202 break; 1203 } 1204 WAKE_SCTP(sctp); 1205 return (retval); 1206 } 1207 1208 int 1209 sctp_set_opt(sctp_t *sctp, int level, int name, const void *invalp, 1210 socklen_t inlen) 1211 { 1212 ip6_pkt_t *ipp = &sctp->sctp_sticky_ipp; 1213 int *i1 = (int *)invalp; 1214 boolean_t onoff; 1215 int retval = 0, addrcnt; 1216 conn_t *connp = sctp->sctp_connp; 1217 1218 /* In all cases, the size of the option must be bigger than int */ 1219 if (inlen >= sizeof (int32_t)) { 1220 onoff = ONOFF(*i1); 1221 } 1222 retval = 0; 1223 1224 RUN_SCTP(sctp); 1225 1226 switch (level) { 1227 case SOL_SOCKET: 1228 if (inlen < sizeof (int32_t)) { 1229 retval = EINVAL; 1230 break; 1231 } 1232 switch (name) { 1233 case SO_LINGER: { 1234 struct linger *lgr; 1235 1236 if (inlen != sizeof (struct linger)) { 1237 retval = EINVAL; 1238 break; 1239 } 1240 lgr = (struct linger *)invalp; 1241 if (lgr->l_onoff != 0) { 1242 sctp->sctp_linger = 1; 1243 sctp->sctp_lingertime = MSEC_TO_TICK( 1244 lgr->l_linger); 1245 } else { 1246 sctp->sctp_linger = 0; 1247 sctp->sctp_lingertime = 0; 1248 } 1249 break; 1250 } 1251 case SO_DEBUG: 1252 sctp->sctp_debug = onoff; 1253 break; 1254 case SO_KEEPALIVE: 1255 break; 1256 case SO_DONTROUTE: 1257 /* 1258 * SO_DONTROUTE, SO_USELOOPBACK and SO_BROADCAST are 1259 * only of interest to IP. We track them here only so 1260 * that we can report their current value. 1261 */ 1262 sctp->sctp_dontroute = onoff; 1263 connp->conn_dontroute = onoff; 1264 break; 1265 case SO_USELOOPBACK: 1266 sctp->sctp_useloopback = onoff; 1267 connp->conn_loopback = onoff; 1268 break; 1269 case SO_BROADCAST: 1270 sctp->sctp_broadcast = onoff; 1271 connp->conn_broadcast = onoff; 1272 break; 1273 case SO_REUSEADDR: 1274 sctp->sctp_reuseaddr = onoff; 1275 connp->conn_reuseaddr = onoff; 1276 break; 1277 case SO_DGRAM_ERRIND: 1278 sctp->sctp_dgram_errind = onoff; 1279 break; 1280 case SO_SNDBUF: 1281 if (*i1 > sctp_max_buf) { 1282 retval = ENOBUFS; 1283 break; 1284 } 1285 if (*i1 < 0) { 1286 retval = EINVAL; 1287 break; 1288 } 1289 sctp->sctp_xmit_hiwater = *i1; 1290 if (sctp_snd_lowat_fraction != 0) 1291 sctp->sctp_xmit_lowater = 1292 sctp->sctp_xmit_hiwater / 1293 sctp_snd_lowat_fraction; 1294 break; 1295 case SO_RCVBUF: 1296 if (*i1 > sctp_max_buf) { 1297 retval = ENOBUFS; 1298 break; 1299 } 1300 /* Silently ignore zero */ 1301 if (*i1 != 0) { 1302 /* 1303 * Insist on a receive window that is at least 1304 * sctp_recv_hiwat_minmss * MSS (default 4*MSS) 1305 * to avoid funny interactions of Nagle 1306 * algorithm, SWS avoidance and delayed 1307 * acknowledgement. 1308 */ 1309 *i1 = MAX(*i1, 1310 sctp_recv_hiwat_minmss * sctp->sctp_mss); 1311 sctp->sctp_rwnd = *i1; 1312 sctp->sctp_irwnd = sctp->sctp_rwnd; 1313 } 1314 /* 1315 * XXX should we return the rwnd here 1316 * and sctp_opt_get ? 1317 */ 1318 break; 1319 default: 1320 retval = EINVAL; 1321 break; 1322 } 1323 break; 1324 1325 case IPPROTO_SCTP: 1326 if (inlen < sizeof (int32_t)) { 1327 retval = EINVAL; 1328 break; 1329 } 1330 switch (name) { 1331 case SCTP_RTOINFO: 1332 retval = sctp_set_rtoinfo(sctp, invalp, inlen); 1333 break; 1334 case SCTP_ASSOCINFO: 1335 retval = sctp_set_assocparams(sctp, invalp, inlen); 1336 break; 1337 case SCTP_INITMSG: 1338 retval = sctp_set_initmsg(sctp, invalp, inlen); 1339 break; 1340 case SCTP_NODELAY: 1341 sctp->sctp_ndelay = ONOFF(*i1); 1342 break; 1343 case SCTP_AUTOCLOSE: 1344 if (SEC_TO_TICK(*i1) < 0) { 1345 retval = EINVAL; 1346 break; 1347 } 1348 /* Convert the number of seconds to ticks. */ 1349 sctp->sctp_autoclose = SEC_TO_TICK(*i1); 1350 sctp_heartbeat_timer(sctp); 1351 break; 1352 case SCTP_SET_PEER_PRIMARY_ADDR: 1353 retval = sctp_set_peerprim(sctp, invalp, inlen); 1354 break; 1355 case SCTP_PRIMARY_ADDR: 1356 retval = sctp_set_prim(sctp, invalp, inlen); 1357 break; 1358 case SCTP_ADAPTION_LAYER: { 1359 struct sctp_setadaption *ssb; 1360 1361 if (inlen < sizeof (struct sctp_setadaption)) { 1362 retval = EINVAL; 1363 break; 1364 } 1365 ssb = (struct sctp_setadaption *)invalp; 1366 sctp->sctp_send_adaption = 1; 1367 sctp->sctp_tx_adaption_code = ssb->ssb_adaption_ind; 1368 break; 1369 } 1370 case SCTP_PEER_ADDR_PARAMS: 1371 retval = sctp_set_peer_addr_params(sctp, invalp, 1372 inlen); 1373 break; 1374 case SCTP_DEFAULT_SEND_PARAM: 1375 retval = sctp_set_def_send_params(sctp, invalp, inlen); 1376 break; 1377 case SCTP_EVENTS: { 1378 struct sctp_event_subscribe *ev; 1379 1380 if (inlen < sizeof (struct sctp_event_subscribe)) { 1381 retval = EINVAL; 1382 break; 1383 } 1384 ev = (struct sctp_event_subscribe *)invalp; 1385 sctp->sctp_recvsndrcvinfo = 1386 ONOFF(ev->sctp_data_io_event); 1387 sctp->sctp_recvassocevnt = 1388 ONOFF(ev->sctp_association_event); 1389 sctp->sctp_recvpathevnt = 1390 ONOFF(ev->sctp_address_event); 1391 sctp->sctp_recvsendfailevnt = 1392 ONOFF(ev->sctp_send_failure_event); 1393 sctp->sctp_recvpeererr = 1394 ONOFF(ev->sctp_peer_error_event); 1395 sctp->sctp_recvshutdownevnt = 1396 ONOFF(ev->sctp_shutdown_event); 1397 sctp->sctp_recvpdevnt = 1398 ONOFF(ev->sctp_partial_delivery_event); 1399 sctp->sctp_recvalevnt = 1400 ONOFF(ev->sctp_adaption_layer_event); 1401 break; 1402 } 1403 case SCTP_ADD_ADDR: 1404 case SCTP_REM_ADDR: 1405 /* 1406 * The sctp_t has to be bound first before 1407 * the address list can be changed. 1408 */ 1409 if (sctp->sctp_state < SCTPS_BOUND) { 1410 retval = EINVAL; 1411 break; 1412 } 1413 if (sctp->sctp_family == AF_INET) { 1414 addrcnt = inlen / sizeof (struct sockaddr_in); 1415 } else { 1416 ASSERT(sctp->sctp_family == AF_INET6); 1417 addrcnt = inlen / sizeof (struct sockaddr_in6); 1418 } 1419 if (name == SCTP_ADD_ADDR) { 1420 retval = sctp_bind_add(sctp, invalp, addrcnt, 1421 B_TRUE, sctp->sctp_lport); 1422 } else { 1423 retval = sctp_bind_del(sctp, invalp, addrcnt, 1424 B_TRUE); 1425 } 1426 break; 1427 case SCTP_UC_SWAP: { 1428 struct sctp_uc_swap *us; 1429 1430 /* 1431 * Change handle & upcalls. 1432 */ 1433 if (inlen < sizeof (*us)) { 1434 retval = EINVAL; 1435 break; 1436 } 1437 us = (struct sctp_uc_swap *)invalp; 1438 sctp->sctp_ulpd = us->sus_handle; 1439 bcopy(us->sus_upcalls, &sctp->sctp_upcalls, 1440 sizeof (sctp_upcalls_t)); 1441 break; 1442 } 1443 case SCTP_PRSCTP: 1444 sctp->sctp_prsctp_aware = onoff; 1445 break; 1446 case SCTP_I_WANT_MAPPED_V4_ADDR: 1447 case SCTP_MAXSEG: 1448 case SCTP_DISABLE_FRAGMENTS: 1449 /* Not yet supported. */ 1450 default: 1451 retval = EINVAL; 1452 break; 1453 } 1454 break; 1455 1456 case IPPROTO_IP: 1457 if (sctp->sctp_family != AF_INET) { 1458 retval = ENOPROTOOPT; 1459 break; 1460 } 1461 if ((name != IP_OPTIONS) && (inlen < sizeof (int32_t))) { 1462 retval = EINVAL; 1463 break; 1464 } 1465 switch (name) { 1466 case IP_OPTIONS: 1467 case T_IP_OPTIONS: 1468 retval = sctp_opt_set_header(sctp, B_FALSE, 1469 invalp, inlen); 1470 break; 1471 case IP_TOS: 1472 case T_IP_TOS: 1473 sctp->sctp_ipha->ipha_type_of_service = (uchar_t)*i1; 1474 break; 1475 case IP_TTL: 1476 sctp->sctp_ipha->ipha_ttl = (uchar_t)*i1; 1477 break; 1478 case IP_SEC_OPT: 1479 /* 1480 * We should not allow policy setting after 1481 * we start listening for connections. 1482 */ 1483 if (sctp->sctp_state >= SCTPS_LISTEN) { 1484 retval = EINVAL; 1485 } else { 1486 retval = ipsec_set_req(sctp->sctp_credp, 1487 sctp->sctp_connp, (ipsec_req_t *)invalp); 1488 } 1489 break; 1490 /* IP level options */ 1491 case IP_RECVIF: 1492 connp->conn_recvif = onoff; 1493 break; 1494 case IP_RECVSLLA: 1495 connp->conn_recvslla = onoff; 1496 break; 1497 case IP_UNSPEC_SRC: 1498 connp->conn_unspec_src = onoff; 1499 break; 1500 case IP_NEXTHOP: { 1501 ipaddr_t addr = *i1; 1502 ipif_t *ipif = NULL; 1503 ill_t *ill; 1504 1505 if (secpolicy_net(CRED(), OP_CONFIG, B_TRUE) == 0) { 1506 ipif = 1507 ipif_lookup_onlink_addr(addr, 1508 connp->conn_zoneid); 1509 if (ipif == NULL) { 1510 retval = EHOSTUNREACH; 1511 break; 1512 } 1513 ill = ipif->ipif_ill; 1514 mutex_enter(&ill->ill_lock); 1515 if ((ill->ill_state_flags & ILL_CONDEMNED) || 1516 (ipif->ipif_state_flags & IPIF_CONDEMNED)) { 1517 mutex_exit(&ill->ill_lock); 1518 ipif_refrele(ipif); 1519 retval = EHOSTUNREACH; 1520 break; 1521 } 1522 mutex_exit(&ill->ill_lock); 1523 ipif_refrele(ipif); 1524 mutex_enter(&connp->conn_lock); 1525 connp->conn_nexthop_v4 = addr; 1526 connp->conn_nexthop_set = B_TRUE; 1527 mutex_exit(&connp->conn_lock); 1528 } 1529 break; 1530 } 1531 default: 1532 retval = EINVAL; 1533 break; 1534 } 1535 break; 1536 case IPPROTO_IPV6: { 1537 if (sctp->sctp_family != AF_INET6) { 1538 retval = ENOPROTOOPT; 1539 break; 1540 } 1541 1542 switch (name) { 1543 case IPV6_UNICAST_HOPS: 1544 if (inlen < sizeof (int32_t)) { 1545 retval = EINVAL; 1546 break; 1547 } 1548 if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) { 1549 retval = EINVAL; 1550 break; 1551 } 1552 if (*i1 == -1) { 1553 ipp->ipp_unicast_hops = sctp_ipv6_hoplimit; 1554 ipp->ipp_fields &= ~IPPF_UNICAST_HOPS; 1555 } else { 1556 ipp->ipp_unicast_hops = (uint8_t)*i1; 1557 ipp->ipp_fields |= IPPF_UNICAST_HOPS; 1558 } 1559 retval = sctp_build_hdrs(sctp); 1560 break; 1561 case IPV6_UNSPEC_SRC: 1562 if (inlen < sizeof (int32_t)) { 1563 retval = EINVAL; 1564 break; 1565 } 1566 connp->conn_unspec_src = onoff; 1567 break; 1568 case IPV6_RECVPKTINFO: 1569 if (inlen < sizeof (int32_t)) { 1570 retval = EINVAL; 1571 break; 1572 } 1573 if (onoff) 1574 sctp->sctp_ipv6_recvancillary |= 1575 SCTP_IPV6_RECVPKTINFO; 1576 else 1577 sctp->sctp_ipv6_recvancillary &= 1578 ~SCTP_IPV6_RECVPKTINFO; 1579 /* Send it with the next msg */ 1580 sctp->sctp_recvifindex = 0; 1581 connp->conn_ipv6_recvpktinfo = onoff; 1582 break; 1583 case IPV6_RECVHOPLIMIT: 1584 if (inlen < sizeof (int32_t)) { 1585 retval = EINVAL; 1586 break; 1587 } 1588 if (onoff) 1589 sctp->sctp_ipv6_recvancillary |= 1590 SCTP_IPV6_RECVHOPLIMIT; 1591 else 1592 sctp->sctp_ipv6_recvancillary &= 1593 ~SCTP_IPV6_RECVHOPLIMIT; 1594 sctp->sctp_recvhops = 0xffffffffU; 1595 connp->conn_ipv6_recvhoplimit = onoff; 1596 break; 1597 case IPV6_RECVHOPOPTS: 1598 if (inlen < sizeof (int32_t)) { 1599 retval = EINVAL; 1600 break; 1601 } 1602 if (onoff) 1603 sctp->sctp_ipv6_recvancillary |= 1604 SCTP_IPV6_RECVHOPOPTS; 1605 else 1606 sctp->sctp_ipv6_recvancillary &= 1607 ~SCTP_IPV6_RECVHOPOPTS; 1608 connp->conn_ipv6_recvhopopts = onoff; 1609 break; 1610 case IPV6_RECVDSTOPTS: 1611 if (inlen < sizeof (int32_t)) { 1612 retval = EINVAL; 1613 break; 1614 } 1615 if (onoff) 1616 sctp->sctp_ipv6_recvancillary |= 1617 SCTP_IPV6_RECVDSTOPTS; 1618 else 1619 sctp->sctp_ipv6_recvancillary &= 1620 ~SCTP_IPV6_RECVDSTOPTS; 1621 connp->conn_ipv6_recvdstopts = onoff; 1622 break; 1623 case IPV6_RECVRTHDR: 1624 if (inlen < sizeof (int32_t)) { 1625 retval = EINVAL; 1626 break; 1627 } 1628 if (onoff) 1629 sctp->sctp_ipv6_recvancillary |= 1630 SCTP_IPV6_RECVRTHDR; 1631 else 1632 sctp->sctp_ipv6_recvancillary &= 1633 ~SCTP_IPV6_RECVRTHDR; 1634 connp->conn_ipv6_recvrthdr = onoff; 1635 break; 1636 case IPV6_RECVRTHDRDSTOPTS: 1637 if (inlen < sizeof (int32_t)) { 1638 retval = EINVAL; 1639 break; 1640 } 1641 if (onoff) 1642 sctp->sctp_ipv6_recvancillary |= 1643 SCTP_IPV6_RECVRTDSTOPTS; 1644 else 1645 sctp->sctp_ipv6_recvancillary &= 1646 ~SCTP_IPV6_RECVRTDSTOPTS; 1647 connp->conn_ipv6_recvrtdstopts = onoff; 1648 break; 1649 case IPV6_PKTINFO: 1650 if (inlen != 0 && 1651 inlen != sizeof (struct in6_pktinfo)) { 1652 retval = EINVAL; 1653 break; 1654 } 1655 1656 if (inlen == 0) { 1657 ipp->ipp_fields &= ~(IPPF_IFINDEX |IPPF_ADDR); 1658 } else { 1659 struct in6_pktinfo *pkti; 1660 1661 pkti = (struct in6_pktinfo *)invalp; 1662 /* XXX Need to check if the index exists */ 1663 ipp->ipp_ifindex = pkti->ipi6_ifindex; 1664 ipp->ipp_addr = pkti->ipi6_addr; 1665 if (ipp->ipp_ifindex != 0) 1666 ipp->ipp_fields |= IPPF_IFINDEX; 1667 else 1668 ipp->ipp_fields &= ~IPPF_IFINDEX; 1669 if (!IN6_IS_ADDR_UNSPECIFIED(&ipp->ipp_addr)) 1670 ipp->ipp_fields |= IPPF_ADDR; 1671 else 1672 ipp->ipp_fields &= ~IPPF_ADDR; 1673 } 1674 retval = sctp_build_hdrs(sctp); 1675 break; 1676 case IPV6_NEXTHOP: { 1677 struct sockaddr_in6 *sin6; 1678 1679 if (inlen != 0 && inlen != sizeof (sin6_t)) { 1680 retval = EINVAL; 1681 break; 1682 } 1683 1684 if (inlen == 0) { 1685 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1686 } else { 1687 sin6 = (struct sockaddr_in6 *)invalp; 1688 if (sin6->sin6_family != AF_INET6) { 1689 retval = EAFNOSUPPORT; 1690 break; 1691 } 1692 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 1693 retval = EADDRNOTAVAIL; 1694 break; 1695 } 1696 ipp->ipp_nexthop = sin6->sin6_addr; 1697 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1698 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1699 } else { 1700 ire_t *ire; 1701 1702 ire = ire_route_lookup_v6( 1703 &sin6->sin6_addr, 0, 0, 0, NULL, 1704 NULL, NULL, MATCH_IRE_DEFAULT); 1705 if (ire == NULL) { 1706 retval = EHOSTUNREACH; 1707 break; 1708 } 1709 ire_refrele(ire); 1710 ipp->ipp_fields |= IPPF_NEXTHOP; 1711 } 1712 } 1713 retval = sctp_build_hdrs(sctp); 1714 break; 1715 } 1716 case IPV6_HOPOPTS: { 1717 ip6_hbh_t *hopts = (ip6_hbh_t *)invalp; 1718 1719 if (inlen != 0 && 1720 inlen != (8 * (hopts->ip6h_len + 1))) { 1721 retval = EINVAL; 1722 break; 1723 } 1724 1725 if (inlen == 0) { 1726 ipp->ipp_fields &= ~IPPF_HOPOPTS; 1727 } else { 1728 retval = sctp_pkt_set((uchar_t *)invalp, inlen, 1729 (uchar_t **)&ipp->ipp_hopopts, 1730 &ipp->ipp_hopoptslen); 1731 if (retval != 0) 1732 break; 1733 ipp->ipp_fields |= IPPF_HOPOPTS; 1734 } 1735 retval = sctp_build_hdrs(sctp); 1736 break; 1737 } 1738 case IPV6_RTHDRDSTOPTS: { 1739 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1740 1741 if (inlen != 0 && 1742 inlen != (8 * (dopts->ip6d_len + 1))) { 1743 retval = EINVAL; 1744 break; 1745 } 1746 1747 if (inlen == 0) { 1748 ipp->ipp_fields &= ~IPPF_RTDSTOPTS; 1749 } else { 1750 retval = sctp_pkt_set((uchar_t *)invalp, inlen, 1751 (uchar_t **)&ipp->ipp_rtdstopts, 1752 &ipp->ipp_rtdstoptslen); 1753 if (retval != 0) 1754 break; 1755 ipp->ipp_fields |= IPPF_RTDSTOPTS; 1756 } 1757 retval = sctp_build_hdrs(sctp); 1758 break; 1759 } 1760 case IPV6_DSTOPTS: { 1761 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1762 1763 if (inlen != 0 && 1764 inlen != (8 * (dopts->ip6d_len + 1))) { 1765 retval = EINVAL; 1766 break; 1767 } 1768 1769 if (inlen == 0) { 1770 ipp->ipp_fields &= ~IPPF_DSTOPTS; 1771 } else { 1772 retval = sctp_pkt_set((uchar_t *)invalp, inlen, 1773 (uchar_t **)&ipp->ipp_dstopts, 1774 &ipp->ipp_dstoptslen); 1775 if (retval != 0) 1776 break; 1777 ipp->ipp_fields |= IPPF_DSTOPTS; 1778 } 1779 retval = sctp_build_hdrs(sctp); 1780 break; 1781 } 1782 case IPV6_RTHDR: { 1783 ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp; 1784 1785 if (inlen != 0 && 1786 inlen != (8 * (rt->ip6r_len + 1))) { 1787 retval = EINVAL; 1788 break; 1789 } 1790 1791 if (inlen == 0) { 1792 ipp->ipp_fields &= ~IPPF_RTHDR; 1793 } else { 1794 retval = sctp_pkt_set((uchar_t *)invalp, inlen, 1795 (uchar_t **)&ipp->ipp_rthdr, 1796 &ipp->ipp_rthdrlen); 1797 if (retval != 0) 1798 break; 1799 ipp->ipp_fields |= IPPF_RTHDR; 1800 } 1801 retval = sctp_build_hdrs(sctp); 1802 break; 1803 } 1804 case IPV6_SEC_OPT: 1805 /* 1806 * We should not allow policy setting after 1807 * we start listening for connections. 1808 */ 1809 if (sctp->sctp_state >= SCTPS_LISTEN) { 1810 retval = EINVAL; 1811 } else { 1812 retval = ipsec_set_req(sctp->sctp_credp, 1813 sctp->sctp_connp, (ipsec_req_t *)invalp); 1814 } 1815 break; 1816 case IPV6_V6ONLY: 1817 /* 1818 * After the bound state, setting the v6only option 1819 * is too late. 1820 */ 1821 if (sctp->sctp_state >= SCTPS_BOUND) { 1822 retval = EINVAL; 1823 } else { 1824 sctp->sctp_connp->conn_ipv6_v6only = onoff; 1825 } 1826 break; 1827 default: 1828 retval = EINVAL; 1829 break; 1830 } 1831 break; 1832 } 1833 default: 1834 retval = EINVAL; 1835 break; 1836 } 1837 1838 WAKE_SCTP(sctp); 1839 return (retval); 1840 } 1841 1842 /* 1843 * SCTP exported kernel interface for geting the first source address of 1844 * a sctp_t. The parameter addr is assumed to have enough space to hold 1845 * one socket address. 1846 */ 1847 int 1848 sctp_getsockname(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1849 { 1850 int err = 0; 1851 int addrcnt = 1; 1852 sin_t *sin4; 1853 sin6_t *sin6; 1854 1855 ASSERT(sctp != NULL); 1856 1857 RUN_SCTP(sctp); 1858 addr->sa_family = sctp->sctp_family; 1859 switch (sctp->sctp_family) { 1860 case AF_INET: 1861 sin4 = (sin_t *)addr; 1862 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1863 sctp->sctp_bound_to_all) { 1864 sin4->sin_addr.s_addr = INADDR_ANY; 1865 sin4->sin_port = sctp->sctp_lport; 1866 } else { 1867 err = sctp_getmyaddrs(sctp, sin4, &addrcnt); 1868 if (err != 0) { 1869 *addrlen = 0; 1870 break; 1871 } 1872 } 1873 *addrlen = sizeof (struct sockaddr_in); 1874 break; 1875 case AF_INET6: 1876 sin6 = (sin6_t *)addr; 1877 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1878 sctp->sctp_bound_to_all) { 1879 bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr)); 1880 sin6->sin6_port = sctp->sctp_lport; 1881 } else { 1882 err = sctp_getmyaddrs(sctp, sin6, &addrcnt); 1883 if (err != 0) { 1884 *addrlen = 0; 1885 break; 1886 } 1887 } 1888 *addrlen = sizeof (struct sockaddr_in6); 1889 sin6->sin6_flowinfo = sctp->sctp_ip6h->ip6_vcf & 1890 ~IPV6_VERS_AND_FLOW_MASK; 1891 sin6->sin6_scope_id = 0; 1892 sin6->__sin6_src_id = 0; 1893 break; 1894 } 1895 WAKE_SCTP(sctp); 1896 return (err); 1897 } 1898 1899 /* 1900 * SCTP exported kernel interface for geting the primary peer address of 1901 * a sctp_t. The parameter addr is assumed to have enough space to hold 1902 * one socket address. 1903 */ 1904 int 1905 sctp_getpeername(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1906 { 1907 int err = 0; 1908 int addrcnt = 1; 1909 sin6_t *sin6; 1910 1911 ASSERT(sctp != NULL); 1912 1913 RUN_SCTP(sctp); 1914 addr->sa_family = sctp->sctp_family; 1915 switch (sctp->sctp_family) { 1916 case AF_INET: 1917 err = sctp_getpeeraddrs(sctp, addr, &addrcnt); 1918 if (err != 0) { 1919 *addrlen = 0; 1920 break; 1921 } 1922 *addrlen = sizeof (struct sockaddr_in); 1923 break; 1924 case AF_INET6: 1925 sin6 = (sin6_t *)addr; 1926 err = sctp_getpeeraddrs(sctp, sin6, &addrcnt); 1927 if (err != 0) { 1928 *addrlen = 0; 1929 break; 1930 } 1931 *addrlen = sizeof (struct sockaddr_in6); 1932 sin6->sin6_flowinfo = 0; 1933 sin6->sin6_scope_id = 0; 1934 sin6->__sin6_src_id = 0; 1935 break; 1936 } 1937 WAKE_SCTP(sctp); 1938 return (err); 1939 } 1940 1941 /* 1942 * Return a list of IP addresses of the peer endpoint of this sctp_t. 1943 * The parameter paddrs is supposed to be either (struct sockaddr_in *) or 1944 * (struct sockaddr_in6 *) depending on the address family of the sctp_t. 1945 */ 1946 int 1947 sctp_getpeeraddrs(sctp_t *sctp, void *paddrs, int *addrcnt) 1948 { 1949 int family; 1950 struct sockaddr_in *sin4; 1951 struct sockaddr_in6 *sin6; 1952 int max; 1953 int cnt; 1954 sctp_faddr_t *fp = sctp->sctp_faddrs; 1955 in6_addr_t addr; 1956 1957 ASSERT(sctp != NULL); 1958 1959 if (sctp->sctp_faddrs == NULL) 1960 return (ENOTCONN); 1961 1962 family = sctp->sctp_family; 1963 max = *addrcnt; 1964 1965 /* If we want only one, give the primary */ 1966 if (max == 1) { 1967 addr = sctp->sctp_primary->faddr; 1968 switch (family) { 1969 case AF_INET: 1970 sin4 = paddrs; 1971 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1972 sin4->sin_port = sctp->sctp_fport; 1973 sin4->sin_family = AF_INET; 1974 break; 1975 1976 case AF_INET6: 1977 sin6 = paddrs; 1978 sin6->sin6_addr = addr; 1979 sin6->sin6_port = sctp->sctp_fport; 1980 sin6->sin6_family = AF_INET6; 1981 break; 1982 } 1983 return (0); 1984 } 1985 1986 for (cnt = 0; cnt < max && fp != NULL; cnt++, fp = fp->next) { 1987 addr = fp->faddr; 1988 switch (family) { 1989 case AF_INET: 1990 ASSERT(IN6_IS_ADDR_V4MAPPED(&addr)); 1991 sin4 = (struct sockaddr_in *)paddrs + cnt; 1992 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1993 sin4->sin_port = sctp->sctp_fport; 1994 sin4->sin_family = AF_INET; 1995 break; 1996 case AF_INET6: 1997 sin6 = (struct sockaddr_in6 *)paddrs + cnt; 1998 sin6->sin6_addr = addr; 1999 sin6->sin6_port = sctp->sctp_fport; 2000 sin6->sin6_family = AF_INET6; 2001 break; 2002 } 2003 } 2004 *addrcnt = cnt; 2005 return (0); 2006 } 2007