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