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