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 *i1 = MSS_ROUNDUP(*i1, (sctp->sctp_mss - 1302 sizeof (sctp_data_hdr_t))); 1303 sctp->sctp_rwnd = *i1; 1304 } 1305 /* 1306 * XXX should we return the rwnd here 1307 * and sctp_opt_get ? 1308 */ 1309 break; 1310 default: 1311 retval = EINVAL; 1312 break; 1313 } 1314 break; 1315 1316 case IPPROTO_SCTP: 1317 if (inlen < sizeof (int32_t)) { 1318 retval = EINVAL; 1319 break; 1320 } 1321 switch (name) { 1322 case SCTP_RTOINFO: 1323 retval = sctp_set_rtoinfo(sctp, invalp, inlen); 1324 break; 1325 case SCTP_ASSOCINFO: 1326 retval = sctp_set_assocparams(sctp, invalp, inlen); 1327 break; 1328 case SCTP_INITMSG: 1329 retval = sctp_set_initmsg(sctp, invalp, inlen); 1330 break; 1331 case SCTP_NODELAY: 1332 sctp->sctp_ndelay = ONOFF(*i1); 1333 break; 1334 case SCTP_AUTOCLOSE: 1335 if (SEC_TO_TICK(*i1) < 0) { 1336 retval = EINVAL; 1337 break; 1338 } 1339 /* Convert the number of seconds to ticks. */ 1340 sctp->sctp_autoclose = SEC_TO_TICK(*i1); 1341 sctp_heartbeat_timer(sctp); 1342 break; 1343 case SCTP_SET_PEER_PRIMARY_ADDR: 1344 retval = sctp_set_peerprim(sctp, invalp, inlen); 1345 break; 1346 case SCTP_PRIMARY_ADDR: 1347 retval = sctp_set_prim(sctp, invalp, inlen); 1348 break; 1349 case SCTP_ADAPTION_LAYER: { 1350 struct sctp_setadaption *ssb; 1351 1352 if (inlen < sizeof (struct sctp_setadaption)) { 1353 retval = EINVAL; 1354 break; 1355 } 1356 ssb = (struct sctp_setadaption *)invalp; 1357 sctp->sctp_send_adaption = 1; 1358 sctp->sctp_tx_adaption_code = ssb->ssb_adaption_ind; 1359 break; 1360 } 1361 case SCTP_PEER_ADDR_PARAMS: 1362 retval = sctp_set_peer_addr_params(sctp, invalp, 1363 inlen); 1364 break; 1365 case SCTP_DEFAULT_SEND_PARAM: 1366 retval = sctp_set_def_send_params(sctp, invalp, inlen); 1367 break; 1368 case SCTP_EVENTS: { 1369 struct sctp_event_subscribe *ev; 1370 1371 if (inlen < sizeof (struct sctp_event_subscribe)) { 1372 retval = EINVAL; 1373 break; 1374 } 1375 ev = (struct sctp_event_subscribe *)invalp; 1376 sctp->sctp_recvsndrcvinfo = 1377 ONOFF(ev->sctp_data_io_event); 1378 sctp->sctp_recvassocevnt = 1379 ONOFF(ev->sctp_association_event); 1380 sctp->sctp_recvpathevnt = 1381 ONOFF(ev->sctp_address_event); 1382 sctp->sctp_recvsendfailevnt = 1383 ONOFF(ev->sctp_send_failure_event); 1384 sctp->sctp_recvpeererr = 1385 ONOFF(ev->sctp_peer_error_event); 1386 sctp->sctp_recvshutdownevnt = 1387 ONOFF(ev->sctp_shutdown_event); 1388 sctp->sctp_recvpdevnt = 1389 ONOFF(ev->sctp_partial_delivery_event); 1390 sctp->sctp_recvalevnt = 1391 ONOFF(ev->sctp_adaption_layer_event); 1392 break; 1393 } 1394 case SCTP_ADD_ADDR: 1395 case SCTP_REM_ADDR: 1396 /* 1397 * The sctp_t has to be bound first before 1398 * the address list can be changed. 1399 */ 1400 if (sctp->sctp_state < SCTPS_BOUND) { 1401 retval = EINVAL; 1402 break; 1403 } 1404 if (sctp->sctp_family == AF_INET) { 1405 addrcnt = inlen / sizeof (struct sockaddr_in); 1406 } else { 1407 ASSERT(sctp->sctp_family == AF_INET6); 1408 addrcnt = inlen / sizeof (struct sockaddr_in6); 1409 } 1410 if (name == SCTP_ADD_ADDR) { 1411 retval = sctp_bind_add(sctp, invalp, addrcnt, 1412 B_TRUE); 1413 } else { 1414 retval = sctp_bind_del(sctp, invalp, addrcnt, 1415 B_TRUE); 1416 } 1417 break; 1418 case SCTP_UC_SWAP: { 1419 struct sctp_uc_swap *us; 1420 1421 /* 1422 * Change handle & upcalls. 1423 */ 1424 if (inlen < sizeof (*us)) { 1425 retval = EINVAL; 1426 break; 1427 } 1428 us = (struct sctp_uc_swap *)invalp; 1429 sctp->sctp_ulpd = us->sus_handle; 1430 bcopy(us->sus_upcalls, &sctp->sctp_upcalls, 1431 sizeof (sctp_upcalls_t)); 1432 break; 1433 } 1434 case SCTP_PRSCTP: 1435 sctp->sctp_prsctp_aware = onoff; 1436 break; 1437 case SCTP_I_WANT_MAPPED_V4_ADDR: 1438 case SCTP_MAXSEG: 1439 case SCTP_DISABLE_FRAGMENTS: 1440 /* Not yet supported. */ 1441 default: 1442 retval = EINVAL; 1443 break; 1444 } 1445 break; 1446 1447 case IPPROTO_IP: 1448 if (sctp->sctp_family != AF_INET) { 1449 retval = ENOPROTOOPT; 1450 break; 1451 } 1452 if ((name != IP_OPTIONS) && (inlen < sizeof (int32_t))) { 1453 retval = EINVAL; 1454 break; 1455 } 1456 switch (name) { 1457 case IP_OPTIONS: 1458 case T_IP_OPTIONS: 1459 retval = sctp_opt_set_header(sctp, B_FALSE, 1460 invalp, inlen); 1461 break; 1462 case IP_TOS: 1463 case T_IP_TOS: 1464 sctp->sctp_ipha->ipha_type_of_service = (uchar_t)*i1; 1465 break; 1466 case IP_TTL: 1467 sctp->sctp_ipha->ipha_ttl = (uchar_t)*i1; 1468 break; 1469 case IP_SEC_OPT: 1470 /* 1471 * We should not allow policy setting after 1472 * we start listening for connections. 1473 */ 1474 if (sctp->sctp_state >= SCTPS_LISTEN) { 1475 retval = EINVAL; 1476 } else { 1477 retval = ipsec_set_req(sctp->sctp_credp, 1478 sctp->sctp_connp, (ipsec_req_t *)invalp); 1479 } 1480 break; 1481 /* IP level options */ 1482 case IP_RECVIF: 1483 connp->conn_recvif = onoff; 1484 break; 1485 case IP_RECVSLLA: 1486 connp->conn_recvslla = onoff; 1487 break; 1488 case IP_UNSPEC_SRC: 1489 connp->conn_unspec_src = onoff; 1490 break; 1491 default: 1492 retval = EINVAL; 1493 break; 1494 } 1495 break; 1496 case IPPROTO_IPV6: { 1497 if (sctp->sctp_family != AF_INET6) { 1498 retval = ENOPROTOOPT; 1499 break; 1500 } 1501 1502 switch (name) { 1503 case IPV6_UNICAST_HOPS: 1504 if (inlen < sizeof (int32_t)) { 1505 retval = EINVAL; 1506 break; 1507 } 1508 if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) { 1509 retval = EINVAL; 1510 break; 1511 } 1512 if (*i1 == -1) { 1513 ipp->ipp_unicast_hops = sctp_ipv6_hoplimit; 1514 ipp->ipp_fields &= ~IPPF_UNICAST_HOPS; 1515 } else { 1516 ipp->ipp_unicast_hops = (uint8_t)*i1; 1517 ipp->ipp_fields |= IPPF_UNICAST_HOPS; 1518 } 1519 retval = sctp_build_hdrs(sctp); 1520 break; 1521 case IPV6_UNSPEC_SRC: 1522 if (inlen < sizeof (int32_t)) { 1523 retval = EINVAL; 1524 break; 1525 } 1526 connp->conn_unspec_src = onoff; 1527 break; 1528 case IPV6_RECVPKTINFO: 1529 if (inlen < sizeof (int32_t)) { 1530 retval = EINVAL; 1531 break; 1532 } 1533 if (onoff) 1534 sctp->sctp_ipv6_recvancillary |= 1535 SCTP_IPV6_RECVPKTINFO; 1536 else 1537 sctp->sctp_ipv6_recvancillary &= 1538 ~SCTP_IPV6_RECVPKTINFO; 1539 /* Send it with the next msg */ 1540 sctp->sctp_recvifindex = 0; 1541 connp->conn_ipv6_recvpktinfo = onoff; 1542 break; 1543 case IPV6_RECVHOPLIMIT: 1544 if (inlen < sizeof (int32_t)) { 1545 retval = EINVAL; 1546 break; 1547 } 1548 if (onoff) 1549 sctp->sctp_ipv6_recvancillary |= 1550 SCTP_IPV6_RECVHOPLIMIT; 1551 else 1552 sctp->sctp_ipv6_recvancillary &= 1553 ~SCTP_IPV6_RECVHOPLIMIT; 1554 sctp->sctp_recvhops = 0xffffffffU; 1555 connp->conn_ipv6_recvhoplimit = onoff; 1556 break; 1557 case IPV6_RECVHOPOPTS: 1558 if (inlen < sizeof (int32_t)) { 1559 retval = EINVAL; 1560 break; 1561 } 1562 if (onoff) 1563 sctp->sctp_ipv6_recvancillary |= 1564 SCTP_IPV6_RECVHOPOPTS; 1565 else 1566 sctp->sctp_ipv6_recvancillary &= 1567 ~SCTP_IPV6_RECVHOPOPTS; 1568 connp->conn_ipv6_recvhopopts = onoff; 1569 break; 1570 case IPV6_RECVDSTOPTS: 1571 if (inlen < sizeof (int32_t)) { 1572 retval = EINVAL; 1573 break; 1574 } 1575 if (onoff) 1576 sctp->sctp_ipv6_recvancillary |= 1577 SCTP_IPV6_RECVDSTOPTS; 1578 else 1579 sctp->sctp_ipv6_recvancillary &= 1580 ~SCTP_IPV6_RECVDSTOPTS; 1581 connp->conn_ipv6_recvdstopts = onoff; 1582 break; 1583 case IPV6_RECVRTHDR: 1584 if (inlen < sizeof (int32_t)) { 1585 retval = EINVAL; 1586 break; 1587 } 1588 if (onoff) 1589 sctp->sctp_ipv6_recvancillary |= 1590 SCTP_IPV6_RECVRTHDR; 1591 else 1592 sctp->sctp_ipv6_recvancillary &= 1593 ~SCTP_IPV6_RECVRTHDR; 1594 connp->conn_ipv6_recvrthdr = onoff; 1595 break; 1596 case IPV6_RECVRTHDRDSTOPTS: 1597 if (inlen < sizeof (int32_t)) { 1598 retval = EINVAL; 1599 break; 1600 } 1601 if (onoff) 1602 sctp->sctp_ipv6_recvancillary |= 1603 SCTP_IPV6_RECVRTDSTOPTS; 1604 else 1605 sctp->sctp_ipv6_recvancillary &= 1606 ~SCTP_IPV6_RECVRTDSTOPTS; 1607 connp->conn_ipv6_recvrtdstopts = onoff; 1608 break; 1609 case IPV6_PKTINFO: 1610 if (inlen != 0 && 1611 inlen != sizeof (struct in6_pktinfo)) { 1612 retval = EINVAL; 1613 break; 1614 } 1615 1616 if (inlen == 0) { 1617 ipp->ipp_fields &= ~(IPPF_IFINDEX |IPPF_ADDR); 1618 } else { 1619 struct in6_pktinfo *pkti; 1620 1621 pkti = (struct in6_pktinfo *)invalp; 1622 /* XXX Need to check if the index exists */ 1623 ipp->ipp_ifindex = pkti->ipi6_ifindex; 1624 ipp->ipp_addr = pkti->ipi6_addr; 1625 if (ipp->ipp_ifindex != 0) 1626 ipp->ipp_fields |= IPPF_IFINDEX; 1627 else 1628 ipp->ipp_fields &= ~IPPF_IFINDEX; 1629 if (!IN6_IS_ADDR_UNSPECIFIED(&ipp->ipp_addr)) 1630 ipp->ipp_fields |= IPPF_ADDR; 1631 else 1632 ipp->ipp_fields &= ~IPPF_ADDR; 1633 } 1634 retval = sctp_build_hdrs(sctp); 1635 break; 1636 case IPV6_NEXTHOP: { 1637 struct sockaddr_in6 *sin6; 1638 1639 if (inlen != 0 && inlen != sizeof (sin6_t)) { 1640 retval = EINVAL; 1641 break; 1642 } 1643 1644 if (inlen == 0) { 1645 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1646 } else { 1647 sin6 = (struct sockaddr_in6 *)invalp; 1648 if (sin6->sin6_family != AF_INET6) { 1649 retval = EAFNOSUPPORT; 1650 break; 1651 } 1652 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 1653 retval = EADDRNOTAVAIL; 1654 break; 1655 } 1656 ipp->ipp_nexthop = sin6->sin6_addr; 1657 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1658 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1659 } else { 1660 ire_t *ire; 1661 1662 ire = ire_route_lookup_v6( 1663 &sin6->sin6_addr, 0, 0, 0, NULL, 1664 NULL, NULL, MATCH_IRE_DEFAULT); 1665 if (ire == NULL) { 1666 retval = EHOSTUNREACH; 1667 break; 1668 } 1669 ire_refrele(ire); 1670 ipp->ipp_fields |= IPPF_NEXTHOP; 1671 } 1672 } 1673 retval = sctp_build_hdrs(sctp); 1674 break; 1675 } 1676 case IPV6_HOPOPTS: { 1677 ip6_hbh_t *hopts = (ip6_hbh_t *)invalp; 1678 1679 if (inlen != 0 && 1680 inlen != (8 * (hopts->ip6h_len + 1))) { 1681 retval = EINVAL; 1682 break; 1683 } 1684 1685 if (inlen == 0) { 1686 ipp->ipp_fields &= ~IPPF_HOPOPTS; 1687 } else { 1688 retval = sctp_pkt_set((uchar_t *)invalp, inlen, 1689 (uchar_t **)&ipp->ipp_hopopts, 1690 &ipp->ipp_hopoptslen); 1691 if (retval != 0) 1692 break; 1693 ipp->ipp_fields |= IPPF_HOPOPTS; 1694 } 1695 retval = sctp_build_hdrs(sctp); 1696 break; 1697 } 1698 case IPV6_RTHDRDSTOPTS: { 1699 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1700 1701 if (inlen != 0 && 1702 inlen != (8 * (dopts->ip6d_len + 1))) { 1703 retval = EINVAL; 1704 break; 1705 } 1706 1707 if (inlen == 0) { 1708 ipp->ipp_fields &= ~IPPF_RTDSTOPTS; 1709 } else { 1710 retval = sctp_pkt_set((uchar_t *)invalp, inlen, 1711 (uchar_t **)&ipp->ipp_rtdstopts, 1712 &ipp->ipp_rtdstoptslen); 1713 if (retval != 0) 1714 break; 1715 ipp->ipp_fields |= IPPF_RTDSTOPTS; 1716 } 1717 retval = sctp_build_hdrs(sctp); 1718 break; 1719 } 1720 case IPV6_DSTOPTS: { 1721 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1722 1723 if (inlen != 0 && 1724 inlen != (8 * (dopts->ip6d_len + 1))) { 1725 retval = EINVAL; 1726 break; 1727 } 1728 1729 if (inlen == 0) { 1730 ipp->ipp_fields &= ~IPPF_DSTOPTS; 1731 } else { 1732 retval = sctp_pkt_set((uchar_t *)invalp, inlen, 1733 (uchar_t **)&ipp->ipp_dstopts, 1734 &ipp->ipp_dstoptslen); 1735 if (retval != 0) 1736 break; 1737 ipp->ipp_fields |= IPPF_DSTOPTS; 1738 } 1739 retval = sctp_build_hdrs(sctp); 1740 break; 1741 } 1742 case IPV6_RTHDR: { 1743 ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp; 1744 1745 if (inlen != 0 && 1746 inlen != (8 * (rt->ip6r_len + 1))) { 1747 retval = EINVAL; 1748 break; 1749 } 1750 1751 if (inlen == 0) { 1752 ipp->ipp_fields &= ~IPPF_RTHDR; 1753 } else { 1754 retval = sctp_pkt_set((uchar_t *)invalp, inlen, 1755 (uchar_t **)&ipp->ipp_rthdr, 1756 &ipp->ipp_rthdrlen); 1757 if (retval != 0) 1758 break; 1759 ipp->ipp_fields |= IPPF_RTHDR; 1760 } 1761 retval = sctp_build_hdrs(sctp); 1762 break; 1763 } 1764 case IPV6_SEC_OPT: 1765 /* 1766 * We should not allow policy setting after 1767 * we start listening for connections. 1768 */ 1769 if (sctp->sctp_state >= SCTPS_LISTEN) { 1770 retval = EINVAL; 1771 } else { 1772 retval = ipsec_set_req(sctp->sctp_credp, 1773 sctp->sctp_connp, (ipsec_req_t *)invalp); 1774 } 1775 break; 1776 case IPV6_V6ONLY: 1777 /* 1778 * After the bound state, setting the v6only option 1779 * is too late. 1780 */ 1781 if (sctp->sctp_state >= SCTPS_BOUND) { 1782 retval = EINVAL; 1783 } else { 1784 sctp->sctp_connp->conn_ipv6_v6only = onoff; 1785 } 1786 break; 1787 default: 1788 retval = EINVAL; 1789 break; 1790 } 1791 break; 1792 } 1793 default: 1794 retval = EINVAL; 1795 break; 1796 } 1797 1798 WAKE_SCTP(sctp); 1799 return (retval); 1800 } 1801 1802 /* 1803 * SCTP exported kernel interface for geting the first source address of 1804 * a sctp_t. The parameter addr is assumed to have enough space to hold 1805 * one socket address. 1806 */ 1807 int 1808 sctp_getsockname(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1809 { 1810 int err = 0; 1811 int addrcnt = 1; 1812 sin_t *sin4; 1813 sin6_t *sin6; 1814 1815 ASSERT(sctp != NULL); 1816 1817 RUN_SCTP(sctp); 1818 addr->sa_family = sctp->sctp_family; 1819 switch (sctp->sctp_family) { 1820 case AF_INET: 1821 sin4 = (sin_t *)addr; 1822 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1823 sctp->sctp_bound_to_all) { 1824 sin4->sin_addr.s_addr = INADDR_ANY; 1825 sin4->sin_port = sctp->sctp_lport; 1826 } else { 1827 err = sctp_getmyaddrs(sctp, sin4, &addrcnt); 1828 if (err != 0) { 1829 *addrlen = 0; 1830 break; 1831 } 1832 } 1833 *addrlen = sizeof (struct sockaddr_in); 1834 break; 1835 case AF_INET6: 1836 sin6 = (sin6_t *)addr; 1837 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1838 sctp->sctp_bound_to_all) { 1839 bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr)); 1840 sin6->sin6_port = sctp->sctp_lport; 1841 } else { 1842 err = sctp_getmyaddrs(sctp, sin6, &addrcnt); 1843 if (err != 0) { 1844 *addrlen = 0; 1845 break; 1846 } 1847 } 1848 *addrlen = sizeof (struct sockaddr_in6); 1849 sin6->sin6_flowinfo = sctp->sctp_ip6h->ip6_vcf & 1850 ~IPV6_VERS_AND_FLOW_MASK; 1851 sin6->sin6_scope_id = 0; 1852 sin6->__sin6_src_id = 0; 1853 break; 1854 } 1855 WAKE_SCTP(sctp); 1856 return (err); 1857 } 1858 1859 /* 1860 * SCTP exported kernel interface for geting the primary peer address of 1861 * a sctp_t. The parameter addr is assumed to have enough space to hold 1862 * one socket address. 1863 */ 1864 int 1865 sctp_getpeername(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1866 { 1867 int err = 0; 1868 int addrcnt = 1; 1869 sin6_t *sin6; 1870 1871 ASSERT(sctp != NULL); 1872 1873 RUN_SCTP(sctp); 1874 addr->sa_family = sctp->sctp_family; 1875 switch (sctp->sctp_family) { 1876 case AF_INET: 1877 err = sctp_getpeeraddrs(sctp, addr, &addrcnt); 1878 if (err != 0) { 1879 *addrlen = 0; 1880 break; 1881 } 1882 *addrlen = sizeof (struct sockaddr_in); 1883 break; 1884 case AF_INET6: 1885 sin6 = (sin6_t *)addr; 1886 err = sctp_getpeeraddrs(sctp, sin6, &addrcnt); 1887 if (err != 0) { 1888 *addrlen = 0; 1889 break; 1890 } 1891 *addrlen = sizeof (struct sockaddr_in6); 1892 sin6->sin6_flowinfo = 0; 1893 sin6->sin6_scope_id = 0; 1894 sin6->__sin6_src_id = 0; 1895 break; 1896 } 1897 WAKE_SCTP(sctp); 1898 return (err); 1899 } 1900 1901 /* 1902 * Return a list of IP addresses of the peer endpoint of this sctp_t. 1903 * The parameter paddrs is supposed to be either (struct sockaddr_in *) or 1904 * (struct sockaddr_in6 *) depending on the address family of the sctp_t. 1905 */ 1906 int 1907 sctp_getpeeraddrs(sctp_t *sctp, void *paddrs, int *addrcnt) 1908 { 1909 int family; 1910 struct sockaddr_in *sin4; 1911 struct sockaddr_in6 *sin6; 1912 int max; 1913 int cnt; 1914 sctp_faddr_t *fp = sctp->sctp_faddrs; 1915 in6_addr_t addr; 1916 1917 ASSERT(sctp != NULL); 1918 1919 if (sctp->sctp_faddrs == NULL) 1920 return (ENOTCONN); 1921 1922 family = sctp->sctp_family; 1923 max = *addrcnt; 1924 1925 /* If we want only one, give the primary */ 1926 if (max == 1) { 1927 addr = sctp->sctp_primary->faddr; 1928 switch (family) { 1929 case AF_INET: 1930 sin4 = paddrs; 1931 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1932 sin4->sin_port = sctp->sctp_fport; 1933 sin4->sin_family = AF_INET; 1934 break; 1935 1936 case AF_INET6: 1937 sin6 = paddrs; 1938 sin6->sin6_addr = addr; 1939 sin6->sin6_port = sctp->sctp_fport; 1940 sin6->sin6_family = AF_INET6; 1941 break; 1942 } 1943 return (0); 1944 } 1945 1946 for (cnt = 0; cnt < max && fp != NULL; cnt++, fp = fp->next) { 1947 addr = fp->faddr; 1948 switch (family) { 1949 case AF_INET: 1950 ASSERT(IN6_IS_ADDR_V4MAPPED(&addr)); 1951 sin4 = (struct sockaddr_in *)paddrs + cnt; 1952 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1953 sin4->sin_port = sctp->sctp_fport; 1954 sin4->sin_family = AF_INET; 1955 break; 1956 case AF_INET6: 1957 sin6 = (struct sockaddr_in6 *)paddrs + cnt; 1958 sin6->sin6_addr = addr; 1959 sin6->sin6_port = sctp->sctp_fport; 1960 sin6->sin6_family = AF_INET6; 1961 break; 1962 } 1963 } 1964 *addrcnt = cnt; 1965 return (0); 1966 } 1967