1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * Copyright (c) 2018, Joyent, Inc. 28 * Copyright 2024 Oxide Computer Company 29 * Copyright 2026 Edgecast Cloud LLC. 30 */ 31 32 #include <sys/types.h> 33 #include <sys/stream.h> 34 #define _SUN_TPI_VERSION 2 35 #include <sys/tihdr.h> 36 #include <sys/socket.h> 37 #include <sys/xti_inet.h> 38 #include <sys/systm.h> 39 #include <sys/ddi.h> 40 #include <sys/sunddi.h> 41 #include <sys/kmem.h> 42 #include <sys/strsubr.h> 43 #include <sys/strsun.h> 44 #include <sys/policy.h> 45 46 #include <inet/common.h> 47 #include <netinet/ip6.h> 48 #include <inet/ip.h> 49 #include <inet/ip_ire.h> 50 #include <inet/ip_if.h> 51 #include <inet/proto_set.h> 52 #include <inet/ipclassifier.h> 53 #include <inet/ipsec_impl.h> 54 55 #include <netinet/in.h> 56 #include <netinet/ip.h> 57 #include <netinet/tcp.h> 58 59 #include <inet/common.h> 60 #include <inet/ip.h> 61 #include <inet/ip6.h> 62 #include <inet/sctp_itf.h> 63 #include "sctp_impl.h" 64 #include "sctp_asconf.h" 65 #include "sctp_addr.h" 66 67 static int sctp_getpeeraddrs(sctp_t *, void *, int *); 68 69 static int 70 sctp_get_status(sctp_t *sctp, void *ptr) 71 { 72 struct sctp_status *sstat = ptr; 73 sctp_faddr_t *fp; 74 struct sockaddr_in *sin; 75 struct sockaddr_in6 *sin6; 76 struct sctp_paddrinfo *sp; 77 mblk_t *meta, *mp; 78 int i; 79 conn_t *connp = sctp->sctp_connp; 80 81 sstat->sstat_state = sctp->sctp_state; 82 sstat->sstat_rwnd = sctp->sctp_frwnd; 83 84 sp = &sstat->sstat_primary; 85 if (!sctp->sctp_primary) { 86 bzero(sp, sizeof (*sp)); 87 goto noprim; 88 } 89 fp = sctp->sctp_primary; 90 91 if (fp->sf_isv4) { 92 sin = (struct sockaddr_in *)&sp->spinfo_address; 93 sin->sin_family = AF_INET; 94 sin->sin_port = connp->conn_fport; 95 IN6_V4MAPPED_TO_INADDR(&fp->sf_faddr, &sin->sin_addr); 96 sp->spinfo_mtu = sctp->sctp_hdr_len; 97 } else { 98 sin6 = (struct sockaddr_in6 *)&sp->spinfo_address; 99 sin6->sin6_family = AF_INET6; 100 sin6->sin6_port = connp->conn_fport; 101 sin6->sin6_addr = fp->sf_faddr; 102 sp->spinfo_mtu = sctp->sctp_hdr6_len; 103 } 104 sp->spinfo_state = fp->sf_state == SCTP_FADDRS_ALIVE ? SCTP_ACTIVE : 105 SCTP_INACTIVE; 106 sp->spinfo_cwnd = fp->sf_cwnd; 107 sp->spinfo_srtt = fp->sf_srtt; 108 sp->spinfo_rto = fp->sf_rto; 109 sp->spinfo_mtu += fp->sf_pmss; 110 111 noprim: 112 sstat->sstat_unackdata = 0; 113 sstat->sstat_penddata = 0; 114 sstat->sstat_instrms = sctp->sctp_num_istr; 115 sstat->sstat_outstrms = sctp->sctp_num_ostr; 116 sstat->sstat_fragmentation_point = sctp->sctp_mss - 117 sizeof (sctp_data_hdr_t); 118 119 /* count unack'd */ 120 for (meta = sctp->sctp_xmit_head; meta; meta = meta->b_next) { 121 for (mp = meta->b_cont; mp; mp = mp->b_next) { 122 if (!SCTP_CHUNK_ISSENT(mp)) { 123 break; 124 } 125 if (!SCTP_CHUNK_ISACKED(mp)) { 126 sstat->sstat_unackdata++; 127 } 128 } 129 } 130 131 /* 132 * Count penddata chunks. We can only count chunks in SCTP (not 133 * data already delivered to socket layer). 134 */ 135 if (sctp->sctp_instr != NULL) { 136 for (i = 0; i < sctp->sctp_num_istr; i++) { 137 for (meta = sctp->sctp_instr[i].istr_reass; 138 meta != NULL; meta = meta->b_next) { 139 for (mp = meta->b_cont; mp; mp = mp->b_cont) { 140 if (DB_TYPE(mp) != M_CTL) { 141 sstat->sstat_penddata++; 142 } 143 } 144 } 145 } 146 } 147 /* Un-Ordered Frag list */ 148 for (meta = sctp->sctp_uo_frags; meta != NULL; meta = meta->b_next) 149 sstat->sstat_penddata++; 150 151 return (sizeof (*sstat)); 152 } 153 154 /* 155 * SCTP_GET_PEER_ADDR_INFO 156 */ 157 static int 158 sctp_get_paddrinfo(sctp_t *sctp, void *ptr, socklen_t *optlen) 159 { 160 struct sctp_paddrinfo *infop = ptr; 161 struct sockaddr_in *sin4; 162 struct sockaddr_in6 *sin6; 163 in6_addr_t faddr; 164 sctp_faddr_t *fp; 165 166 switch (infop->spinfo_address.ss_family) { 167 case AF_INET: 168 sin4 = (struct sockaddr_in *)&infop->spinfo_address; 169 IN6_INADDR_TO_V4MAPPED(&sin4->sin_addr, &faddr); 170 break; 171 case AF_INET6: 172 sin6 = (struct sockaddr_in6 *)&infop->spinfo_address; 173 faddr = sin6->sin6_addr; 174 break; 175 default: 176 return (EAFNOSUPPORT); 177 } 178 179 if ((fp = sctp_lookup_faddr(sctp, &faddr)) == NULL) 180 return (EINVAL); 181 182 infop->spinfo_state = (fp->sf_state == SCTP_FADDRS_ALIVE) ? 183 SCTP_ACTIVE : SCTP_INACTIVE; 184 infop->spinfo_cwnd = fp->sf_cwnd; 185 infop->spinfo_srtt = TICK_TO_MSEC(fp->sf_srtt); 186 infop->spinfo_rto = TICK_TO_MSEC(fp->sf_rto); 187 infop->spinfo_mtu = fp->sf_pmss; 188 189 *optlen = sizeof (struct sctp_paddrinfo); 190 return (0); 191 } 192 193 /* 194 * SCTP_RTOINFO 195 */ 196 static int 197 sctp_get_rtoinfo(sctp_t *sctp, void *ptr) 198 { 199 struct sctp_rtoinfo *srto = ptr; 200 201 srto->srto_initial = TICK_TO_MSEC(sctp->sctp_rto_initial); 202 srto->srto_max = TICK_TO_MSEC(sctp->sctp_rto_max); 203 srto->srto_min = TICK_TO_MSEC(sctp->sctp_rto_min); 204 205 return (sizeof (*srto)); 206 } 207 208 static int 209 sctp_set_rtoinfo(sctp_t *sctp, const void *invalp) 210 { 211 const struct sctp_rtoinfo *srto; 212 boolean_t ispriv; 213 sctp_stack_t *sctps = sctp->sctp_sctps; 214 conn_t *connp = sctp->sctp_connp; 215 uint32_t new_min, new_max; 216 217 srto = invalp; 218 219 ispriv = secpolicy_ip_config(connp->conn_cred, B_TRUE) == 0; 220 221 /* 222 * Bounds checking. Priviledged user can set the RTO initial 223 * outside the ndd boundary. 224 */ 225 if (srto->srto_initial != 0 && 226 (!ispriv && (srto->srto_initial < sctps->sctps_rto_initialg_low || 227 srto->srto_initial > sctps->sctps_rto_initialg_high))) { 228 return (EINVAL); 229 } 230 if (srto->srto_max != 0 && 231 (!ispriv && (srto->srto_max < sctps->sctps_rto_maxg_low || 232 srto->srto_max > sctps->sctps_rto_maxg_high))) { 233 return (EINVAL); 234 } 235 if (srto->srto_min != 0 && 236 (!ispriv && (srto->srto_min < sctps->sctps_rto_ming_low || 237 srto->srto_min > sctps->sctps_rto_ming_high))) { 238 return (EINVAL); 239 } 240 241 new_min = (srto->srto_min != 0) ? srto->srto_min : sctp->sctp_rto_min; 242 new_max = (srto->srto_max != 0) ? srto->srto_max : sctp->sctp_rto_max; 243 if (new_max < new_min) { 244 return (EINVAL); 245 } 246 247 if (srto->srto_initial != 0) { 248 sctp->sctp_rto_initial = MSEC_TO_TICK(srto->srto_initial); 249 } 250 251 /* Ensure that sctp_rto_max will never be zero. */ 252 if (srto->srto_max != 0) { 253 sctp->sctp_rto_max = MAX(MSEC_TO_TICK(srto->srto_max), 1); 254 } 255 if (srto->srto_min != 0) { 256 sctp->sctp_rto_min = MSEC_TO_TICK(srto->srto_min); 257 } 258 259 return (0); 260 } 261 262 /* 263 * SCTP_ASSOCINFO 264 */ 265 static int 266 sctp_get_assocparams(sctp_t *sctp, void *ptr) 267 { 268 struct sctp_assocparams *sap = ptr; 269 sctp_faddr_t *fp; 270 uint16_t i; 271 272 sap->sasoc_asocmaxrxt = sctp->sctp_pa_max_rxt; 273 274 /* 275 * Count the number of peer addresses 276 */ 277 for (i = 0, fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) { 278 i++; 279 } 280 sap->sasoc_number_peer_destinations = i; 281 sap->sasoc_peer_rwnd = sctp->sctp_frwnd; 282 sap->sasoc_local_rwnd = sctp->sctp_rwnd; 283 sap->sasoc_cookie_life = TICK_TO_MSEC(sctp->sctp_cookie_lifetime); 284 285 return (sizeof (*sap)); 286 } 287 288 static int 289 sctp_set_assocparams(sctp_t *sctp, const void *invalp) 290 { 291 const struct sctp_assocparams *sap = invalp; 292 uint32_t sum = 0; 293 sctp_faddr_t *fp; 294 sctp_stack_t *sctps = sctp->sctp_sctps; 295 296 if (sap->sasoc_asocmaxrxt) { 297 if (sctp->sctp_faddrs) { 298 /* 299 * Bounds check: as per rfc2960, assoc max retr cannot 300 * exceed the sum of all individual path max retr's. 301 */ 302 for (fp = sctp->sctp_faddrs; fp; fp = fp->sf_next) { 303 sum += fp->sf_max_retr; 304 } 305 if (sap->sasoc_asocmaxrxt > sum) { 306 return (EINVAL); 307 } 308 } 309 if (sap->sasoc_asocmaxrxt < sctps->sctps_pa_max_retr_low || 310 sap->sasoc_asocmaxrxt > sctps->sctps_pa_max_retr_high) { 311 /* 312 * Out of bounds. 313 */ 314 return (EINVAL); 315 } 316 } 317 if (sap->sasoc_cookie_life != 0 && 318 (sap->sasoc_cookie_life < sctps->sctps_cookie_life_low || 319 sap->sasoc_cookie_life > sctps->sctps_cookie_life_high)) { 320 return (EINVAL); 321 } 322 323 if (sap->sasoc_asocmaxrxt > 0) { 324 sctp->sctp_pa_max_rxt = sap->sasoc_asocmaxrxt; 325 } 326 if (sap->sasoc_cookie_life > 0) { 327 sctp->sctp_cookie_lifetime = MSEC_TO_TICK( 328 sap->sasoc_cookie_life); 329 } 330 return (0); 331 } 332 333 /* 334 * SCTP_INITMSG 335 */ 336 static int 337 sctp_get_initmsg(sctp_t *sctp, void *ptr) 338 { 339 struct sctp_initmsg *si = ptr; 340 341 si->sinit_num_ostreams = sctp->sctp_num_ostr; 342 si->sinit_max_instreams = sctp->sctp_num_istr; 343 si->sinit_max_attempts = sctp->sctp_max_init_rxt; 344 si->sinit_max_init_timeo = TICK_TO_MSEC(sctp->sctp_rto_max_init); 345 346 return (sizeof (*si)); 347 } 348 349 static int 350 sctp_set_initmsg(sctp_t *sctp, const void *invalp, uint_t inlen) 351 { 352 const struct sctp_initmsg *si = invalp; 353 sctp_stack_t *sctps = sctp->sctp_sctps; 354 conn_t *connp = sctp->sctp_connp; 355 356 if (sctp->sctp_state > SCTPS_LISTEN) { 357 return (EINVAL); 358 } 359 if (inlen < sizeof (*si)) { 360 return (EINVAL); 361 } 362 if (si->sinit_num_ostreams != 0 && 363 (si->sinit_num_ostreams < sctps->sctps_initial_out_streams_low || 364 si->sinit_num_ostreams > 365 sctps->sctps_initial_out_streams_high)) { 366 /* 367 * Out of bounds. 368 */ 369 return (EINVAL); 370 } 371 if (si->sinit_max_instreams != 0 && 372 (si->sinit_max_instreams < sctps->sctps_max_in_streams_low || 373 si->sinit_max_instreams > sctps->sctps_max_in_streams_high)) { 374 return (EINVAL); 375 } 376 if (si->sinit_max_attempts != 0 && 377 (si->sinit_max_attempts < sctps->sctps_max_init_retr_low || 378 si->sinit_max_attempts > sctps->sctps_max_init_retr_high)) { 379 return (EINVAL); 380 } 381 if (si->sinit_max_init_timeo != 0 && 382 (secpolicy_ip_config(connp->conn_cred, B_TRUE) != 0 && 383 (si->sinit_max_init_timeo < sctps->sctps_rto_maxg_low || 384 si->sinit_max_init_timeo > sctps->sctps_rto_maxg_high))) { 385 return (EINVAL); 386 } 387 if (si->sinit_num_ostreams != 0) 388 sctp->sctp_num_ostr = si->sinit_num_ostreams; 389 390 if (si->sinit_max_instreams != 0) 391 sctp->sctp_num_istr = si->sinit_max_instreams; 392 393 if (si->sinit_max_attempts != 0) 394 sctp->sctp_max_init_rxt = si->sinit_max_attempts; 395 396 if (si->sinit_max_init_timeo != 0) { 397 sctp->sctp_rto_max_init = 398 MSEC_TO_TICK(si->sinit_max_init_timeo); 399 } 400 return (0); 401 } 402 403 /* 404 * SCTP_PEER_ADDR_PARAMS 405 */ 406 static int 407 sctp_find_peer_fp(sctp_t *sctp, const struct sockaddr_storage *ss, 408 sctp_faddr_t **fpp) 409 { 410 struct sockaddr_in *sin; 411 struct sockaddr_in6 *sin6; 412 in6_addr_t addr; 413 414 if (ss->ss_family == AF_INET) { 415 sin = (struct sockaddr_in *)ss; 416 IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &addr); 417 } else if (ss->ss_family == AF_INET6) { 418 sin6 = (struct sockaddr_in6 *)ss; 419 addr = sin6->sin6_addr; 420 } else if (ss->ss_family) { 421 return (EAFNOSUPPORT); 422 } 423 424 if (!ss->ss_family || 425 SCTP_IS_ADDR_UNSPEC(IN6_IS_ADDR_V4MAPPED(&addr), addr)) { 426 *fpp = NULL; 427 } else { 428 *fpp = sctp_lookup_faddr(sctp, &addr); 429 if (*fpp == NULL) { 430 return (EINVAL); 431 } 432 } 433 return (0); 434 } 435 436 static int 437 sctp_get_peer_addr_params(sctp_t *sctp, void *ptr) 438 { 439 struct sctp_paddrparams *spp = ptr; 440 sctp_faddr_t *fp; 441 int retval; 442 443 retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp); 444 if (retval) { 445 return (retval); 446 } 447 if (fp) { 448 spp->spp_hbinterval = TICK_TO_MSEC(fp->sf_hb_interval); 449 spp->spp_pathmaxrxt = fp->sf_max_retr; 450 } else { 451 spp->spp_hbinterval = TICK_TO_MSEC(sctp->sctp_hb_interval); 452 spp->spp_pathmaxrxt = sctp->sctp_pp_max_rxt; 453 } 454 return (sizeof (*spp)); 455 } 456 457 static int 458 sctp_set_peer_addr_params(sctp_t *sctp, const void *invalp) 459 { 460 const struct sctp_paddrparams *spp = invalp; 461 sctp_faddr_t *fp, *fp2; 462 int retval; 463 uint32_t sum = 0; 464 int64_t now; 465 sctp_stack_t *sctps = sctp->sctp_sctps; 466 467 retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp); 468 if (retval != 0) { 469 return (retval); 470 } 471 472 if (spp->spp_hbinterval && spp->spp_hbinterval != UINT32_MAX && 473 (spp->spp_hbinterval < sctps->sctps_heartbeat_interval_low || 474 spp->spp_hbinterval > sctps->sctps_heartbeat_interval_high)) { 475 return (EINVAL); 476 } 477 if (spp->spp_pathmaxrxt && 478 (spp->spp_pathmaxrxt < sctps->sctps_pp_max_retr_low || 479 spp->spp_pathmaxrxt > sctps->sctps_pp_max_retr_high)) { 480 return (EINVAL); 481 } 482 if (spp->spp_pathmaxrxt && sctp->sctp_faddrs) { 483 for (fp2 = sctp->sctp_faddrs; fp2; fp2 = fp2->sf_next) { 484 if (!fp || fp2 == fp) { 485 sum += spp->spp_pathmaxrxt; 486 } else { 487 sum += fp2->sf_max_retr; 488 } 489 } 490 if (sctp->sctp_pa_max_rxt > sum) { 491 return (EINVAL); 492 } 493 } 494 495 now = ddi_get_lbolt64(); 496 if (fp != NULL) { 497 if (spp->spp_hbinterval == UINT32_MAX) { 498 /* 499 * Send heartbeat immediatelly, don't modify the 500 * current setting. 501 */ 502 sctp_send_heartbeat(sctp, fp); 503 } else { 504 fp->sf_hb_interval = MSEC_TO_TICK(spp->spp_hbinterval); 505 fp->sf_hb_expiry = now + SET_HB_INTVL(fp); 506 /* 507 * Restart the heartbeat timer using the new intrvl. 508 * We need to call sctp_heartbeat_timer() to set 509 * the earliest heartbeat expiry time. 510 */ 511 sctp_heartbeat_timer(sctp); 512 } 513 if (spp->spp_pathmaxrxt) { 514 fp->sf_max_retr = spp->spp_pathmaxrxt; 515 } 516 } else { 517 for (fp2 = sctp->sctp_faddrs; fp2 != NULL; fp2 = fp2->sf_next) { 518 if (spp->spp_hbinterval == UINT32_MAX) { 519 /* 520 * Send heartbeat immediatelly, don't modify 521 * the current setting. 522 */ 523 sctp_send_heartbeat(sctp, fp2); 524 } else { 525 fp2->sf_hb_interval = MSEC_TO_TICK( 526 spp->spp_hbinterval); 527 fp2->sf_hb_expiry = now + SET_HB_INTVL(fp2); 528 } 529 if (spp->spp_pathmaxrxt) { 530 fp2->sf_max_retr = spp->spp_pathmaxrxt; 531 } 532 } 533 if (spp->spp_hbinterval != UINT32_MAX) { 534 sctp->sctp_hb_interval = MSEC_TO_TICK( 535 spp->spp_hbinterval); 536 /* Restart the heartbeat timer using the new intrvl. */ 537 sctp_timer(sctp, sctp->sctp_heartbeat_mp, 538 sctp->sctp_hb_interval); 539 } 540 if (spp->spp_pathmaxrxt) { 541 sctp->sctp_pp_max_rxt = spp->spp_pathmaxrxt; 542 } 543 } 544 return (0); 545 } 546 547 /* 548 * SCTP_DEFAULT_SEND_PARAM 549 */ 550 static int 551 sctp_get_def_send_params(sctp_t *sctp, void *ptr) 552 { 553 struct sctp_sndrcvinfo *sinfo = ptr; 554 555 sinfo->sinfo_stream = sctp->sctp_def_stream; 556 sinfo->sinfo_ssn = 0; 557 sinfo->sinfo_flags = sctp->sctp_def_flags; 558 sinfo->sinfo_ppid = sctp->sctp_def_ppid; 559 sinfo->sinfo_context = sctp->sctp_def_context; 560 sinfo->sinfo_timetolive = sctp->sctp_def_timetolive; 561 sinfo->sinfo_tsn = 0; 562 sinfo->sinfo_cumtsn = 0; 563 564 return (sizeof (*sinfo)); 565 } 566 567 static int 568 sctp_set_def_send_params(sctp_t *sctp, const void *invalp) 569 { 570 const struct sctp_sndrcvinfo *sinfo = invalp; 571 572 if (sinfo->sinfo_stream >= sctp->sctp_num_ostr) { 573 return (EINVAL); 574 } 575 576 sctp->sctp_def_stream = sinfo->sinfo_stream; 577 sctp->sctp_def_flags = sinfo->sinfo_flags; 578 sctp->sctp_def_ppid = sinfo->sinfo_ppid; 579 sctp->sctp_def_context = sinfo->sinfo_context; 580 sctp->sctp_def_timetolive = sinfo->sinfo_timetolive; 581 582 return (0); 583 } 584 585 static int 586 sctp_set_prim(sctp_t *sctp, const void *invalp) 587 { 588 const struct sctp_setpeerprim *pp = invalp; 589 int retval; 590 sctp_faddr_t *fp; 591 592 retval = sctp_find_peer_fp(sctp, &pp->sspp_addr, &fp); 593 if (retval) 594 return (retval); 595 596 if (fp == NULL) 597 return (EINVAL); 598 if (fp == sctp->sctp_primary) 599 return (0); 600 sctp->sctp_primary = fp; 601 602 /* Only switch current if fp is alive */ 603 if (fp->sf_state != SCTP_FADDRS_ALIVE || fp == sctp->sctp_current) { 604 return (0); 605 } 606 sctp_set_faddr_current(sctp, fp); 607 608 return (0); 609 } 610 611 /* 612 * Table of all known options handled on a SCTP protocol stack. 613 * 614 * Note: This table contains options processed by both SCTP and IP levels 615 * and is the superset of options that can be performed on a SCTP and IP 616 * stack. 617 */ 618 opdes_t sctp_opt_arr[] = { 619 620 { SO_LINGER, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, 621 sizeof (struct linger), 0 }, 622 623 { SO_DEBUG, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 624 { SO_KEEPALIVE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 625 { SO_DONTROUTE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 626 { SO_USELOOPBACK, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 627 }, 628 { SO_BROADCAST, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 629 { SO_REUSEADDR, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 630 { SO_OOBINLINE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 631 { SO_TYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 }, 632 { SO_SNDBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 633 { SO_RCVBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 634 { SO_DGRAM_ERRIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 635 }, 636 { SO_SND_COPYAVOID, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 637 { SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 638 0 }, 639 { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 640 0 }, 641 { SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int), 642 0 }, 643 { SO_EXCLBIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 644 645 { SO_DOMAIN, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 }, 646 647 { SO_PROTOTYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 }, 648 649 { SCTP_ADAPTATION_LAYER, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, 650 sizeof (struct sctp_setadaptation), 0 }, 651 { SCTP_ADD_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, OP_VARLEN, 652 sizeof (int), 0 }, 653 { SCTP_ASSOCINFO, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, 654 sizeof (struct sctp_assocparams), 0 }, 655 { SCTP_AUTOCLOSE, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 656 { SCTP_DEFAULT_SEND_PARAM, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, 657 sizeof (struct sctp_sndrcvinfo), 0 }, 658 { SCTP_DISABLE_FRAGMENTS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, 659 sizeof (int), 0 }, 660 { SCTP_EVENTS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, 661 sizeof (struct sctp_event_subscribe), 0 }, 662 { SCTP_GET_LADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, OP_VARLEN, 663 sizeof (int), 0 }, 664 { SCTP_GET_NLADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 }, 665 { SCTP_GET_NPADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 }, 666 { SCTP_GET_PADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, OP_VARLEN, 667 sizeof (int), 0 }, 668 { SCTP_GET_PEER_ADDR_INFO, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, 669 sizeof (struct sctp_paddrinfo), 0 }, 670 { SCTP_INITMSG, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, 671 sizeof (struct sctp_initmsg), 0 }, 672 { SCTP_I_WANT_MAPPED_V4_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, 673 sizeof (int), 0 }, 674 { SCTP_MAXSEG, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 675 { SCTP_NODELAY, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 676 { SCTP_PEER_ADDR_PARAMS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, 677 sizeof (struct sctp_paddrparams), 0 }, 678 { SCTP_PRIMARY_ADDR, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0, 679 sizeof (struct sctp_setpeerprim), 0 }, 680 { SCTP_PRSCTP, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 681 { SCTP_GET_ASSOC_STATS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, 682 sizeof (sctp_assoc_stats_t), 0 }, 683 { SCTP_REM_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, OP_VARLEN, 684 sizeof (int), 0 }, 685 { SCTP_RTOINFO, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, 686 sizeof (struct sctp_rtoinfo), 0 }, 687 { SCTP_SET_PEER_PRIMARY_ADDR, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0, 688 sizeof (struct sctp_setprim), 0 }, 689 { SCTP_STATUS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, 690 sizeof (struct sctp_status), 0 }, 691 { SCTP_UC_SWAP, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0, 692 sizeof (struct sctp_uc_swap), 0 }, 693 694 { IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 695 (OP_VARLEN|OP_NODEFAULT), 696 40, -1 /* not initialized */ }, 697 { T_IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 698 (OP_VARLEN|OP_NODEFAULT), 699 40, -1 /* not initialized */ }, 700 701 { IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 702 { T_IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 703 { IP_TTL, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_DEF_FN, 704 sizeof (int), -1 /* not initialized */ }, 705 706 { IP_SEC_OPT, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_NODEFAULT, 707 sizeof (ipsec_req_t), -1 /* not initialized */ }, 708 709 { IP_BOUND_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, 710 sizeof (int), 0 /* no ifindex */ }, 711 712 { IP_UNSPEC_SRC, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0, 713 sizeof (int), 0 }, 714 715 { IPV6_UNICAST_HOPS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_DEF_FN, 716 sizeof (int), -1 /* not initialized */ }, 717 718 { IPV6_BOUND_IF, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 719 sizeof (int), 0 /* no ifindex */ }, 720 721 { IP_DONTFRAG, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 722 723 { IP_NEXTHOP, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, 0, 724 sizeof (in_addr_t), -1 /* not initialized */ }, 725 726 { IP_MINTTL, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 }, 727 728 { IPV6_UNSPEC_SRC, IPPROTO_IPV6, OA_R, OA_RW, OP_RAW, 0, 729 sizeof (int), 0 }, 730 731 { IPV6_PKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 732 (OP_NODEFAULT|OP_VARLEN), 733 sizeof (struct in6_pktinfo), -1 /* not initialized */ }, 734 { IPV6_NEXTHOP, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 735 OP_NODEFAULT, 736 sizeof (sin6_t), -1 /* not initialized */ }, 737 { IPV6_HOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 738 (OP_VARLEN|OP_NODEFAULT), 255*8, 739 -1 /* not initialized */ }, 740 { IPV6_DSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 741 (OP_VARLEN|OP_NODEFAULT), 255*8, 742 -1 /* not initialized */ }, 743 { IPV6_RTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 744 (OP_VARLEN|OP_NODEFAULT), 255*8, 745 -1 /* not initialized */ }, 746 { IPV6_RTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 747 (OP_VARLEN|OP_NODEFAULT), 255*8, 748 -1 /* not initialized */ }, 749 { IPV6_TCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 750 OP_NODEFAULT, 751 sizeof (int), -1 /* not initialized */ }, 752 { IPV6_PATHMTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 753 OP_NODEFAULT, 754 sizeof (struct ip6_mtuinfo), -1 /* not initialized */ }, 755 { IPV6_DONTFRAG, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 756 sizeof (int), 0 }, 757 { IPV6_USE_MIN_MTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 758 sizeof (int), 0 }, 759 { IPV6_V6ONLY, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 760 sizeof (int), 0 }, 761 762 /* Enable receipt of ancillary data */ 763 { IPV6_RECVPKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 764 sizeof (int), 0 }, 765 { IPV6_RECVHOPLIMIT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 766 sizeof (int), 0 }, 767 { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 768 sizeof (int), 0 }, 769 { IPV6_RECVHOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 770 sizeof (int), 0 }, 771 { _OLD_IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 772 sizeof (int), 0 }, 773 { IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 774 sizeof (int), 0 }, 775 { IPV6_RECVRTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 776 sizeof (int), 0 }, 777 { IPV6_RECVRTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 778 sizeof (int), 0 }, 779 { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 780 sizeof (int), 0 }, 781 782 { IPV6_SEC_OPT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_NODEFAULT, 783 sizeof (ipsec_req_t), -1 /* not initialized */ }, 784 { IPV6_SRC_PREFERENCES, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 785 sizeof (uint32_t), IPV6_PREFER_SRC_DEFAULT }, 786 787 { IPV6_MINHOPCOUNT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, 788 sizeof (int), 0 }, 789 }; 790 791 uint_t sctp_opt_arr_size = A_CNT(sctp_opt_arr); 792 793 /* Handy on off switch for socket option processing. */ 794 #define ONOFF(x) ((x) == 0 ? 0 : 1) 795 796 /* 797 * SCTP routine to get the values of options. 798 */ 799 int 800 sctp_get_opt(sctp_t *sctp, int level, int name, void *ptr, socklen_t *optlen) 801 { 802 int *i1 = (int *)ptr; 803 int retval = 0; 804 int buflen = *optlen; 805 conn_t *connp = sctp->sctp_connp; 806 conn_opt_arg_t coas; 807 808 coas.coa_connp = connp; 809 coas.coa_ixa = connp->conn_ixa; 810 coas.coa_ipp = &connp->conn_xmit_ipp; 811 812 /* In most cases, the return buffer is just an int */ 813 *optlen = sizeof (int32_t); 814 815 RUN_SCTP(sctp); 816 817 if (connp->conn_state_flags & CONN_CLOSING) { 818 WAKE_SCTP(sctp); 819 return (EINVAL); 820 } 821 822 /* 823 * Check that the level and name are supported by SCTP, and that 824 * the length and credentials are ok. 825 */ 826 retval = proto_opt_check(level, name, buflen, NULL, sctp_opt_arr, 827 sctp_opt_arr_size, B_FALSE, B_TRUE, connp->conn_cred); 828 if (retval != 0) { 829 WAKE_SCTP(sctp); 830 if (retval < 0) { 831 retval = proto_tlitosyserr(-retval); 832 } 833 return (retval); 834 } 835 836 switch (level) { 837 case IPPROTO_SCTP: 838 switch (name) { 839 case SCTP_RTOINFO: 840 *optlen = sctp_get_rtoinfo(sctp, ptr); 841 break; 842 case SCTP_ASSOCINFO: 843 *optlen = sctp_get_assocparams(sctp, ptr); 844 break; 845 case SCTP_INITMSG: 846 *optlen = sctp_get_initmsg(sctp, ptr); 847 break; 848 case SCTP_NODELAY: 849 *i1 = sctp->sctp_ndelay; 850 break; 851 case SCTP_AUTOCLOSE: 852 *i1 = TICK_TO_SEC(sctp->sctp_autoclose); 853 break; 854 case SCTP_ADAPTATION_LAYER: 855 ((struct sctp_setadaptation *)ptr)->ssb_adaptation_ind = 856 sctp->sctp_tx_adaptation_code; 857 break; 858 case SCTP_PEER_ADDR_PARAMS: 859 *optlen = sctp_get_peer_addr_params(sctp, ptr); 860 break; 861 case SCTP_DEFAULT_SEND_PARAM: 862 *optlen = sctp_get_def_send_params(sctp, ptr); 863 break; 864 case SCTP_EVENTS: { 865 struct sctp_event_subscribe *ev; 866 867 ev = (struct sctp_event_subscribe *)ptr; 868 ev->sctp_data_io_event = 869 ONOFF(sctp->sctp_recvsndrcvinfo); 870 ev->sctp_association_event = 871 ONOFF(sctp->sctp_recvassocevnt); 872 ev->sctp_address_event = 873 ONOFF(sctp->sctp_recvpathevnt); 874 ev->sctp_send_failure_event = 875 ONOFF(sctp->sctp_recvsendfailevnt); 876 ev->sctp_peer_error_event = 877 ONOFF(sctp->sctp_recvpeererr); 878 ev->sctp_shutdown_event = 879 ONOFF(sctp->sctp_recvshutdownevnt); 880 ev->sctp_partial_delivery_event = 881 ONOFF(sctp->sctp_recvpdevnt); 882 ev->sctp_adaptation_layer_event = 883 ONOFF(sctp->sctp_recvalevnt); 884 *optlen = sizeof (struct sctp_event_subscribe); 885 break; 886 } 887 case SCTP_STATUS: 888 *optlen = sctp_get_status(sctp, ptr); 889 break; 890 case SCTP_GET_PEER_ADDR_INFO: 891 retval = sctp_get_paddrinfo(sctp, ptr, optlen); 892 break; 893 case SCTP_GET_NLADDRS: 894 *(int32_t *)ptr = sctp->sctp_nsaddrs; 895 break; 896 case SCTP_GET_LADDRS: { 897 int addr_cnt; 898 int addr_size; 899 900 if (connp->conn_family == AF_INET) 901 addr_size = sizeof (struct sockaddr_in); 902 else 903 addr_size = sizeof (struct sockaddr_in6); 904 addr_cnt = buflen / addr_size; 905 retval = sctp_getmyaddrs(sctp, ptr, &addr_cnt); 906 if (retval == 0) 907 *optlen = addr_cnt * addr_size; 908 break; 909 } 910 case SCTP_GET_NPADDRS: { 911 int i; 912 sctp_faddr_t *fp; 913 914 for (i = 0, fp = sctp->sctp_faddrs; fp != NULL; 915 i++, fp = fp->sf_next) 916 ; 917 *(int32_t *)ptr = i; 918 break; 919 } 920 case SCTP_GET_PADDRS: { 921 int addr_cnt; 922 int addr_size; 923 924 if (connp->conn_family == AF_INET) 925 addr_size = sizeof (struct sockaddr_in); 926 else 927 addr_size = sizeof (struct sockaddr_in6); 928 addr_cnt = buflen / addr_size; 929 retval = sctp_getpeeraddrs(sctp, ptr, &addr_cnt); 930 if (retval == 0) 931 *optlen = addr_cnt * addr_size; 932 break; 933 } 934 case SCTP_PRSCTP: 935 *i1 = sctp->sctp_prsctp_aware ? 1 : 0; 936 break; 937 938 case SCTP_GET_ASSOC_STATS: { 939 sctp_assoc_stats_t *sas; 940 941 sas = (sctp_assoc_stats_t *)ptr; 942 943 /* 944 * Copy the current stats to the stats struct. 945 * For stats which can be reset by snmp users 946 * add the cumulative and current stats for 947 * the raw totals to output to the user. 948 */ 949 sas->sas_gapcnt = sctp->sctp_gapcnt; 950 sas->sas_outseqtsns = sctp->sctp_outseqtsns; 951 sas->sas_osacks = sctp->sctp_osacks; 952 sas->sas_isacks = sctp->sctp_isacks; 953 sas->sas_idupchunks = sctp->sctp_idupchunks; 954 sas->sas_rtxchunks = sctp->sctp_rxtchunks + 955 sctp->sctp_cum_rxtchunks; 956 sas->sas_octrlchunks = sctp->sctp_obchunks + 957 sctp->sctp_cum_obchunks; 958 sas->sas_ictrlchunks = sctp->sctp_ibchunks + 959 sctp->sctp_cum_ibchunks; 960 sas->sas_oodchunks = sctp->sctp_odchunks + 961 sctp->sctp_cum_odchunks; 962 sas->sas_iodchunks = sctp->sctp_idchunks + 963 sctp->sctp_cum_idchunks; 964 sas->sas_ouodchunks = sctp->sctp_oudchunks + 965 sctp->sctp_cum_oudchunks; 966 sas->sas_iuodchunks = sctp->sctp_iudchunks + 967 sctp->sctp_cum_iudchunks; 968 969 /* 970 * Copy out the maximum observed RTO since the 971 * time this data was last requested 972 */ 973 if (sctp->sctp_maxrto == 0) { 974 /* unchanged during obervation period */ 975 sas->sas_maxrto = sctp->sctp_prev_maxrto; 976 } else { 977 /* record new period maximum */ 978 sas->sas_maxrto = sctp->sctp_maxrto; 979 } 980 /* Record the value sent to the user this period */ 981 sctp->sctp_prev_maxrto = sas->sas_maxrto; 982 983 /* Mark beginning of a new observation period */ 984 sctp->sctp_maxrto = 0; 985 986 *optlen = sizeof (sctp_assoc_stats_t); 987 break; 988 } 989 case SCTP_I_WANT_MAPPED_V4_ADDR: 990 case SCTP_MAXSEG: 991 case SCTP_DISABLE_FRAGMENTS: 992 default: 993 /* Not yet supported. */ 994 retval = ENOPROTOOPT; 995 break; 996 } 997 WAKE_SCTP(sctp); 998 return (retval); 999 case IPPROTO_IP: 1000 if (connp->conn_family != AF_INET) { 1001 retval = EINVAL; 1002 break; 1003 } 1004 switch (name) { 1005 case IP_OPTIONS: 1006 case T_IP_OPTIONS: { 1007 /* 1008 * This is compatible with BSD in that in only return 1009 * the reverse source route with the final destination 1010 * as the last entry. The first 4 bytes of the option 1011 * will contain the final destination. Allocate a 1012 * buffer large enough to hold all the options, we 1013 * add IP_ADDR_LEN to SCTP_MAX_IP_OPTIONS_LENGTH since 1014 * ip_opt_get_user() adds the final destination 1015 * at the start. 1016 */ 1017 int opt_len; 1018 uchar_t obuf[SCTP_MAX_IP_OPTIONS_LENGTH + IP_ADDR_LEN]; 1019 1020 opt_len = ip_opt_get_user(connp, obuf); 1021 ASSERT(opt_len <= sizeof (obuf)); 1022 1023 if (buflen < opt_len) { 1024 /* Silently truncate */ 1025 opt_len = buflen; 1026 } 1027 *optlen = opt_len; 1028 bcopy(obuf, ptr, opt_len); 1029 WAKE_SCTP(sctp); 1030 return (0); 1031 } 1032 default: 1033 break; 1034 } 1035 break; 1036 } 1037 mutex_enter(&connp->conn_lock); 1038 retval = conn_opt_get(&coas, level, name, ptr); 1039 mutex_exit(&connp->conn_lock); 1040 WAKE_SCTP(sctp); 1041 if (retval == -1) 1042 return (EINVAL); 1043 *optlen = retval; 1044 return (0); 1045 } 1046 1047 int 1048 sctp_set_opt(sctp_t *sctp, int level, int name, const void *invalp, 1049 socklen_t inlen) 1050 { 1051 return (sctp_set_opt_common(sctp, level, name, invalp, inlen, B_FALSE)); 1052 } 1053 1054 int 1055 sctp_set_opt_common(sctp_t *sctp, int level, int name, const void *invalp, 1056 socklen_t inlen, boolean_t kernel_special) 1057 { 1058 int *i1 = (int *)invalp; 1059 boolean_t onoff; 1060 int retval = 0, addrcnt; 1061 conn_t *connp = sctp->sctp_connp; 1062 sctp_stack_t *sctps = sctp->sctp_sctps; 1063 conn_opt_arg_t coas; 1064 1065 coas.coa_connp = connp; 1066 coas.coa_ixa = connp->conn_ixa; 1067 coas.coa_ipp = &connp->conn_xmit_ipp; 1068 coas.coa_ancillary = B_FALSE; 1069 coas.coa_changed = 0; 1070 1071 /* In all cases, the size of the option must be bigger than int */ 1072 if (inlen >= sizeof (int32_t)) { 1073 onoff = ONOFF(*i1); 1074 } else { 1075 return (EINVAL); 1076 } 1077 1078 retval = 0; 1079 1080 RUN_SCTP(sctp); 1081 1082 if (connp->conn_state_flags & CONN_CLOSING) { 1083 WAKE_SCTP(sctp); 1084 return (EINVAL); 1085 } 1086 1087 /* 1088 * Check that the level and name are supported by SCTP, and that 1089 * the length an credentials are ok. 1090 */ 1091 retval = proto_opt_check(level, name, inlen, NULL, sctp_opt_arr, 1092 sctp_opt_arr_size, B_TRUE, B_FALSE, connp->conn_cred); 1093 if (retval != 0) { 1094 if (retval < 0) { 1095 retval = proto_tlitosyserr(-retval); 1096 } 1097 goto done; 1098 } 1099 1100 /* Note: both SCTP and TCP interpret l_linger as being in seconds */ 1101 switch (level) { 1102 case SOL_SOCKET: 1103 switch (name) { 1104 case SO_SNDBUF: 1105 if (*i1 > sctps->sctps_max_buf) { 1106 retval = ENOBUFS; 1107 goto done; 1108 } 1109 if (*i1 < 0) { 1110 retval = EINVAL; 1111 goto done; 1112 } 1113 connp->conn_sndbuf = *i1; 1114 if (sctps->sctps_snd_lowat_fraction != 0) { 1115 connp->conn_sndlowat = connp->conn_sndbuf / 1116 sctps->sctps_snd_lowat_fraction; 1117 } 1118 goto done; 1119 case SO_RCVBUF: 1120 if (*i1 > sctps->sctps_max_buf) { 1121 retval = ENOBUFS; 1122 goto done; 1123 } 1124 /* Silently ignore zero */ 1125 if (*i1 != 0) { 1126 struct sock_proto_props sopp; 1127 1128 /* 1129 * Insist on a receive window that is at least 1130 * sctp_recv_hiwat_minmss * MSS (default 4*MSS) 1131 * to avoid funny interactions of Nagle 1132 * algorithm, SWS avoidance and delayed 1133 * acknowledgement. 1134 */ 1135 *i1 = MAX(*i1, 1136 sctps->sctps_recv_hiwat_minmss * 1137 sctp->sctp_mss); 1138 /* 1139 * Note that sctp_rwnd is modified by the 1140 * protocol and here we just whack it. 1141 */ 1142 connp->conn_rcvbuf = sctp->sctp_rwnd = *i1; 1143 sctp->sctp_arwnd = sctp->sctp_rwnd; 1144 sctp->sctp_pd_point = sctp->sctp_rwnd; 1145 1146 sopp.sopp_flags = SOCKOPT_RCVHIWAT; 1147 sopp.sopp_rxhiwat = connp->conn_rcvbuf; 1148 sctp->sctp_ulp_prop(sctp->sctp_ulpd, &sopp); 1149 1150 } 1151 /* 1152 * XXX should we return the rwnd here 1153 * and sctp_opt_get ? 1154 */ 1155 goto done; 1156 case SO_ALLZONES: 1157 if (sctp->sctp_state >= SCTPS_BOUND) { 1158 retval = EINVAL; 1159 goto done; 1160 } 1161 break; 1162 case SO_MAC_EXEMPT: 1163 if (sctp->sctp_state >= SCTPS_BOUND) { 1164 retval = EINVAL; 1165 goto done; 1166 } 1167 break; 1168 } 1169 break; 1170 1171 case IPPROTO_SCTP: 1172 switch (name) { 1173 case SCTP_RTOINFO: 1174 retval = sctp_set_rtoinfo(sctp, invalp); 1175 break; 1176 case SCTP_ASSOCINFO: 1177 retval = sctp_set_assocparams(sctp, invalp); 1178 break; 1179 case SCTP_INITMSG: 1180 retval = sctp_set_initmsg(sctp, invalp, inlen); 1181 break; 1182 case SCTP_NODELAY: 1183 sctp->sctp_ndelay = ONOFF(*i1); 1184 break; 1185 case SCTP_AUTOCLOSE: 1186 if (SEC_TO_TICK(*i1) < 0) { 1187 retval = EINVAL; 1188 break; 1189 } 1190 /* Convert the number of seconds to ticks. */ 1191 sctp->sctp_autoclose = SEC_TO_TICK(*i1); 1192 sctp_heartbeat_timer(sctp); 1193 break; 1194 case SCTP_SET_PEER_PRIMARY_ADDR: 1195 retval = sctp_set_peerprim(sctp, invalp); 1196 break; 1197 case SCTP_PRIMARY_ADDR: 1198 retval = sctp_set_prim(sctp, invalp); 1199 break; 1200 case SCTP_ADAPTATION_LAYER: { 1201 struct sctp_setadaptation *ssb; 1202 1203 ssb = (struct sctp_setadaptation *)invalp; 1204 sctp->sctp_send_adaptation = 1; 1205 sctp->sctp_tx_adaptation_code = ssb->ssb_adaptation_ind; 1206 break; 1207 } 1208 case SCTP_PEER_ADDR_PARAMS: 1209 retval = sctp_set_peer_addr_params(sctp, invalp); 1210 break; 1211 case SCTP_DEFAULT_SEND_PARAM: 1212 retval = sctp_set_def_send_params(sctp, invalp); 1213 break; 1214 case SCTP_EVENTS: { 1215 struct sctp_event_subscribe *ev; 1216 1217 ev = (struct sctp_event_subscribe *)invalp; 1218 sctp->sctp_recvsndrcvinfo = 1219 ONOFF(ev->sctp_data_io_event); 1220 sctp->sctp_recvassocevnt = 1221 ONOFF(ev->sctp_association_event); 1222 sctp->sctp_recvpathevnt = 1223 ONOFF(ev->sctp_address_event); 1224 sctp->sctp_recvsendfailevnt = 1225 ONOFF(ev->sctp_send_failure_event); 1226 sctp->sctp_recvpeererr = 1227 ONOFF(ev->sctp_peer_error_event); 1228 sctp->sctp_recvshutdownevnt = 1229 ONOFF(ev->sctp_shutdown_event); 1230 sctp->sctp_recvpdevnt = 1231 ONOFF(ev->sctp_partial_delivery_event); 1232 sctp->sctp_recvalevnt = 1233 ONOFF(ev->sctp_adaptation_layer_event); 1234 break; 1235 } 1236 case SCTP_ADD_ADDR: 1237 case SCTP_REM_ADDR: 1238 /* 1239 * The sctp_t has to be bound first before 1240 * the address list can be changed. 1241 */ 1242 if (sctp->sctp_state < SCTPS_BOUND) { 1243 retval = EINVAL; 1244 break; 1245 } 1246 if (connp->conn_family == AF_INET) { 1247 addrcnt = inlen / sizeof (struct sockaddr_in); 1248 } else { 1249 ASSERT(connp->conn_family == AF_INET6); 1250 addrcnt = inlen / sizeof (struct sockaddr_in6); 1251 } 1252 if (name == SCTP_ADD_ADDR) { 1253 retval = sctp_bind_add(sctp, invalp, addrcnt, 1254 B_TRUE, connp->conn_lport); 1255 } else { 1256 retval = sctp_bind_del(sctp, invalp, addrcnt, 1257 B_TRUE); 1258 } 1259 break; 1260 case SCTP_UC_SWAP: 1261 if (kernel_special) { 1262 struct sctp_uc_swap *us; 1263 1264 /* 1265 * Change handle & upcalls. 1266 */ 1267 us = (struct sctp_uc_swap *)invalp; 1268 sctp->sctp_ulpd = us->sus_handle; 1269 sctp->sctp_upcalls = us->sus_upcalls; 1270 } else { 1271 /* 1272 * We don't want ANYONE other than 1273 * our own kernel-ness mucking with this 1274 * socket option. Everyone else gets an error. 1275 */ 1276 retval = ENOPROTOOPT; 1277 } 1278 break; 1279 case SCTP_PRSCTP: 1280 sctp->sctp_prsctp_aware = onoff; 1281 break; 1282 case SCTP_I_WANT_MAPPED_V4_ADDR: 1283 case SCTP_MAXSEG: 1284 case SCTP_DISABLE_FRAGMENTS: 1285 /* Not yet supported. */ 1286 retval = ENOPROTOOPT; 1287 break; 1288 } 1289 goto done; 1290 1291 case IPPROTO_IP: 1292 if (connp->conn_family != AF_INET) { 1293 retval = EINVAL; 1294 goto done; 1295 } 1296 switch (name) { 1297 case IP_SEC_OPT: 1298 /* 1299 * We should not allow policy setting after 1300 * we start listening for connections. 1301 */ 1302 if (sctp->sctp_state >= SCTPS_LISTEN) { 1303 retval = EINVAL; 1304 goto done; 1305 } 1306 break; 1307 } 1308 break; 1309 case IPPROTO_IPV6: 1310 if (connp->conn_family != AF_INET6) { 1311 retval = EINVAL; 1312 goto done; 1313 } 1314 1315 switch (name) { 1316 case IPV6_RECVPKTINFO: 1317 /* Send it with the next msg */ 1318 sctp->sctp_recvifindex = 0; 1319 break; 1320 case IPV6_RECVTCLASS: 1321 /* Force it to be sent up with the next msg */ 1322 sctp->sctp_recvtclass = 0xffffffffU; 1323 break; 1324 case IPV6_RECVHOPLIMIT: 1325 /* Force it to be sent up with the next msg */ 1326 sctp->sctp_recvhops = 0xffffffffU; 1327 break; 1328 case IPV6_SEC_OPT: 1329 /* 1330 * We should not allow policy setting after 1331 * we start listening for connections. 1332 */ 1333 if (sctp->sctp_state >= SCTPS_LISTEN) { 1334 retval = EINVAL; 1335 goto done; 1336 } 1337 break; 1338 case IPV6_V6ONLY: 1339 /* 1340 * After the bound state, setting the v6only option 1341 * is too late. 1342 */ 1343 if (sctp->sctp_state >= SCTPS_BOUND) { 1344 retval = EINVAL; 1345 goto done; 1346 } 1347 break; 1348 } 1349 break; 1350 } 1351 1352 retval = conn_opt_set(&coas, level, name, inlen, (uchar_t *)invalp, 1353 B_FALSE, connp->conn_cred); 1354 if (retval != 0) 1355 goto done; 1356 1357 if (coas.coa_changed & COA_ROUTE_CHANGED) { 1358 sctp_faddr_t *fp; 1359 /* 1360 * We recache the information which might pick a different 1361 * source and redo IPsec as a result. 1362 */ 1363 for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) 1364 sctp_get_dest(sctp, fp); 1365 } 1366 if (coas.coa_changed & COA_HEADER_CHANGED) { 1367 retval = sctp_build_hdrs(sctp, KM_NOSLEEP); 1368 if (retval != 0) 1369 goto done; 1370 } 1371 if (coas.coa_changed & COA_WROFF_CHANGED) { 1372 connp->conn_wroff = connp->conn_ht_iphc_allocated + 1373 sctps->sctps_wroff_xtra; 1374 if (sctp->sctp_current != NULL) { 1375 /* 1376 * Could be setting options before setting up 1377 * connection. 1378 */ 1379 sctp_set_ulp_prop(sctp); 1380 } 1381 } 1382 done: 1383 WAKE_SCTP(sctp); 1384 return (retval); 1385 } 1386 1387 /* 1388 * SCTP exported kernel interface for geting the first source address of 1389 * a sctp_t. The parameter addr is assumed to have enough space to hold 1390 * one socket address. 1391 */ 1392 int 1393 sctp_getsockname(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1394 { 1395 int err = 0; 1396 int addrcnt = 1; 1397 sin_t *sin4; 1398 sin6_t *sin6; 1399 conn_t *connp = sctp->sctp_connp; 1400 1401 ASSERT(sctp != NULL); 1402 1403 RUN_SCTP(sctp); 1404 addr->sa_family = connp->conn_family; 1405 switch (connp->conn_family) { 1406 case AF_INET: 1407 sin4 = (sin_t *)addr; 1408 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1409 sctp->sctp_bound_to_all) { 1410 sin4->sin_addr.s_addr = INADDR_ANY; 1411 sin4->sin_port = connp->conn_lport; 1412 } else { 1413 err = sctp_getmyaddrs(sctp, sin4, &addrcnt); 1414 if (err != 0) { 1415 *addrlen = 0; 1416 break; 1417 } 1418 } 1419 *addrlen = sizeof (struct sockaddr_in); 1420 break; 1421 case AF_INET6: 1422 sin6 = (sin6_t *)addr; 1423 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1424 sctp->sctp_bound_to_all) { 1425 bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr)); 1426 sin6->sin6_port = connp->conn_lport; 1427 } else { 1428 err = sctp_getmyaddrs(sctp, sin6, &addrcnt); 1429 if (err != 0) { 1430 *addrlen = 0; 1431 break; 1432 } 1433 } 1434 *addrlen = sizeof (struct sockaddr_in6); 1435 /* Note that flowinfo is only returned for getpeername */ 1436 break; 1437 } 1438 WAKE_SCTP(sctp); 1439 return (err); 1440 } 1441 1442 /* 1443 * SCTP exported kernel interface for geting the primary peer address of 1444 * a sctp_t. The parameter addr is assumed to have enough space to hold 1445 * one socket address. 1446 */ 1447 int 1448 sctp_getpeername(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1449 { 1450 int err = 0; 1451 int addrcnt = 1; 1452 sin6_t *sin6; 1453 conn_t *connp = sctp->sctp_connp; 1454 1455 ASSERT(sctp != NULL); 1456 1457 RUN_SCTP(sctp); 1458 addr->sa_family = connp->conn_family; 1459 switch (connp->conn_family) { 1460 case AF_INET: 1461 err = sctp_getpeeraddrs(sctp, addr, &addrcnt); 1462 if (err != 0) { 1463 *addrlen = 0; 1464 break; 1465 } 1466 *addrlen = sizeof (struct sockaddr_in); 1467 break; 1468 case AF_INET6: 1469 sin6 = (sin6_t *)addr; 1470 err = sctp_getpeeraddrs(sctp, sin6, &addrcnt); 1471 if (err != 0) { 1472 *addrlen = 0; 1473 break; 1474 } 1475 *addrlen = sizeof (struct sockaddr_in6); 1476 break; 1477 } 1478 WAKE_SCTP(sctp); 1479 return (err); 1480 } 1481 1482 /* 1483 * Return a list of IP addresses of the peer endpoint of this sctp_t. 1484 * The parameter paddrs is supposed to be either (struct sockaddr_in *) or 1485 * (struct sockaddr_in6 *) depending on the address family of the sctp_t. 1486 */ 1487 int 1488 sctp_getpeeraddrs(sctp_t *sctp, void *paddrs, int *addrcnt) 1489 { 1490 int family; 1491 struct sockaddr_in *sin4; 1492 struct sockaddr_in6 *sin6; 1493 int max; 1494 int cnt; 1495 sctp_faddr_t *fp = sctp->sctp_faddrs; 1496 in6_addr_t addr; 1497 conn_t *connp = sctp->sctp_connp; 1498 1499 ASSERT(sctp != NULL); 1500 1501 if (sctp->sctp_faddrs == NULL) 1502 return (ENOTCONN); 1503 1504 family = connp->conn_family; 1505 max = *addrcnt; 1506 1507 /* If we want only one, give the primary */ 1508 if (max == 1) { 1509 addr = sctp->sctp_primary->sf_faddr; 1510 switch (family) { 1511 case AF_INET: 1512 sin4 = paddrs; 1513 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1514 sin4->sin_port = connp->conn_fport; 1515 sin4->sin_family = AF_INET; 1516 break; 1517 1518 case AF_INET6: 1519 sin6 = paddrs; 1520 sin6->sin6_addr = addr; 1521 sin6->sin6_port = connp->conn_fport; 1522 sin6->sin6_family = AF_INET6; 1523 sin6->sin6_flowinfo = connp->conn_flowinfo; 1524 if (IN6_IS_ADDR_LINKSCOPE(&addr) && 1525 (sctp->sctp_primary->sf_ixa->ixa_flags & 1526 IXAF_SCOPEID_SET)) { 1527 sin6->sin6_scope_id = 1528 sctp->sctp_primary->sf_ixa->ixa_scopeid; 1529 } else { 1530 sin6->sin6_scope_id = 0; 1531 } 1532 sin6->__sin6_src_id = 0; 1533 break; 1534 } 1535 return (0); 1536 } 1537 1538 for (cnt = 0; cnt < max && fp != NULL; cnt++, fp = fp->sf_next) { 1539 addr = fp->sf_faddr; 1540 switch (family) { 1541 case AF_INET: 1542 ASSERT(IN6_IS_ADDR_V4MAPPED(&addr)); 1543 sin4 = (struct sockaddr_in *)paddrs + cnt; 1544 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1545 sin4->sin_port = connp->conn_fport; 1546 sin4->sin_family = AF_INET; 1547 break; 1548 case AF_INET6: 1549 sin6 = (struct sockaddr_in6 *)paddrs + cnt; 1550 sin6->sin6_addr = addr; 1551 sin6->sin6_port = connp->conn_fport; 1552 sin6->sin6_family = AF_INET6; 1553 sin6->sin6_flowinfo = connp->conn_flowinfo; 1554 if (IN6_IS_ADDR_LINKSCOPE(&addr) && 1555 (fp->sf_ixa->ixa_flags & IXAF_SCOPEID_SET)) 1556 sin6->sin6_scope_id = fp->sf_ixa->ixa_scopeid; 1557 else 1558 sin6->sin6_scope_id = 0; 1559 sin6->__sin6_src_id = 0; 1560 break; 1561 } 1562 } 1563 *addrcnt = cnt; 1564 return (0); 1565 } 1566