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