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