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