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