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/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 /* 64 * Copy the standard header into its new location, 65 * lay in the new options and then update the relevant 66 * fields in both sctp_t and the standard header. 67 * Returns 0 on success, errno otherwise. 68 */ 69 static int 70 sctp_opt_set_header(sctp_t *sctp, const void *ptr, uint_t len) 71 { 72 uint8_t *ip_optp; 73 sctp_hdr_t *new_sctph; 74 75 if ((len > SCTP_MAX_IP_OPTIONS_LENGTH) || (len & 0x3)) 76 return (EINVAL); 77 78 if (len > IP_MAX_OPT_LENGTH - sctp->sctp_v4label_len) 79 return (EINVAL); 80 81 ip_optp = (uint8_t *)sctp->sctp_ipha + IP_SIMPLE_HDR_LENGTH; 82 83 if (sctp->sctp_v4label_len > 0) { 84 int padlen; 85 uint8_t opt; 86 87 /* convert list termination to no-ops as needed */ 88 padlen = sctp->sctp_v4label_len - ip_optp[IPOPT_OLEN]; 89 ip_optp += ip_optp[IPOPT_OLEN]; 90 opt = len > 0 ? IPOPT_NOP : IPOPT_EOL; 91 while (--padlen >= 0) 92 *ip_optp++ = opt; 93 ASSERT(ip_optp == (uint8_t *)sctp->sctp_ipha + 94 IP_SIMPLE_HDR_LENGTH + sctp->sctp_v4label_len); 95 } 96 97 /* 98 * Move the existing SCTP header out where it belongs. 99 */ 100 new_sctph = (sctp_hdr_t *)(ip_optp + len); 101 ovbcopy(sctp->sctp_sctph, new_sctph, sizeof (sctp_hdr_t)); 102 sctp->sctp_sctph = new_sctph; 103 104 /* 105 * Insert the new user-supplied IP options. 106 */ 107 if (len > 0) 108 bcopy(ptr, ip_optp, len); 109 110 len += sctp->sctp_v4label_len; 111 sctp->sctp_ip_hdr_len = len; 112 sctp->sctp_ipha->ipha_version_and_hdr_length = 113 (IP_VERSION << 4) | (len >> 2); 114 sctp->sctp_hdr_len = len + sizeof (sctp_hdr_t); 115 116 if (sctp->sctp_current) { 117 /* 118 * Could be setting options before setting up connection. 119 */ 120 sctp_set_ulp_prop(sctp); 121 } 122 return (0); 123 } 124 125 static int 126 sctp_get_status(sctp_t *sctp, void *ptr) 127 { 128 struct sctp_status *sstat = ptr; 129 sctp_faddr_t *fp; 130 struct sockaddr_in *sin; 131 struct sockaddr_in6 *sin6; 132 struct sctp_paddrinfo *sp; 133 mblk_t *meta, *mp; 134 int i; 135 136 sstat->sstat_state = sctp->sctp_state; 137 sstat->sstat_rwnd = sctp->sctp_frwnd; 138 139 sp = &sstat->sstat_primary; 140 if (!sctp->sctp_primary) { 141 bzero(sp, sizeof (*sp)); 142 goto noprim; 143 } 144 fp = sctp->sctp_primary; 145 146 if (fp->isv4) { 147 sin = (struct sockaddr_in *)&sp->spinfo_address; 148 sin->sin_family = AF_INET; 149 sin->sin_port = sctp->sctp_fport; 150 IN6_V4MAPPED_TO_INADDR(&fp->faddr, &sin->sin_addr); 151 sp->spinfo_mtu = sctp->sctp_hdr_len; 152 } else { 153 sin6 = (struct sockaddr_in6 *)&sp->spinfo_address; 154 sin6->sin6_family = AF_INET6; 155 sin6->sin6_port = sctp->sctp_fport; 156 sin6->sin6_addr = fp->faddr; 157 sp->spinfo_mtu = sctp->sctp_hdr6_len; 158 } 159 sp->spinfo_state = fp->state == SCTP_FADDRS_ALIVE ? SCTP_ACTIVE : 160 SCTP_INACTIVE; 161 sp->spinfo_cwnd = fp->cwnd; 162 sp->spinfo_srtt = fp->srtt; 163 sp->spinfo_rto = fp->rto; 164 sp->spinfo_mtu += fp->sfa_pmss; 165 166 noprim: 167 sstat->sstat_unackdata = 0; 168 sstat->sstat_penddata = 0; 169 sstat->sstat_instrms = sctp->sctp_num_istr; 170 sstat->sstat_outstrms = sctp->sctp_num_ostr; 171 sstat->sstat_fragmentation_point = sctp->sctp_mss - 172 sizeof (sctp_data_hdr_t); 173 174 /* count unack'd */ 175 for (meta = sctp->sctp_xmit_head; meta; meta = meta->b_next) { 176 for (mp = meta->b_cont; mp; mp = mp->b_next) { 177 if (!SCTP_CHUNK_ISSENT(mp)) { 178 break; 179 } 180 if (!SCTP_CHUNK_ISACKED(mp)) { 181 sstat->sstat_unackdata++; 182 } 183 } 184 } 185 186 /* 187 * Count penddata chunks. We can only count chunks in SCTP (not 188 * data already delivered to socket layer). 189 */ 190 if (sctp->sctp_instr != NULL) { 191 for (i = 0; i < sctp->sctp_num_istr; i++) { 192 for (meta = sctp->sctp_instr[i].istr_reass; 193 meta != NULL; meta = meta->b_next) { 194 for (mp = meta->b_cont; mp; mp = mp->b_cont) { 195 if (DB_TYPE(mp) != M_CTL) { 196 sstat->sstat_penddata++; 197 } 198 } 199 } 200 } 201 } 202 /* Un-Ordered Frag list */ 203 for (meta = sctp->sctp_uo_frags; meta != NULL; meta = meta->b_next) 204 sstat->sstat_penddata++; 205 206 return (sizeof (*sstat)); 207 } 208 209 /* 210 * SCTP_GET_PEER_ADDR_INFO 211 */ 212 static int 213 sctp_get_paddrinfo(sctp_t *sctp, void *ptr, socklen_t *optlen) 214 { 215 struct sctp_paddrinfo *infop = ptr; 216 struct sockaddr_in *sin4; 217 struct sockaddr_in6 *sin6; 218 in6_addr_t faddr; 219 sctp_faddr_t *fp; 220 221 switch (infop->spinfo_address.ss_family) { 222 case AF_INET: 223 sin4 = (struct sockaddr_in *)&infop->spinfo_address; 224 IN6_INADDR_TO_V4MAPPED(&sin4->sin_addr, &faddr); 225 break; 226 case AF_INET6: 227 sin6 = (struct sockaddr_in6 *)&infop->spinfo_address; 228 faddr = sin6->sin6_addr; 229 break; 230 default: 231 return (EAFNOSUPPORT); 232 } 233 234 if ((fp = sctp_lookup_faddr(sctp, &faddr)) == NULL) 235 return (EINVAL); 236 237 infop->spinfo_state = (fp->state == SCTP_FADDRS_ALIVE) ? SCTP_ACTIVE : 238 SCTP_INACTIVE; 239 infop->spinfo_cwnd = fp->cwnd; 240 infop->spinfo_srtt = TICK_TO_MSEC(fp->srtt); 241 infop->spinfo_rto = TICK_TO_MSEC(fp->rto); 242 infop->spinfo_mtu = fp->sfa_pmss; 243 244 *optlen = sizeof (struct sctp_paddrinfo); 245 return (0); 246 } 247 248 /* 249 * SCTP_RTOINFO 250 */ 251 static int 252 sctp_get_rtoinfo(sctp_t *sctp, void *ptr) 253 { 254 struct sctp_rtoinfo *srto = ptr; 255 256 srto->srto_initial = TICK_TO_MSEC(sctp->sctp_rto_initial); 257 srto->srto_max = TICK_TO_MSEC(sctp->sctp_rto_max); 258 srto->srto_min = TICK_TO_MSEC(sctp->sctp_rto_min); 259 260 return (sizeof (*srto)); 261 } 262 263 static int 264 sctp_set_rtoinfo(sctp_t *sctp, const void *invalp, uint_t inlen) 265 { 266 const struct sctp_rtoinfo *srto; 267 boolean_t ispriv; 268 sctp_stack_t *sctps = sctp->sctp_sctps; 269 270 if (inlen < sizeof (*srto)) { 271 return (EINVAL); 272 } 273 srto = invalp; 274 275 ispriv = secpolicy_ip_config(sctp->sctp_credp, B_TRUE) == 0; 276 277 /* 278 * Bounds checking. Priviledged user can set the RTO initial 279 * outside the ndd boundary. 280 */ 281 if (srto->srto_initial != 0 && 282 (!ispriv && (srto->srto_initial < sctps->sctps_rto_initialg_low || 283 srto->srto_initial > sctps->sctps_rto_initialg_high))) { 284 return (EINVAL); 285 } 286 if (srto->srto_max != 0 && 287 (!ispriv && (srto->srto_max < sctps->sctps_rto_maxg_low || 288 srto->srto_max > sctps->sctps_rto_maxg_high))) { 289 return (EINVAL); 290 } 291 if (srto->srto_min != 0 && 292 (!ispriv && (srto->srto_min < sctps->sctps_rto_ming_low || 293 srto->srto_min > sctps->sctps_rto_ming_high))) { 294 return (EINVAL); 295 } 296 297 if (srto->srto_initial != 0) { 298 sctp->sctp_rto_initial = MSEC_TO_TICK(srto->srto_initial); 299 } 300 if (srto->srto_max != 0) { 301 sctp->sctp_rto_max = MSEC_TO_TICK(srto->srto_max); 302 } 303 if (srto->srto_min != 0) { 304 sctp->sctp_rto_min = MSEC_TO_TICK(srto->srto_min); 305 } 306 307 return (0); 308 } 309 310 /* 311 * SCTP_ASSOCINFO 312 */ 313 static int 314 sctp_get_assocparams(sctp_t *sctp, void *ptr) 315 { 316 struct sctp_assocparams *sap = ptr; 317 sctp_faddr_t *fp; 318 uint16_t i; 319 320 sap->sasoc_asocmaxrxt = sctp->sctp_pa_max_rxt; 321 322 /* 323 * Count the number of peer addresses 324 */ 325 for (i = 0, fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { 326 i++; 327 } 328 sap->sasoc_number_peer_destinations = i; 329 sap->sasoc_peer_rwnd = sctp->sctp_frwnd; 330 sap->sasoc_local_rwnd = sctp->sctp_rwnd; 331 sap->sasoc_cookie_life = TICK_TO_MSEC(sctp->sctp_cookie_lifetime); 332 333 return (sizeof (*sap)); 334 } 335 336 static int 337 sctp_set_assocparams(sctp_t *sctp, const void *invalp, uint_t inlen) 338 { 339 const struct sctp_assocparams *sap = invalp; 340 uint32_t sum = 0; 341 sctp_faddr_t *fp; 342 sctp_stack_t *sctps = sctp->sctp_sctps; 343 344 if (inlen < sizeof (*sap)) { 345 return (EINVAL); 346 } 347 348 if (sap->sasoc_asocmaxrxt) { 349 if (sctp->sctp_faddrs) { 350 /* 351 * Bounds check: as per rfc2960, assoc max retr cannot 352 * exceed the sum of all individual path max retr's. 353 */ 354 for (fp = sctp->sctp_faddrs; fp; fp = fp->next) { 355 sum += fp->max_retr; 356 } 357 if (sap->sasoc_asocmaxrxt > sum) { 358 return (EINVAL); 359 } 360 } 361 if (sap->sasoc_asocmaxrxt < sctps->sctps_pa_max_retr_low || 362 sap->sasoc_asocmaxrxt > sctps->sctps_pa_max_retr_high) { 363 /* 364 * Out of bounds. 365 */ 366 return (EINVAL); 367 } 368 } 369 if (sap->sasoc_cookie_life != 0 && 370 (sap->sasoc_cookie_life < sctps->sctps_cookie_life_low || 371 sap->sasoc_cookie_life > sctps->sctps_cookie_life_high)) { 372 return (EINVAL); 373 } 374 375 if (sap->sasoc_asocmaxrxt > 0) { 376 sctp->sctp_pa_max_rxt = sap->sasoc_asocmaxrxt; 377 } 378 if (sap->sasoc_cookie_life > 0) { 379 sctp->sctp_cookie_lifetime = MSEC_TO_TICK( 380 sap->sasoc_cookie_life); 381 } 382 return (0); 383 } 384 385 /* 386 * SCTP_INITMSG 387 */ 388 static int 389 sctp_get_initmsg(sctp_t *sctp, void *ptr) 390 { 391 struct sctp_initmsg *si = ptr; 392 393 si->sinit_num_ostreams = sctp->sctp_num_ostr; 394 si->sinit_max_instreams = sctp->sctp_num_istr; 395 si->sinit_max_attempts = sctp->sctp_max_init_rxt; 396 si->sinit_max_init_timeo = TICK_TO_MSEC(sctp->sctp_init_rto_max); 397 398 return (sizeof (*si)); 399 } 400 401 static int 402 sctp_set_initmsg(sctp_t *sctp, const void *invalp, uint_t inlen) 403 { 404 const struct sctp_initmsg *si = invalp; 405 sctp_stack_t *sctps = sctp->sctp_sctps; 406 407 if (sctp->sctp_state > SCTPS_LISTEN) { 408 return (EINVAL); 409 } 410 if (inlen < sizeof (*si)) { 411 return (EINVAL); 412 } 413 if (si->sinit_num_ostreams != 0 && 414 (si->sinit_num_ostreams < sctps->sctps_initial_out_streams_low || 415 si->sinit_num_ostreams > 416 sctps->sctps_initial_out_streams_high)) { 417 /* 418 * Out of bounds. 419 */ 420 return (EINVAL); 421 } 422 if (si->sinit_max_instreams != 0 && 423 (si->sinit_max_instreams < sctps->sctps_max_in_streams_low || 424 si->sinit_max_instreams > sctps->sctps_max_in_streams_high)) { 425 return (EINVAL); 426 } 427 if (si->sinit_max_attempts != 0 && 428 (si->sinit_max_attempts < sctps->sctps_max_init_retr_low || 429 si->sinit_max_attempts > sctps->sctps_max_init_retr_high)) { 430 return (EINVAL); 431 } 432 if (si->sinit_max_init_timeo != 0 && 433 (secpolicy_ip_config(sctp->sctp_credp, B_TRUE) != 0 && 434 (si->sinit_max_init_timeo < sctps->sctps_rto_maxg_low || 435 si->sinit_max_init_timeo > sctps->sctps_rto_maxg_high))) { 436 return (EINVAL); 437 } 438 if (si->sinit_num_ostreams != 0) 439 sctp->sctp_num_ostr = si->sinit_num_ostreams; 440 441 if (si->sinit_max_instreams != 0) 442 sctp->sctp_num_istr = si->sinit_max_instreams; 443 444 if (si->sinit_max_attempts != 0) 445 sctp->sctp_max_init_rxt = si->sinit_max_attempts; 446 447 if (si->sinit_max_init_timeo != 0) { 448 sctp->sctp_init_rto_max = 449 MSEC_TO_TICK(si->sinit_max_init_timeo); 450 } 451 return (0); 452 } 453 454 /* 455 * SCTP_PEER_ADDR_PARAMS 456 */ 457 static int 458 sctp_find_peer_fp(sctp_t *sctp, const struct sockaddr_storage *ss, 459 sctp_faddr_t **fpp) 460 { 461 struct sockaddr_in *sin; 462 struct sockaddr_in6 *sin6; 463 in6_addr_t addr; 464 465 if (ss->ss_family == AF_INET) { 466 sin = (struct sockaddr_in *)ss; 467 IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &addr); 468 } else if (ss->ss_family == AF_INET6) { 469 sin6 = (struct sockaddr_in6 *)ss; 470 addr = sin6->sin6_addr; 471 } else if (ss->ss_family) { 472 return (EAFNOSUPPORT); 473 } 474 475 if (!ss->ss_family || 476 SCTP_IS_ADDR_UNSPEC(IN6_IS_ADDR_V4MAPPED(&addr), addr)) { 477 *fpp = NULL; 478 } else { 479 *fpp = sctp_lookup_faddr(sctp, &addr); 480 if (*fpp == NULL) { 481 return (EINVAL); 482 } 483 } 484 return (0); 485 } 486 487 static int 488 sctp_get_peer_addr_params(sctp_t *sctp, void *ptr) 489 { 490 struct sctp_paddrparams *spp = ptr; 491 sctp_faddr_t *fp; 492 int retval; 493 494 retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp); 495 if (retval) { 496 return (retval); 497 } 498 if (fp) { 499 spp->spp_hbinterval = TICK_TO_MSEC(fp->hb_interval); 500 spp->spp_pathmaxrxt = fp->max_retr; 501 } else { 502 spp->spp_hbinterval = TICK_TO_MSEC(sctp->sctp_hb_interval); 503 spp->spp_pathmaxrxt = sctp->sctp_pp_max_rxt; 504 } 505 return (sizeof (*spp)); 506 } 507 508 static int 509 sctp_set_peer_addr_params(sctp_t *sctp, const void *invalp, uint_t inlen) 510 { 511 const struct sctp_paddrparams *spp = invalp; 512 sctp_faddr_t *fp, *fp2; 513 int retval; 514 uint32_t sum = 0; 515 int64_t now; 516 sctp_stack_t *sctps = sctp->sctp_sctps; 517 518 if (inlen < sizeof (*spp)) { 519 return (EINVAL); 520 } 521 522 retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp); 523 if (retval != 0) { 524 return (retval); 525 } 526 527 if (spp->spp_hbinterval && spp->spp_hbinterval != UINT32_MAX && 528 (spp->spp_hbinterval < sctps->sctps_heartbeat_interval_low || 529 spp->spp_hbinterval > sctps->sctps_heartbeat_interval_high)) { 530 return (EINVAL); 531 } 532 if (spp->spp_pathmaxrxt && 533 (spp->spp_pathmaxrxt < sctps->sctps_pp_max_retr_low || 534 spp->spp_pathmaxrxt > sctps->sctps_pp_max_retr_high)) { 535 return (EINVAL); 536 } 537 if (spp->spp_pathmaxrxt && sctp->sctp_faddrs) { 538 for (fp2 = sctp->sctp_faddrs; fp2; fp2 = fp2->next) { 539 if (!fp || fp2 == fp) { 540 sum += spp->spp_pathmaxrxt; 541 } else { 542 sum += fp2->max_retr; 543 } 544 } 545 if (sctp->sctp_pa_max_rxt > sum) { 546 return (EINVAL); 547 } 548 } 549 550 now = lbolt64; 551 if (fp != NULL) { 552 if (spp->spp_hbinterval == UINT32_MAX) { 553 /* 554 * Send heartbeat immediatelly, don't modify the 555 * current setting. 556 */ 557 sctp_send_heartbeat(sctp, fp); 558 } else { 559 fp->hb_interval = MSEC_TO_TICK(spp->spp_hbinterval); 560 fp->hb_expiry = now + SET_HB_INTVL(fp); 561 /* 562 * Restart the heartbeat timer using the new intrvl. 563 * We need to call sctp_heartbeat_timer() to set 564 * the earliest heartbeat expiry time. 565 */ 566 sctp_heartbeat_timer(sctp); 567 } 568 if (spp->spp_pathmaxrxt) { 569 fp->max_retr = spp->spp_pathmaxrxt; 570 } 571 } else { 572 for (fp2 = sctp->sctp_faddrs; fp2 != NULL; fp2 = fp2->next) { 573 if (spp->spp_hbinterval == UINT32_MAX) { 574 /* 575 * Send heartbeat immediatelly, don't modify 576 * the current setting. 577 */ 578 sctp_send_heartbeat(sctp, fp2); 579 } else { 580 fp2->hb_interval = MSEC_TO_TICK( 581 spp->spp_hbinterval); 582 fp2->hb_expiry = now + SET_HB_INTVL(fp2); 583 } 584 if (spp->spp_pathmaxrxt) { 585 fp2->max_retr = spp->spp_pathmaxrxt; 586 } 587 } 588 if (spp->spp_hbinterval != UINT32_MAX) { 589 sctp->sctp_hb_interval = MSEC_TO_TICK( 590 spp->spp_hbinterval); 591 /* Restart the heartbeat timer using the new intrvl. */ 592 sctp_timer(sctp, sctp->sctp_heartbeat_mp, 593 sctp->sctp_hb_interval); 594 } 595 if (spp->spp_pathmaxrxt) { 596 sctp->sctp_pp_max_rxt = spp->spp_pathmaxrxt; 597 } 598 } 599 return (0); 600 } 601 602 /* 603 * SCTP_DEFAULT_SEND_PARAM 604 */ 605 static int 606 sctp_get_def_send_params(sctp_t *sctp, void *ptr) 607 { 608 struct sctp_sndrcvinfo *sinfo = ptr; 609 610 sinfo->sinfo_stream = sctp->sctp_def_stream; 611 sinfo->sinfo_ssn = 0; 612 sinfo->sinfo_flags = sctp->sctp_def_flags; 613 sinfo->sinfo_ppid = sctp->sctp_def_ppid; 614 sinfo->sinfo_context = sctp->sctp_def_context; 615 sinfo->sinfo_timetolive = sctp->sctp_def_timetolive; 616 sinfo->sinfo_tsn = 0; 617 sinfo->sinfo_cumtsn = 0; 618 619 return (sizeof (*sinfo)); 620 } 621 622 static int 623 sctp_set_def_send_params(sctp_t *sctp, const void *invalp, uint_t inlen) 624 { 625 const struct sctp_sndrcvinfo *sinfo = invalp; 626 627 if (inlen < sizeof (*sinfo)) { 628 return (EINVAL); 629 } 630 if (sinfo->sinfo_stream >= sctp->sctp_num_ostr) { 631 return (EINVAL); 632 } 633 634 sctp->sctp_def_stream = sinfo->sinfo_stream; 635 sctp->sctp_def_flags = sinfo->sinfo_flags; 636 sctp->sctp_def_ppid = sinfo->sinfo_ppid; 637 sctp->sctp_def_context = sinfo->sinfo_context; 638 sctp->sctp_def_timetolive = sinfo->sinfo_timetolive; 639 640 return (0); 641 } 642 643 static int 644 sctp_set_prim(sctp_t *sctp, const void *invalp, uint_t inlen) 645 { 646 const struct sctp_setpeerprim *pp = invalp; 647 int retval; 648 sctp_faddr_t *fp; 649 650 if (inlen < sizeof (*pp)) { 651 return (EINVAL); 652 } 653 654 retval = sctp_find_peer_fp(sctp, &pp->sspp_addr, &fp); 655 if (retval) 656 return (retval); 657 658 if (fp == NULL) 659 return (EINVAL); 660 if (fp == sctp->sctp_primary) 661 return (0); 662 sctp->sctp_primary = fp; 663 664 /* Only switch current if fp is alive */ 665 if (fp->state != SCTP_FADDRS_ALIVE || fp == sctp->sctp_current) { 666 return (0); 667 } 668 sctp_set_faddr_current(sctp, fp); 669 670 return (0); 671 } 672 673 /* Handy on off switch for socket option processing. */ 674 #define ONOFF(x) ((x) == 0 ? 0 : 1) 675 676 /* 677 * SCTP routine to get the values of options. 678 */ 679 int 680 sctp_get_opt(sctp_t *sctp, int level, int name, void *ptr, socklen_t *optlen) 681 { 682 int *i1 = (int *)ptr; 683 int retval = 0; 684 int buflen = *optlen; 685 conn_t *connp = sctp->sctp_connp; 686 ip6_pkt_t *ipp = &sctp->sctp_sticky_ipp; 687 688 /* In most cases, the return buffer is just an int */ 689 *optlen = sizeof (int32_t); 690 691 RUN_SCTP(sctp); 692 693 if (connp->conn_state_flags & CONN_CLOSING) { 694 WAKE_SCTP(sctp); 695 return (EINVAL); 696 } 697 698 switch (level) { 699 case SOL_SOCKET: 700 switch (name) { 701 case SO_LINGER: { 702 struct linger *lgr = (struct linger *)ptr; 703 704 lgr->l_onoff = sctp->sctp_linger ? SO_LINGER : 0; 705 lgr->l_linger = TICK_TO_MSEC(sctp->sctp_lingertime); 706 *optlen = sizeof (struct linger); 707 break; 708 } 709 case SO_DEBUG: 710 *i1 = sctp->sctp_debug ? SO_DEBUG : 0; 711 break; 712 case SO_DONTROUTE: 713 *i1 = connp->conn_dontroute ? SO_DONTROUTE : 0; 714 break; 715 case SO_USELOOPBACK: 716 *i1 = connp->conn_loopback ? SO_USELOOPBACK : 0; 717 break; 718 case SO_BROADCAST: 719 *i1 = connp->conn_broadcast ? SO_BROADCAST : 0; 720 break; 721 case SO_REUSEADDR: 722 *i1 = connp->conn_reuseaddr ? SO_REUSEADDR : 0; 723 break; 724 case SO_DGRAM_ERRIND: 725 *i1 = sctp->sctp_dgram_errind ? SO_DGRAM_ERRIND : 0; 726 break; 727 case SO_SNDBUF: 728 *i1 = sctp->sctp_xmit_hiwater; 729 break; 730 case SO_RCVBUF: 731 *i1 = sctp->sctp_rwnd; 732 break; 733 case SO_ALLZONES: 734 *i1 = connp->conn_allzones; 735 break; 736 case SO_MAC_EXEMPT: 737 *i1 = connp->conn_mac_exempt; 738 break; 739 case SO_PROTOTYPE: 740 *i1 = IPPROTO_SCTP; 741 break; 742 case SO_DOMAIN: 743 *i1 = sctp->sctp_family; 744 break; 745 default: 746 retval = ENOPROTOOPT; 747 break; 748 } 749 break; 750 751 case IPPROTO_SCTP: 752 switch (name) { 753 case SCTP_RTOINFO: 754 if (buflen < sizeof (struct sctp_rtoinfo)) { 755 retval = EINVAL; 756 break; 757 } 758 *optlen = sctp_get_rtoinfo(sctp, ptr); 759 break; 760 case SCTP_ASSOCINFO: 761 if (buflen < sizeof (struct sctp_assocparams)) { 762 retval = EINVAL; 763 break; 764 } 765 *optlen = sctp_get_assocparams(sctp, ptr); 766 break; 767 case SCTP_INITMSG: 768 if (buflen < sizeof (struct sctp_initmsg)) { 769 retval = EINVAL; 770 break; 771 } 772 *optlen = sctp_get_initmsg(sctp, ptr); 773 break; 774 case SCTP_NODELAY: 775 *i1 = sctp->sctp_ndelay; 776 break; 777 case SCTP_AUTOCLOSE: 778 *i1 = TICK_TO_SEC(sctp->sctp_autoclose); 779 break; 780 case SCTP_ADAPTATION_LAYER: 781 if (buflen < sizeof (struct sctp_setadaptation)) { 782 retval = EINVAL; 783 break; 784 } 785 ((struct sctp_setadaptation *)ptr)->ssb_adaptation_ind = 786 sctp->sctp_tx_adaptation_code; 787 break; 788 case SCTP_PEER_ADDR_PARAMS: 789 if (buflen < sizeof (struct sctp_paddrparams)) { 790 retval = EINVAL; 791 break; 792 } 793 *optlen = sctp_get_peer_addr_params(sctp, ptr); 794 break; 795 case SCTP_DEFAULT_SEND_PARAM: 796 if (buflen < sizeof (struct sctp_sndrcvinfo)) { 797 retval = EINVAL; 798 break; 799 } 800 *optlen = sctp_get_def_send_params(sctp, ptr); 801 break; 802 case SCTP_EVENTS: { 803 struct sctp_event_subscribe *ev; 804 805 if (buflen < sizeof (struct sctp_event_subscribe)) { 806 retval = EINVAL; 807 break; 808 } 809 ev = (struct sctp_event_subscribe *)ptr; 810 ev->sctp_data_io_event = 811 ONOFF(sctp->sctp_recvsndrcvinfo); 812 ev->sctp_association_event = 813 ONOFF(sctp->sctp_recvassocevnt); 814 ev->sctp_address_event = 815 ONOFF(sctp->sctp_recvpathevnt); 816 ev->sctp_send_failure_event = 817 ONOFF(sctp->sctp_recvsendfailevnt); 818 ev->sctp_peer_error_event = 819 ONOFF(sctp->sctp_recvpeererr); 820 ev->sctp_shutdown_event = 821 ONOFF(sctp->sctp_recvshutdownevnt); 822 ev->sctp_partial_delivery_event = 823 ONOFF(sctp->sctp_recvpdevnt); 824 ev->sctp_adaptation_layer_event = 825 ONOFF(sctp->sctp_recvalevnt); 826 *optlen = sizeof (struct sctp_event_subscribe); 827 break; 828 } 829 case SCTP_STATUS: 830 if (buflen < sizeof (struct sctp_status)) { 831 retval = EINVAL; 832 break; 833 } 834 *optlen = sctp_get_status(sctp, ptr); 835 break; 836 case SCTP_GET_PEER_ADDR_INFO: 837 if (buflen < sizeof (struct sctp_paddrinfo)) { 838 retval = EINVAL; 839 break; 840 } 841 retval = sctp_get_paddrinfo(sctp, ptr, optlen); 842 break; 843 case SCTP_GET_NLADDRS: 844 *(int32_t *)ptr = sctp->sctp_nsaddrs; 845 break; 846 case SCTP_GET_LADDRS: { 847 int addr_cnt; 848 int addr_size; 849 850 if (sctp->sctp_family == AF_INET) 851 addr_size = sizeof (struct sockaddr_in); 852 else 853 addr_size = sizeof (struct sockaddr_in6); 854 addr_cnt = buflen / addr_size; 855 retval = sctp_getmyaddrs(sctp, ptr, &addr_cnt); 856 if (retval == 0) 857 *optlen = addr_cnt * addr_size; 858 break; 859 } 860 case SCTP_GET_NPADDRS: { 861 int i; 862 sctp_faddr_t *fp; 863 864 for (i = 0, fp = sctp->sctp_faddrs; fp != NULL; 865 i++, fp = fp->next) 866 ; 867 *(int32_t *)ptr = i; 868 break; 869 } 870 case SCTP_GET_PADDRS: { 871 int addr_cnt; 872 int addr_size; 873 874 if (sctp->sctp_family == AF_INET) 875 addr_size = sizeof (struct sockaddr_in); 876 else 877 addr_size = sizeof (struct sockaddr_in6); 878 addr_cnt = buflen / addr_size; 879 retval = sctp_getpeeraddrs(sctp, ptr, &addr_cnt); 880 if (retval == 0) 881 *optlen = addr_cnt * addr_size; 882 break; 883 } 884 case SCTP_PRSCTP: 885 *i1 = sctp->sctp_prsctp_aware ? 1 : 0; 886 break; 887 case SCTP_I_WANT_MAPPED_V4_ADDR: 888 case SCTP_MAXSEG: 889 case SCTP_DISABLE_FRAGMENTS: 890 /* Not yet supported. */ 891 default: 892 retval = ENOPROTOOPT; 893 break; 894 } 895 break; 896 897 case IPPROTO_IP: 898 if (sctp->sctp_family != AF_INET) { 899 retval = EINVAL; 900 break; 901 } 902 switch (name) { 903 case IP_OPTIONS: 904 case T_IP_OPTIONS: { 905 /* 906 * This is compatible with BSD in that in only return 907 * the reverse source route with the final destination 908 * as the last entry. The first 4 bytes of the option 909 * will contain the final destination. Allocate a 910 * buffer large enough to hold all the options, we 911 * add IP_ADDR_LEN to SCTP_MAX_IP_OPTIONS_LENGTH since 912 * ip_opt_get_user() adds the final destination 913 * at the start. 914 */ 915 char *opt_ptr; 916 int opt_len; 917 uchar_t obuf[SCTP_MAX_IP_OPTIONS_LENGTH + IP_ADDR_LEN]; 918 919 opt_ptr = (char *)sctp->sctp_ipha + 920 IP_SIMPLE_HDR_LENGTH; 921 opt_len = (char *)sctp->sctp_sctph - opt_ptr; 922 /* Caller ensures enough space */ 923 if (opt_len > 0) { 924 /* 925 * TODO: Do we have to handle getsockopt on an 926 * initiator as well? 927 */ 928 opt_len = ip_opt_get_user(sctp->sctp_ipha, 929 obuf); 930 ASSERT(opt_len <= sizeof (obuf)); 931 } else { 932 opt_len = 0; 933 } 934 if (buflen < opt_len) { 935 /* Silently truncate */ 936 opt_len = buflen; 937 } 938 *optlen = opt_len; 939 bcopy(obuf, ptr, opt_len); 940 break; 941 } 942 case IP_TOS: 943 case T_IP_TOS: 944 *i1 = (int)sctp->sctp_ipha->ipha_type_of_service; 945 break; 946 case IP_TTL: 947 *i1 = (int)sctp->sctp_ipha->ipha_ttl; 948 break; 949 case IP_NEXTHOP: 950 if (connp->conn_nexthop_set) { 951 *(ipaddr_t *)ptr = connp->conn_nexthop_v4; 952 *optlen = sizeof (ipaddr_t); 953 } else { 954 *optlen = 0; 955 } 956 break; 957 default: 958 retval = ENOPROTOOPT; 959 break; 960 } 961 break; 962 case IPPROTO_IPV6: 963 if (sctp->sctp_family != AF_INET6) { 964 retval = EINVAL; 965 break; 966 } 967 switch (name) { 968 case IPV6_UNICAST_HOPS: 969 *i1 = (unsigned int) sctp->sctp_ip6h->ip6_hops; 970 break; /* goto sizeof (int) option return */ 971 case IPV6_RECVPKTINFO: 972 if (sctp->sctp_ipv6_recvancillary & 973 SCTP_IPV6_RECVPKTINFO) { 974 *i1 = 1; 975 } else { 976 *i1 = 0; 977 } 978 break; /* goto sizeof (int) option return */ 979 case IPV6_RECVHOPLIMIT: 980 if (sctp->sctp_ipv6_recvancillary & 981 SCTP_IPV6_RECVHOPLIMIT) { 982 *i1 = 1; 983 } else { 984 *i1 = 0; 985 } 986 break; /* goto sizeof (int) option return */ 987 case IPV6_RECVHOPOPTS: 988 if (sctp->sctp_ipv6_recvancillary & 989 SCTP_IPV6_RECVHOPOPTS) { 990 *i1 = 1; 991 } else { 992 *i1 = 0; 993 } 994 break; /* goto sizeof (int) option return */ 995 case IPV6_RECVDSTOPTS: 996 if (sctp->sctp_ipv6_recvancillary & 997 SCTP_IPV6_RECVDSTOPTS) { 998 *i1 = 1; 999 } else { 1000 *i1 = 0; 1001 } 1002 break; /* goto sizeof (int) option return */ 1003 case IPV6_RECVRTHDR: 1004 if (sctp->sctp_ipv6_recvancillary & 1005 SCTP_IPV6_RECVRTHDR) { 1006 *i1 = 1; 1007 } else { 1008 *i1 = 0; 1009 } 1010 break; /* goto sizeof (int) option return */ 1011 case IPV6_RECVRTHDRDSTOPTS: 1012 if (sctp->sctp_ipv6_recvancillary & 1013 SCTP_IPV6_RECVRTDSTOPTS) { 1014 *i1 = 1; 1015 } else { 1016 *i1 = 0; 1017 } 1018 break; /* goto sizeof (int) option return */ 1019 case IPV6_PKTINFO: { 1020 struct in6_pktinfo *pkti; 1021 1022 if (buflen < sizeof (struct in6_pktinfo)) { 1023 retval = EINVAL; 1024 break; 1025 } 1026 pkti = (struct in6_pktinfo *)ptr; 1027 if (ipp->ipp_fields & IPPF_IFINDEX) 1028 pkti->ipi6_ifindex = ipp->ipp_ifindex; 1029 else 1030 pkti->ipi6_ifindex = 0; 1031 if (ipp->ipp_fields & IPPF_ADDR) 1032 pkti->ipi6_addr = ipp->ipp_addr; 1033 else 1034 pkti->ipi6_addr = ipv6_all_zeros; 1035 *optlen = sizeof (struct in6_pktinfo); 1036 break; 1037 } 1038 case IPV6_NEXTHOP: { 1039 sin6_t *sin6; 1040 1041 if (buflen < sizeof (sin6_t)) { 1042 retval = EINVAL; 1043 break; 1044 } 1045 sin6 = (sin6_t *)ptr; 1046 if (!(ipp->ipp_fields & IPPF_NEXTHOP)) 1047 break; 1048 *sin6 = sctp_sin6_null; 1049 sin6->sin6_family = AF_INET6; 1050 sin6->sin6_addr = ipp->ipp_nexthop; 1051 *optlen = sizeof (sin6_t); 1052 break; 1053 } 1054 case IPV6_HOPOPTS: { 1055 int len; 1056 1057 if (!(ipp->ipp_fields & IPPF_HOPOPTS)) 1058 break; 1059 len = ipp->ipp_hopoptslen - sctp->sctp_v6label_len; 1060 if (len <= 0) 1061 break; 1062 if (buflen < len) { 1063 retval = EINVAL; 1064 break; 1065 } 1066 bcopy((char *)ipp->ipp_hopopts + 1067 sctp->sctp_v6label_len, ptr, len); 1068 if (sctp->sctp_v6label_len > 0) { 1069 char *cptr = ptr; 1070 1071 /* 1072 * If the label length is greater than zero, 1073 * then we need to hide the label from user. 1074 * Make it look as though a normal Hop-By-Hop 1075 * Options Header is present here. 1076 */ 1077 cptr[0] = ((char *)ipp->ipp_hopopts)[0]; 1078 cptr[1] = (len + 7) / 8 - 1; 1079 } 1080 *optlen = len; 1081 break; 1082 } 1083 case IPV6_RTHDRDSTOPTS: 1084 if (!(ipp->ipp_fields & IPPF_RTDSTOPTS)) 1085 break; 1086 if (buflen < ipp->ipp_rtdstoptslen) { 1087 retval = EINVAL; 1088 break; 1089 } 1090 bcopy(ipp->ipp_rtdstopts, ptr, ipp->ipp_rtdstoptslen); 1091 *optlen = ipp->ipp_rtdstoptslen; 1092 break; 1093 case IPV6_RTHDR: 1094 if (!(ipp->ipp_fields & IPPF_RTHDR)) 1095 break; 1096 if (buflen < ipp->ipp_rthdrlen) { 1097 retval = EINVAL; 1098 break; 1099 } 1100 bcopy(ipp->ipp_rthdr, ptr, ipp->ipp_rthdrlen); 1101 *optlen = ipp->ipp_rthdrlen; 1102 break; 1103 case IPV6_DSTOPTS: 1104 if (!(ipp->ipp_fields & IPPF_DSTOPTS)) 1105 break; 1106 if (buflen < ipp->ipp_dstoptslen) { 1107 retval = EINVAL; 1108 break; 1109 } 1110 bcopy(ipp->ipp_dstopts, ptr, ipp->ipp_dstoptslen); 1111 *optlen = ipp->ipp_dstoptslen; 1112 break; 1113 case IPV6_V6ONLY: 1114 *i1 = sctp->sctp_connp->conn_ipv6_v6only; 1115 break; 1116 default: 1117 retval = ENOPROTOOPT; 1118 break; 1119 } 1120 break; 1121 1122 default: 1123 retval = ENOPROTOOPT; 1124 break; 1125 } 1126 WAKE_SCTP(sctp); 1127 return (retval); 1128 } 1129 1130 int 1131 sctp_set_opt(sctp_t *sctp, int level, int name, const void *invalp, 1132 socklen_t inlen) 1133 { 1134 ip6_pkt_t *ipp = &sctp->sctp_sticky_ipp; 1135 int *i1 = (int *)invalp; 1136 boolean_t onoff; 1137 int retval = 0, addrcnt; 1138 conn_t *connp = sctp->sctp_connp; 1139 sctp_stack_t *sctps = sctp->sctp_sctps; 1140 1141 /* In all cases, the size of the option must be bigger than int */ 1142 if (inlen >= sizeof (int32_t)) { 1143 onoff = ONOFF(*i1); 1144 } 1145 retval = 0; 1146 1147 RUN_SCTP(sctp); 1148 1149 if (connp->conn_state_flags & CONN_CLOSING) { 1150 WAKE_SCTP(sctp); 1151 return (EINVAL); 1152 } 1153 1154 switch (level) { 1155 case SOL_SOCKET: 1156 if (inlen < sizeof (int32_t)) { 1157 retval = EINVAL; 1158 break; 1159 } 1160 switch (name) { 1161 case SO_LINGER: { 1162 struct linger *lgr; 1163 1164 if (inlen != sizeof (struct linger)) { 1165 retval = EINVAL; 1166 break; 1167 } 1168 lgr = (struct linger *)invalp; 1169 if (lgr->l_onoff != 0) { 1170 sctp->sctp_linger = 1; 1171 sctp->sctp_lingertime = MSEC_TO_TICK( 1172 lgr->l_linger); 1173 } else { 1174 sctp->sctp_linger = 0; 1175 sctp->sctp_lingertime = 0; 1176 } 1177 break; 1178 } 1179 case SO_DEBUG: 1180 sctp->sctp_debug = onoff; 1181 break; 1182 case SO_KEEPALIVE: 1183 break; 1184 case SO_DONTROUTE: 1185 /* 1186 * SO_DONTROUTE, SO_USELOOPBACK and SO_BROADCAST are 1187 * only of interest to IP. 1188 */ 1189 connp->conn_dontroute = onoff; 1190 break; 1191 case SO_USELOOPBACK: 1192 connp->conn_loopback = onoff; 1193 break; 1194 case SO_BROADCAST: 1195 connp->conn_broadcast = onoff; 1196 break; 1197 case SO_REUSEADDR: 1198 connp->conn_reuseaddr = onoff; 1199 break; 1200 case SO_DGRAM_ERRIND: 1201 sctp->sctp_dgram_errind = onoff; 1202 break; 1203 case SO_SNDBUF: 1204 if (*i1 > sctps->sctps_max_buf) { 1205 retval = ENOBUFS; 1206 break; 1207 } 1208 if (*i1 < 0) { 1209 retval = EINVAL; 1210 break; 1211 } 1212 sctp->sctp_xmit_hiwater = *i1; 1213 if (sctps->sctps_snd_lowat_fraction != 0) 1214 sctp->sctp_xmit_lowater = 1215 sctp->sctp_xmit_hiwater / 1216 sctps->sctps_snd_lowat_fraction; 1217 break; 1218 case SO_RCVBUF: 1219 if (*i1 > sctps->sctps_max_buf) { 1220 retval = ENOBUFS; 1221 break; 1222 } 1223 /* Silently ignore zero */ 1224 if (*i1 != 0) { 1225 struct sock_proto_props sopp; 1226 1227 /* 1228 * Insist on a receive window that is at least 1229 * sctp_recv_hiwat_minmss * MSS (default 4*MSS) 1230 * to avoid funny interactions of Nagle 1231 * algorithm, SWS avoidance and delayed 1232 * acknowledgement. 1233 */ 1234 *i1 = MAX(*i1, 1235 sctps->sctps_recv_hiwat_minmss * 1236 sctp->sctp_mss); 1237 sctp->sctp_rwnd = *i1; 1238 sctp->sctp_irwnd = sctp->sctp_rwnd; 1239 sctp->sctp_pd_point = sctp->sctp_rwnd; 1240 1241 sopp.sopp_flags = SOCKOPT_RCVHIWAT; 1242 sopp.sopp_rxhiwat = *i1; 1243 sctp->sctp_ulp_prop(sctp->sctp_ulpd, &sopp); 1244 1245 } 1246 /* 1247 * XXX should we return the rwnd here 1248 * and sctp_opt_get ? 1249 */ 1250 break; 1251 case SO_ALLZONES: 1252 if (secpolicy_ip(sctp->sctp_credp, OP_CONFIG, 1253 B_TRUE)) { 1254 retval = EACCES; 1255 break; 1256 } 1257 if (sctp->sctp_state >= SCTPS_BOUND) { 1258 retval = EINVAL; 1259 break; 1260 } 1261 sctp->sctp_allzones = onoff; 1262 break; 1263 case SO_MAC_EXEMPT: 1264 if (secpolicy_net_mac_aware(sctp->sctp_credp) != 0) { 1265 retval = EACCES; 1266 break; 1267 } 1268 if (sctp->sctp_state >= SCTPS_BOUND) { 1269 retval = EINVAL; 1270 break; 1271 } 1272 connp->conn_mac_exempt = onoff; 1273 break; 1274 default: 1275 retval = ENOPROTOOPT; 1276 break; 1277 } 1278 break; 1279 1280 case IPPROTO_SCTP: 1281 if (inlen < sizeof (int32_t)) { 1282 retval = EINVAL; 1283 break; 1284 } 1285 switch (name) { 1286 case SCTP_RTOINFO: 1287 retval = sctp_set_rtoinfo(sctp, invalp, inlen); 1288 break; 1289 case SCTP_ASSOCINFO: 1290 retval = sctp_set_assocparams(sctp, invalp, inlen); 1291 break; 1292 case SCTP_INITMSG: 1293 retval = sctp_set_initmsg(sctp, invalp, inlen); 1294 break; 1295 case SCTP_NODELAY: 1296 sctp->sctp_ndelay = ONOFF(*i1); 1297 break; 1298 case SCTP_AUTOCLOSE: 1299 if (SEC_TO_TICK(*i1) < 0) { 1300 retval = EINVAL; 1301 break; 1302 } 1303 /* Convert the number of seconds to ticks. */ 1304 sctp->sctp_autoclose = SEC_TO_TICK(*i1); 1305 sctp_heartbeat_timer(sctp); 1306 break; 1307 case SCTP_SET_PEER_PRIMARY_ADDR: 1308 retval = sctp_set_peerprim(sctp, invalp, inlen); 1309 break; 1310 case SCTP_PRIMARY_ADDR: 1311 retval = sctp_set_prim(sctp, invalp, inlen); 1312 break; 1313 case SCTP_ADAPTATION_LAYER: { 1314 struct sctp_setadaptation *ssb; 1315 1316 if (inlen < sizeof (struct sctp_setadaptation)) { 1317 retval = EINVAL; 1318 break; 1319 } 1320 ssb = (struct sctp_setadaptation *)invalp; 1321 sctp->sctp_send_adaptation = 1; 1322 sctp->sctp_tx_adaptation_code = ssb->ssb_adaptation_ind; 1323 break; 1324 } 1325 case SCTP_PEER_ADDR_PARAMS: 1326 retval = sctp_set_peer_addr_params(sctp, invalp, 1327 inlen); 1328 break; 1329 case SCTP_DEFAULT_SEND_PARAM: 1330 retval = sctp_set_def_send_params(sctp, invalp, inlen); 1331 break; 1332 case SCTP_EVENTS: { 1333 struct sctp_event_subscribe *ev; 1334 1335 if (inlen < sizeof (struct sctp_event_subscribe)) { 1336 retval = EINVAL; 1337 break; 1338 } 1339 ev = (struct sctp_event_subscribe *)invalp; 1340 sctp->sctp_recvsndrcvinfo = 1341 ONOFF(ev->sctp_data_io_event); 1342 sctp->sctp_recvassocevnt = 1343 ONOFF(ev->sctp_association_event); 1344 sctp->sctp_recvpathevnt = 1345 ONOFF(ev->sctp_address_event); 1346 sctp->sctp_recvsendfailevnt = 1347 ONOFF(ev->sctp_send_failure_event); 1348 sctp->sctp_recvpeererr = 1349 ONOFF(ev->sctp_peer_error_event); 1350 sctp->sctp_recvshutdownevnt = 1351 ONOFF(ev->sctp_shutdown_event); 1352 sctp->sctp_recvpdevnt = 1353 ONOFF(ev->sctp_partial_delivery_event); 1354 sctp->sctp_recvalevnt = 1355 ONOFF(ev->sctp_adaptation_layer_event); 1356 break; 1357 } 1358 case SCTP_ADD_ADDR: 1359 case SCTP_REM_ADDR: 1360 /* 1361 * The sctp_t has to be bound first before 1362 * the address list can be changed. 1363 */ 1364 if (sctp->sctp_state < SCTPS_BOUND) { 1365 retval = EINVAL; 1366 break; 1367 } 1368 if (sctp->sctp_family == AF_INET) { 1369 addrcnt = inlen / sizeof (struct sockaddr_in); 1370 } else { 1371 ASSERT(sctp->sctp_family == AF_INET6); 1372 addrcnt = inlen / sizeof (struct sockaddr_in6); 1373 } 1374 if (name == SCTP_ADD_ADDR) { 1375 retval = sctp_bind_add(sctp, invalp, addrcnt, 1376 B_TRUE, sctp->sctp_lport); 1377 } else { 1378 retval = sctp_bind_del(sctp, invalp, addrcnt, 1379 B_TRUE); 1380 } 1381 break; 1382 case SCTP_UC_SWAP: { 1383 struct sctp_uc_swap *us; 1384 1385 /* 1386 * Change handle & upcalls. 1387 */ 1388 if (inlen < sizeof (*us)) { 1389 retval = EINVAL; 1390 break; 1391 } 1392 us = (struct sctp_uc_swap *)invalp; 1393 sctp->sctp_ulpd = us->sus_handle; 1394 sctp->sctp_upcalls = us->sus_upcalls; 1395 #if 0 1396 bcopy(us->sus_upcalls, &sctp->sctp_upcalls, 1397 sizeof (sctp_upcalls_t)); 1398 #endif 1399 break; 1400 } 1401 case SCTP_PRSCTP: 1402 sctp->sctp_prsctp_aware = onoff; 1403 break; 1404 case SCTP_I_WANT_MAPPED_V4_ADDR: 1405 case SCTP_MAXSEG: 1406 case SCTP_DISABLE_FRAGMENTS: 1407 /* Not yet supported. */ 1408 default: 1409 retval = ENOPROTOOPT; 1410 break; 1411 } 1412 break; 1413 1414 case IPPROTO_IP: 1415 if (sctp->sctp_family != AF_INET) { 1416 retval = ENOPROTOOPT; 1417 break; 1418 } 1419 if ((name != IP_OPTIONS) && (inlen < sizeof (int32_t))) { 1420 retval = EINVAL; 1421 break; 1422 } 1423 switch (name) { 1424 case IP_OPTIONS: 1425 case T_IP_OPTIONS: 1426 retval = sctp_opt_set_header(sctp, invalp, inlen); 1427 break; 1428 case IP_TOS: 1429 case T_IP_TOS: 1430 sctp->sctp_ipha->ipha_type_of_service = (uchar_t)*i1; 1431 break; 1432 case IP_TTL: 1433 sctp->sctp_ipha->ipha_ttl = (uchar_t)*i1; 1434 break; 1435 case IP_SEC_OPT: 1436 /* 1437 * We should not allow policy setting after 1438 * we start listening for connections. 1439 */ 1440 if (sctp->sctp_state >= SCTPS_LISTEN) { 1441 retval = EINVAL; 1442 } else { 1443 retval = ipsec_set_req(sctp->sctp_credp, 1444 sctp->sctp_connp, (ipsec_req_t *)invalp); 1445 } 1446 break; 1447 /* IP level options */ 1448 case IP_UNSPEC_SRC: 1449 connp->conn_unspec_src = onoff; 1450 break; 1451 case IP_NEXTHOP: { 1452 ipaddr_t addr = *i1; 1453 ipif_t *ipif = NULL; 1454 ill_t *ill; 1455 ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip; 1456 1457 if (secpolicy_ip(sctp->sctp_credp, OP_CONFIG, 1458 B_TRUE) == 0) { 1459 ipif = ipif_lookup_onlink_addr(addr, 1460 connp->conn_zoneid, ipst); 1461 if (ipif == NULL) { 1462 retval = EHOSTUNREACH; 1463 break; 1464 } 1465 ill = ipif->ipif_ill; 1466 mutex_enter(&ill->ill_lock); 1467 if ((ill->ill_state_flags & ILL_CONDEMNED) || 1468 (ipif->ipif_state_flags & IPIF_CONDEMNED)) { 1469 mutex_exit(&ill->ill_lock); 1470 ipif_refrele(ipif); 1471 retval = EHOSTUNREACH; 1472 break; 1473 } 1474 mutex_exit(&ill->ill_lock); 1475 ipif_refrele(ipif); 1476 mutex_enter(&connp->conn_lock); 1477 connp->conn_nexthop_v4 = addr; 1478 connp->conn_nexthop_set = B_TRUE; 1479 mutex_exit(&connp->conn_lock); 1480 } 1481 break; 1482 } 1483 default: 1484 retval = ENOPROTOOPT; 1485 break; 1486 } 1487 break; 1488 case IPPROTO_IPV6: { 1489 if (sctp->sctp_family != AF_INET6) { 1490 retval = ENOPROTOOPT; 1491 break; 1492 } 1493 1494 switch (name) { 1495 case IPV6_UNICAST_HOPS: 1496 if (inlen < sizeof (int32_t)) { 1497 retval = EINVAL; 1498 break; 1499 } 1500 if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) { 1501 retval = EINVAL; 1502 break; 1503 } 1504 if (*i1 == -1) { 1505 ipp->ipp_unicast_hops = 1506 sctps->sctps_ipv6_hoplimit; 1507 ipp->ipp_fields &= ~IPPF_UNICAST_HOPS; 1508 } else { 1509 ipp->ipp_unicast_hops = (uint8_t)*i1; 1510 ipp->ipp_fields |= IPPF_UNICAST_HOPS; 1511 } 1512 retval = sctp_build_hdrs(sctp); 1513 break; 1514 case IPV6_UNSPEC_SRC: 1515 if (inlen < sizeof (int32_t)) { 1516 retval = EINVAL; 1517 break; 1518 } 1519 connp->conn_unspec_src = onoff; 1520 break; 1521 case IPV6_RECVPKTINFO: 1522 if (inlen < sizeof (int32_t)) { 1523 retval = EINVAL; 1524 break; 1525 } 1526 if (onoff) 1527 sctp->sctp_ipv6_recvancillary |= 1528 SCTP_IPV6_RECVPKTINFO; 1529 else 1530 sctp->sctp_ipv6_recvancillary &= 1531 ~SCTP_IPV6_RECVPKTINFO; 1532 /* Send it with the next msg */ 1533 sctp->sctp_recvifindex = 0; 1534 connp->conn_ip_recvpktinfo = onoff; 1535 break; 1536 case IPV6_RECVHOPLIMIT: 1537 if (inlen < sizeof (int32_t)) { 1538 retval = EINVAL; 1539 break; 1540 } 1541 if (onoff) 1542 sctp->sctp_ipv6_recvancillary |= 1543 SCTP_IPV6_RECVHOPLIMIT; 1544 else 1545 sctp->sctp_ipv6_recvancillary &= 1546 ~SCTP_IPV6_RECVHOPLIMIT; 1547 sctp->sctp_recvhops = 0xffffffffU; 1548 connp->conn_ipv6_recvhoplimit = onoff; 1549 break; 1550 case IPV6_RECVHOPOPTS: 1551 if (inlen < sizeof (int32_t)) { 1552 retval = EINVAL; 1553 break; 1554 } 1555 if (onoff) 1556 sctp->sctp_ipv6_recvancillary |= 1557 SCTP_IPV6_RECVHOPOPTS; 1558 else 1559 sctp->sctp_ipv6_recvancillary &= 1560 ~SCTP_IPV6_RECVHOPOPTS; 1561 connp->conn_ipv6_recvhopopts = onoff; 1562 break; 1563 case IPV6_RECVDSTOPTS: 1564 if (inlen < sizeof (int32_t)) { 1565 retval = EINVAL; 1566 break; 1567 } 1568 if (onoff) 1569 sctp->sctp_ipv6_recvancillary |= 1570 SCTP_IPV6_RECVDSTOPTS; 1571 else 1572 sctp->sctp_ipv6_recvancillary &= 1573 ~SCTP_IPV6_RECVDSTOPTS; 1574 connp->conn_ipv6_recvdstopts = onoff; 1575 break; 1576 case IPV6_RECVRTHDR: 1577 if (inlen < sizeof (int32_t)) { 1578 retval = EINVAL; 1579 break; 1580 } 1581 if (onoff) 1582 sctp->sctp_ipv6_recvancillary |= 1583 SCTP_IPV6_RECVRTHDR; 1584 else 1585 sctp->sctp_ipv6_recvancillary &= 1586 ~SCTP_IPV6_RECVRTHDR; 1587 connp->conn_ipv6_recvrthdr = onoff; 1588 break; 1589 case IPV6_RECVRTHDRDSTOPTS: 1590 if (inlen < sizeof (int32_t)) { 1591 retval = EINVAL; 1592 break; 1593 } 1594 if (onoff) 1595 sctp->sctp_ipv6_recvancillary |= 1596 SCTP_IPV6_RECVRTDSTOPTS; 1597 else 1598 sctp->sctp_ipv6_recvancillary &= 1599 ~SCTP_IPV6_RECVRTDSTOPTS; 1600 connp->conn_ipv6_recvrtdstopts = onoff; 1601 break; 1602 case IPV6_PKTINFO: 1603 if (inlen != 0 && 1604 inlen != sizeof (struct in6_pktinfo)) { 1605 retval = EINVAL; 1606 break; 1607 } 1608 1609 if (inlen == 0) { 1610 ipp->ipp_fields &= ~(IPPF_IFINDEX |IPPF_ADDR); 1611 } else { 1612 struct in6_pktinfo *pkti; 1613 1614 pkti = (struct in6_pktinfo *)invalp; 1615 /* XXX Need to check if the index exists */ 1616 ipp->ipp_ifindex = pkti->ipi6_ifindex; 1617 ipp->ipp_addr = pkti->ipi6_addr; 1618 if (ipp->ipp_ifindex != 0) 1619 ipp->ipp_fields |= IPPF_IFINDEX; 1620 else 1621 ipp->ipp_fields &= ~IPPF_IFINDEX; 1622 if (!IN6_IS_ADDR_UNSPECIFIED(&ipp->ipp_addr)) 1623 ipp->ipp_fields |= IPPF_ADDR; 1624 else 1625 ipp->ipp_fields &= ~IPPF_ADDR; 1626 } 1627 retval = sctp_build_hdrs(sctp); 1628 break; 1629 case IPV6_NEXTHOP: { 1630 struct sockaddr_in6 *sin6; 1631 ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip; 1632 1633 if (inlen != 0 && inlen != sizeof (sin6_t)) { 1634 retval = EINVAL; 1635 break; 1636 } 1637 1638 if (inlen == 0) { 1639 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1640 } else { 1641 sin6 = (struct sockaddr_in6 *)invalp; 1642 if (sin6->sin6_family != AF_INET6) { 1643 retval = EAFNOSUPPORT; 1644 break; 1645 } 1646 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 1647 retval = EADDRNOTAVAIL; 1648 break; 1649 } 1650 ipp->ipp_nexthop = sin6->sin6_addr; 1651 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1652 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1653 } else { 1654 ire_t *ire; 1655 1656 ire = ire_route_lookup_v6( 1657 &sin6->sin6_addr, NULL, NULL, 0, 1658 NULL, NULL, ALL_ZONES, NULL, 1659 MATCH_IRE_DEFAULT, ipst); 1660 if (ire == NULL) { 1661 retval = EHOSTUNREACH; 1662 break; 1663 } 1664 ire_refrele(ire); 1665 ipp->ipp_fields |= IPPF_NEXTHOP; 1666 } 1667 } 1668 retval = sctp_build_hdrs(sctp); 1669 break; 1670 } 1671 case IPV6_HOPOPTS: { 1672 ip6_hbh_t *hopts = (ip6_hbh_t *)invalp; 1673 1674 if (inlen != 0 && 1675 inlen != (8 * (hopts->ip6h_len + 1))) { 1676 retval = EINVAL; 1677 break; 1678 } 1679 1680 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1681 B_TRUE, (uchar_t **)&ipp->ipp_hopopts, 1682 &ipp->ipp_hopoptslen, sctp->sctp_v6label_len); 1683 if (retval != 0) 1684 break; 1685 if (ipp->ipp_hopoptslen == 0) 1686 ipp->ipp_fields &= ~IPPF_HOPOPTS; 1687 else 1688 ipp->ipp_fields |= IPPF_HOPOPTS; 1689 retval = sctp_build_hdrs(sctp); 1690 break; 1691 } 1692 case IPV6_RTHDRDSTOPTS: { 1693 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1694 1695 if (inlen != 0 && 1696 inlen != (8 * (dopts->ip6d_len + 1))) { 1697 retval = EINVAL; 1698 break; 1699 } 1700 1701 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1702 B_TRUE, (uchar_t **)&ipp->ipp_rtdstopts, 1703 &ipp->ipp_rtdstoptslen, 0); 1704 if (retval != 0) 1705 break; 1706 if (ipp->ipp_rtdstoptslen == 0) 1707 ipp->ipp_fields &= ~IPPF_RTDSTOPTS; 1708 else 1709 ipp->ipp_fields |= IPPF_RTDSTOPTS; 1710 retval = sctp_build_hdrs(sctp); 1711 break; 1712 } 1713 case IPV6_DSTOPTS: { 1714 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1715 1716 if (inlen != 0 && 1717 inlen != (8 * (dopts->ip6d_len + 1))) { 1718 retval = EINVAL; 1719 break; 1720 } 1721 1722 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1723 B_TRUE, (uchar_t **)&ipp->ipp_dstopts, 1724 &ipp->ipp_dstoptslen, 0); 1725 if (retval != 0) 1726 break; 1727 if (ipp->ipp_dstoptslen == 0) 1728 ipp->ipp_fields &= ~IPPF_DSTOPTS; 1729 else 1730 ipp->ipp_fields |= IPPF_DSTOPTS; 1731 retval = sctp_build_hdrs(sctp); 1732 break; 1733 } 1734 case IPV6_RTHDR: { 1735 ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp; 1736 1737 if (inlen != 0 && 1738 inlen != (8 * (rt->ip6r_len + 1))) { 1739 retval = EINVAL; 1740 break; 1741 } 1742 1743 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1744 B_TRUE, (uchar_t **)&ipp->ipp_rthdr, 1745 &ipp->ipp_rthdrlen, 0); 1746 if (retval != 0) 1747 break; 1748 if (ipp->ipp_rthdrlen == 0) 1749 ipp->ipp_fields &= ~IPPF_RTHDR; 1750 else 1751 ipp->ipp_fields |= IPPF_RTHDR; 1752 retval = sctp_build_hdrs(sctp); 1753 break; 1754 } 1755 case IPV6_SEC_OPT: 1756 /* 1757 * We should not allow policy setting after 1758 * we start listening for connections. 1759 */ 1760 if (sctp->sctp_state >= SCTPS_LISTEN) { 1761 retval = EINVAL; 1762 } else { 1763 retval = ipsec_set_req(sctp->sctp_credp, 1764 sctp->sctp_connp, (ipsec_req_t *)invalp); 1765 } 1766 break; 1767 case IPV6_V6ONLY: 1768 /* 1769 * After the bound state, setting the v6only option 1770 * is too late. 1771 */ 1772 if (sctp->sctp_state >= SCTPS_BOUND) { 1773 retval = EINVAL; 1774 } else { 1775 sctp->sctp_connp->conn_ipv6_v6only = onoff; 1776 } 1777 break; 1778 default: 1779 retval = ENOPROTOOPT; 1780 break; 1781 } 1782 break; 1783 } 1784 default: 1785 retval = ENOPROTOOPT; 1786 break; 1787 } 1788 1789 WAKE_SCTP(sctp); 1790 return (retval); 1791 } 1792 1793 /* 1794 * SCTP exported kernel interface for geting the first source address of 1795 * a sctp_t. The parameter addr is assumed to have enough space to hold 1796 * one socket address. 1797 */ 1798 int 1799 sctp_getsockname(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1800 { 1801 int err = 0; 1802 int addrcnt = 1; 1803 sin_t *sin4; 1804 sin6_t *sin6; 1805 1806 ASSERT(sctp != NULL); 1807 1808 RUN_SCTP(sctp); 1809 addr->sa_family = sctp->sctp_family; 1810 switch (sctp->sctp_family) { 1811 case AF_INET: 1812 sin4 = (sin_t *)addr; 1813 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1814 sctp->sctp_bound_to_all) { 1815 sin4->sin_addr.s_addr = INADDR_ANY; 1816 sin4->sin_port = sctp->sctp_lport; 1817 } else { 1818 err = sctp_getmyaddrs(sctp, sin4, &addrcnt); 1819 if (err != 0) { 1820 *addrlen = 0; 1821 break; 1822 } 1823 } 1824 *addrlen = sizeof (struct sockaddr_in); 1825 break; 1826 case AF_INET6: 1827 sin6 = (sin6_t *)addr; 1828 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1829 sctp->sctp_bound_to_all) { 1830 bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr)); 1831 sin6->sin6_port = sctp->sctp_lport; 1832 } else { 1833 err = sctp_getmyaddrs(sctp, sin6, &addrcnt); 1834 if (err != 0) { 1835 *addrlen = 0; 1836 break; 1837 } 1838 } 1839 *addrlen = sizeof (struct sockaddr_in6); 1840 sin6->sin6_flowinfo = sctp->sctp_ip6h->ip6_vcf & 1841 ~IPV6_VERS_AND_FLOW_MASK; 1842 sin6->sin6_scope_id = 0; 1843 sin6->__sin6_src_id = 0; 1844 break; 1845 } 1846 WAKE_SCTP(sctp); 1847 return (err); 1848 } 1849 1850 /* 1851 * SCTP exported kernel interface for geting the primary peer address of 1852 * a sctp_t. The parameter addr is assumed to have enough space to hold 1853 * one socket address. 1854 */ 1855 int 1856 sctp_getpeername(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1857 { 1858 int err = 0; 1859 int addrcnt = 1; 1860 sin6_t *sin6; 1861 1862 ASSERT(sctp != NULL); 1863 1864 RUN_SCTP(sctp); 1865 addr->sa_family = sctp->sctp_family; 1866 switch (sctp->sctp_family) { 1867 case AF_INET: 1868 err = sctp_getpeeraddrs(sctp, addr, &addrcnt); 1869 if (err != 0) { 1870 *addrlen = 0; 1871 break; 1872 } 1873 *addrlen = sizeof (struct sockaddr_in); 1874 break; 1875 case AF_INET6: 1876 sin6 = (sin6_t *)addr; 1877 err = sctp_getpeeraddrs(sctp, sin6, &addrcnt); 1878 if (err != 0) { 1879 *addrlen = 0; 1880 break; 1881 } 1882 *addrlen = sizeof (struct sockaddr_in6); 1883 sin6->sin6_flowinfo = 0; 1884 sin6->sin6_scope_id = 0; 1885 sin6->__sin6_src_id = 0; 1886 break; 1887 } 1888 WAKE_SCTP(sctp); 1889 return (err); 1890 } 1891 1892 /* 1893 * Return a list of IP addresses of the peer endpoint of this sctp_t. 1894 * The parameter paddrs is supposed to be either (struct sockaddr_in *) or 1895 * (struct sockaddr_in6 *) depending on the address family of the sctp_t. 1896 */ 1897 int 1898 sctp_getpeeraddrs(sctp_t *sctp, void *paddrs, int *addrcnt) 1899 { 1900 int family; 1901 struct sockaddr_in *sin4; 1902 struct sockaddr_in6 *sin6; 1903 int max; 1904 int cnt; 1905 sctp_faddr_t *fp = sctp->sctp_faddrs; 1906 in6_addr_t addr; 1907 1908 ASSERT(sctp != NULL); 1909 1910 if (sctp->sctp_faddrs == NULL) 1911 return (ENOTCONN); 1912 1913 family = sctp->sctp_family; 1914 max = *addrcnt; 1915 1916 /* If we want only one, give the primary */ 1917 if (max == 1) { 1918 addr = sctp->sctp_primary->faddr; 1919 switch (family) { 1920 case AF_INET: 1921 sin4 = paddrs; 1922 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1923 sin4->sin_port = sctp->sctp_fport; 1924 sin4->sin_family = AF_INET; 1925 break; 1926 1927 case AF_INET6: 1928 sin6 = paddrs; 1929 sin6->sin6_addr = addr; 1930 sin6->sin6_port = sctp->sctp_fport; 1931 sin6->sin6_family = AF_INET6; 1932 break; 1933 } 1934 return (0); 1935 } 1936 1937 for (cnt = 0; cnt < max && fp != NULL; cnt++, fp = fp->next) { 1938 addr = fp->faddr; 1939 switch (family) { 1940 case AF_INET: 1941 ASSERT(IN6_IS_ADDR_V4MAPPED(&addr)); 1942 sin4 = (struct sockaddr_in *)paddrs + cnt; 1943 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1944 sin4->sin_port = sctp->sctp_fport; 1945 sin4->sin_family = AF_INET; 1946 break; 1947 case AF_INET6: 1948 sin6 = (struct sockaddr_in6 *)paddrs + cnt; 1949 sin6->sin6_addr = addr; 1950 sin6->sin6_port = sctp->sctp_fport; 1951 sin6->sin6_family = AF_INET6; 1952 break; 1953 } 1954 } 1955 *addrcnt = cnt; 1956 return (0); 1957 } 1958