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 break; 1396 } 1397 case SCTP_PRSCTP: 1398 sctp->sctp_prsctp_aware = onoff; 1399 break; 1400 case SCTP_I_WANT_MAPPED_V4_ADDR: 1401 case SCTP_MAXSEG: 1402 case SCTP_DISABLE_FRAGMENTS: 1403 /* Not yet supported. */ 1404 default: 1405 retval = ENOPROTOOPT; 1406 break; 1407 } 1408 break; 1409 1410 case IPPROTO_IP: 1411 if (sctp->sctp_family != AF_INET) { 1412 retval = ENOPROTOOPT; 1413 break; 1414 } 1415 if ((name != IP_OPTIONS) && (inlen < sizeof (int32_t))) { 1416 retval = EINVAL; 1417 break; 1418 } 1419 switch (name) { 1420 case IP_OPTIONS: 1421 case T_IP_OPTIONS: 1422 retval = sctp_opt_set_header(sctp, invalp, inlen); 1423 break; 1424 case IP_TOS: 1425 case T_IP_TOS: 1426 sctp->sctp_ipha->ipha_type_of_service = (uchar_t)*i1; 1427 break; 1428 case IP_TTL: 1429 sctp->sctp_ipha->ipha_ttl = (uchar_t)*i1; 1430 break; 1431 case IP_SEC_OPT: 1432 /* 1433 * We should not allow policy setting after 1434 * we start listening for connections. 1435 */ 1436 if (sctp->sctp_state >= SCTPS_LISTEN) { 1437 retval = EINVAL; 1438 } else { 1439 retval = ipsec_set_req(sctp->sctp_credp, 1440 sctp->sctp_connp, (ipsec_req_t *)invalp); 1441 } 1442 break; 1443 /* IP level options */ 1444 case IP_UNSPEC_SRC: 1445 connp->conn_unspec_src = onoff; 1446 break; 1447 case IP_NEXTHOP: { 1448 ipaddr_t addr = *i1; 1449 ipif_t *ipif = NULL; 1450 ill_t *ill; 1451 ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip; 1452 1453 if (secpolicy_ip(sctp->sctp_credp, OP_CONFIG, 1454 B_TRUE) == 0) { 1455 ipif = ipif_lookup_onlink_addr(addr, 1456 connp->conn_zoneid, ipst); 1457 if (ipif == NULL) { 1458 retval = EHOSTUNREACH; 1459 break; 1460 } 1461 ill = ipif->ipif_ill; 1462 mutex_enter(&ill->ill_lock); 1463 if ((ill->ill_state_flags & ILL_CONDEMNED) || 1464 (ipif->ipif_state_flags & IPIF_CONDEMNED)) { 1465 mutex_exit(&ill->ill_lock); 1466 ipif_refrele(ipif); 1467 retval = EHOSTUNREACH; 1468 break; 1469 } 1470 mutex_exit(&ill->ill_lock); 1471 ipif_refrele(ipif); 1472 mutex_enter(&connp->conn_lock); 1473 connp->conn_nexthop_v4 = addr; 1474 connp->conn_nexthop_set = B_TRUE; 1475 mutex_exit(&connp->conn_lock); 1476 } 1477 break; 1478 } 1479 default: 1480 retval = ENOPROTOOPT; 1481 break; 1482 } 1483 break; 1484 case IPPROTO_IPV6: { 1485 if (sctp->sctp_family != AF_INET6) { 1486 retval = ENOPROTOOPT; 1487 break; 1488 } 1489 1490 switch (name) { 1491 case IPV6_UNICAST_HOPS: 1492 if (inlen < sizeof (int32_t)) { 1493 retval = EINVAL; 1494 break; 1495 } 1496 if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) { 1497 retval = EINVAL; 1498 break; 1499 } 1500 if (*i1 == -1) { 1501 ipp->ipp_unicast_hops = 1502 sctps->sctps_ipv6_hoplimit; 1503 ipp->ipp_fields &= ~IPPF_UNICAST_HOPS; 1504 } else { 1505 ipp->ipp_unicast_hops = (uint8_t)*i1; 1506 ipp->ipp_fields |= IPPF_UNICAST_HOPS; 1507 } 1508 retval = sctp_build_hdrs(sctp); 1509 break; 1510 case IPV6_UNSPEC_SRC: 1511 if (inlen < sizeof (int32_t)) { 1512 retval = EINVAL; 1513 break; 1514 } 1515 connp->conn_unspec_src = onoff; 1516 break; 1517 case IPV6_RECVPKTINFO: 1518 if (inlen < sizeof (int32_t)) { 1519 retval = EINVAL; 1520 break; 1521 } 1522 if (onoff) 1523 sctp->sctp_ipv6_recvancillary |= 1524 SCTP_IPV6_RECVPKTINFO; 1525 else 1526 sctp->sctp_ipv6_recvancillary &= 1527 ~SCTP_IPV6_RECVPKTINFO; 1528 /* Send it with the next msg */ 1529 sctp->sctp_recvifindex = 0; 1530 connp->conn_ip_recvpktinfo = onoff; 1531 break; 1532 case IPV6_RECVHOPLIMIT: 1533 if (inlen < sizeof (int32_t)) { 1534 retval = EINVAL; 1535 break; 1536 } 1537 if (onoff) 1538 sctp->sctp_ipv6_recvancillary |= 1539 SCTP_IPV6_RECVHOPLIMIT; 1540 else 1541 sctp->sctp_ipv6_recvancillary &= 1542 ~SCTP_IPV6_RECVHOPLIMIT; 1543 sctp->sctp_recvhops = 0xffffffffU; 1544 connp->conn_ipv6_recvhoplimit = onoff; 1545 break; 1546 case IPV6_RECVHOPOPTS: 1547 if (inlen < sizeof (int32_t)) { 1548 retval = EINVAL; 1549 break; 1550 } 1551 if (onoff) 1552 sctp->sctp_ipv6_recvancillary |= 1553 SCTP_IPV6_RECVHOPOPTS; 1554 else 1555 sctp->sctp_ipv6_recvancillary &= 1556 ~SCTP_IPV6_RECVHOPOPTS; 1557 connp->conn_ipv6_recvhopopts = onoff; 1558 break; 1559 case IPV6_RECVDSTOPTS: 1560 if (inlen < sizeof (int32_t)) { 1561 retval = EINVAL; 1562 break; 1563 } 1564 if (onoff) 1565 sctp->sctp_ipv6_recvancillary |= 1566 SCTP_IPV6_RECVDSTOPTS; 1567 else 1568 sctp->sctp_ipv6_recvancillary &= 1569 ~SCTP_IPV6_RECVDSTOPTS; 1570 connp->conn_ipv6_recvdstopts = onoff; 1571 break; 1572 case IPV6_RECVRTHDR: 1573 if (inlen < sizeof (int32_t)) { 1574 retval = EINVAL; 1575 break; 1576 } 1577 if (onoff) 1578 sctp->sctp_ipv6_recvancillary |= 1579 SCTP_IPV6_RECVRTHDR; 1580 else 1581 sctp->sctp_ipv6_recvancillary &= 1582 ~SCTP_IPV6_RECVRTHDR; 1583 connp->conn_ipv6_recvrthdr = onoff; 1584 break; 1585 case IPV6_RECVRTHDRDSTOPTS: 1586 if (inlen < sizeof (int32_t)) { 1587 retval = EINVAL; 1588 break; 1589 } 1590 if (onoff) 1591 sctp->sctp_ipv6_recvancillary |= 1592 SCTP_IPV6_RECVRTDSTOPTS; 1593 else 1594 sctp->sctp_ipv6_recvancillary &= 1595 ~SCTP_IPV6_RECVRTDSTOPTS; 1596 connp->conn_ipv6_recvrtdstopts = onoff; 1597 break; 1598 case IPV6_PKTINFO: 1599 if (inlen != 0 && 1600 inlen != sizeof (struct in6_pktinfo)) { 1601 retval = EINVAL; 1602 break; 1603 } 1604 1605 if (inlen == 0) { 1606 ipp->ipp_fields &= ~(IPPF_IFINDEX |IPPF_ADDR); 1607 } else { 1608 struct in6_pktinfo *pkti; 1609 1610 pkti = (struct in6_pktinfo *)invalp; 1611 /* XXX Need to check if the index exists */ 1612 ipp->ipp_ifindex = pkti->ipi6_ifindex; 1613 ipp->ipp_addr = pkti->ipi6_addr; 1614 if (ipp->ipp_ifindex != 0) 1615 ipp->ipp_fields |= IPPF_IFINDEX; 1616 else 1617 ipp->ipp_fields &= ~IPPF_IFINDEX; 1618 if (!IN6_IS_ADDR_UNSPECIFIED(&ipp->ipp_addr)) 1619 ipp->ipp_fields |= IPPF_ADDR; 1620 else 1621 ipp->ipp_fields &= ~IPPF_ADDR; 1622 } 1623 retval = sctp_build_hdrs(sctp); 1624 break; 1625 case IPV6_NEXTHOP: { 1626 struct sockaddr_in6 *sin6; 1627 ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip; 1628 1629 if (inlen != 0 && inlen != sizeof (sin6_t)) { 1630 retval = EINVAL; 1631 break; 1632 } 1633 1634 if (inlen == 0) { 1635 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1636 } else { 1637 sin6 = (struct sockaddr_in6 *)invalp; 1638 if (sin6->sin6_family != AF_INET6) { 1639 retval = EAFNOSUPPORT; 1640 break; 1641 } 1642 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 1643 retval = EADDRNOTAVAIL; 1644 break; 1645 } 1646 ipp->ipp_nexthop = sin6->sin6_addr; 1647 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1648 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1649 } else { 1650 ire_t *ire; 1651 1652 ire = ire_route_lookup_v6( 1653 &sin6->sin6_addr, NULL, NULL, 0, 1654 NULL, NULL, ALL_ZONES, NULL, 1655 MATCH_IRE_DEFAULT, ipst); 1656 if (ire == NULL) { 1657 retval = EHOSTUNREACH; 1658 break; 1659 } 1660 ire_refrele(ire); 1661 ipp->ipp_fields |= IPPF_NEXTHOP; 1662 } 1663 } 1664 retval = sctp_build_hdrs(sctp); 1665 break; 1666 } 1667 case IPV6_HOPOPTS: { 1668 ip6_hbh_t *hopts = (ip6_hbh_t *)invalp; 1669 1670 if (inlen != 0 && 1671 inlen != (8 * (hopts->ip6h_len + 1))) { 1672 retval = EINVAL; 1673 break; 1674 } 1675 1676 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1677 B_TRUE, (uchar_t **)&ipp->ipp_hopopts, 1678 &ipp->ipp_hopoptslen, sctp->sctp_v6label_len); 1679 if (retval != 0) 1680 break; 1681 if (ipp->ipp_hopoptslen == 0) 1682 ipp->ipp_fields &= ~IPPF_HOPOPTS; 1683 else 1684 ipp->ipp_fields |= IPPF_HOPOPTS; 1685 retval = sctp_build_hdrs(sctp); 1686 break; 1687 } 1688 case IPV6_RTHDRDSTOPTS: { 1689 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1690 1691 if (inlen != 0 && 1692 inlen != (8 * (dopts->ip6d_len + 1))) { 1693 retval = EINVAL; 1694 break; 1695 } 1696 1697 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1698 B_TRUE, (uchar_t **)&ipp->ipp_rtdstopts, 1699 &ipp->ipp_rtdstoptslen, 0); 1700 if (retval != 0) 1701 break; 1702 if (ipp->ipp_rtdstoptslen == 0) 1703 ipp->ipp_fields &= ~IPPF_RTDSTOPTS; 1704 else 1705 ipp->ipp_fields |= IPPF_RTDSTOPTS; 1706 retval = sctp_build_hdrs(sctp); 1707 break; 1708 } 1709 case IPV6_DSTOPTS: { 1710 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1711 1712 if (inlen != 0 && 1713 inlen != (8 * (dopts->ip6d_len + 1))) { 1714 retval = EINVAL; 1715 break; 1716 } 1717 1718 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1719 B_TRUE, (uchar_t **)&ipp->ipp_dstopts, 1720 &ipp->ipp_dstoptslen, 0); 1721 if (retval != 0) 1722 break; 1723 if (ipp->ipp_dstoptslen == 0) 1724 ipp->ipp_fields &= ~IPPF_DSTOPTS; 1725 else 1726 ipp->ipp_fields |= IPPF_DSTOPTS; 1727 retval = sctp_build_hdrs(sctp); 1728 break; 1729 } 1730 case IPV6_RTHDR: { 1731 ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp; 1732 1733 if (inlen != 0 && 1734 inlen != (8 * (rt->ip6r_len + 1))) { 1735 retval = EINVAL; 1736 break; 1737 } 1738 1739 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1740 B_TRUE, (uchar_t **)&ipp->ipp_rthdr, 1741 &ipp->ipp_rthdrlen, 0); 1742 if (retval != 0) 1743 break; 1744 if (ipp->ipp_rthdrlen == 0) 1745 ipp->ipp_fields &= ~IPPF_RTHDR; 1746 else 1747 ipp->ipp_fields |= IPPF_RTHDR; 1748 retval = sctp_build_hdrs(sctp); 1749 break; 1750 } 1751 case IPV6_SEC_OPT: 1752 /* 1753 * We should not allow policy setting after 1754 * we start listening for connections. 1755 */ 1756 if (sctp->sctp_state >= SCTPS_LISTEN) { 1757 retval = EINVAL; 1758 } else { 1759 retval = ipsec_set_req(sctp->sctp_credp, 1760 sctp->sctp_connp, (ipsec_req_t *)invalp); 1761 } 1762 break; 1763 case IPV6_V6ONLY: 1764 /* 1765 * After the bound state, setting the v6only option 1766 * is too late. 1767 */ 1768 if (sctp->sctp_state >= SCTPS_BOUND) { 1769 retval = EINVAL; 1770 } else { 1771 sctp->sctp_connp->conn_ipv6_v6only = onoff; 1772 } 1773 break; 1774 default: 1775 retval = ENOPROTOOPT; 1776 break; 1777 } 1778 break; 1779 } 1780 default: 1781 retval = ENOPROTOOPT; 1782 break; 1783 } 1784 1785 WAKE_SCTP(sctp); 1786 return (retval); 1787 } 1788 1789 /* 1790 * SCTP exported kernel interface for geting the first source address of 1791 * a sctp_t. The parameter addr is assumed to have enough space to hold 1792 * one socket address. 1793 */ 1794 int 1795 sctp_getsockname(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1796 { 1797 int err = 0; 1798 int addrcnt = 1; 1799 sin_t *sin4; 1800 sin6_t *sin6; 1801 1802 ASSERT(sctp != NULL); 1803 1804 RUN_SCTP(sctp); 1805 addr->sa_family = sctp->sctp_family; 1806 switch (sctp->sctp_family) { 1807 case AF_INET: 1808 sin4 = (sin_t *)addr; 1809 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1810 sctp->sctp_bound_to_all) { 1811 sin4->sin_addr.s_addr = INADDR_ANY; 1812 sin4->sin_port = sctp->sctp_lport; 1813 } else { 1814 err = sctp_getmyaddrs(sctp, sin4, &addrcnt); 1815 if (err != 0) { 1816 *addrlen = 0; 1817 break; 1818 } 1819 } 1820 *addrlen = sizeof (struct sockaddr_in); 1821 break; 1822 case AF_INET6: 1823 sin6 = (sin6_t *)addr; 1824 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1825 sctp->sctp_bound_to_all) { 1826 bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr)); 1827 sin6->sin6_port = sctp->sctp_lport; 1828 } else { 1829 err = sctp_getmyaddrs(sctp, sin6, &addrcnt); 1830 if (err != 0) { 1831 *addrlen = 0; 1832 break; 1833 } 1834 } 1835 *addrlen = sizeof (struct sockaddr_in6); 1836 sin6->sin6_flowinfo = sctp->sctp_ip6h->ip6_vcf & 1837 ~IPV6_VERS_AND_FLOW_MASK; 1838 sin6->sin6_scope_id = 0; 1839 sin6->__sin6_src_id = 0; 1840 break; 1841 } 1842 WAKE_SCTP(sctp); 1843 return (err); 1844 } 1845 1846 /* 1847 * SCTP exported kernel interface for geting the primary peer address of 1848 * a sctp_t. The parameter addr is assumed to have enough space to hold 1849 * one socket address. 1850 */ 1851 int 1852 sctp_getpeername(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1853 { 1854 int err = 0; 1855 int addrcnt = 1; 1856 sin6_t *sin6; 1857 1858 ASSERT(sctp != NULL); 1859 1860 RUN_SCTP(sctp); 1861 addr->sa_family = sctp->sctp_family; 1862 switch (sctp->sctp_family) { 1863 case AF_INET: 1864 err = sctp_getpeeraddrs(sctp, addr, &addrcnt); 1865 if (err != 0) { 1866 *addrlen = 0; 1867 break; 1868 } 1869 *addrlen = sizeof (struct sockaddr_in); 1870 break; 1871 case AF_INET6: 1872 sin6 = (sin6_t *)addr; 1873 err = sctp_getpeeraddrs(sctp, sin6, &addrcnt); 1874 if (err != 0) { 1875 *addrlen = 0; 1876 break; 1877 } 1878 *addrlen = sizeof (struct sockaddr_in6); 1879 sin6->sin6_flowinfo = 0; 1880 sin6->sin6_scope_id = 0; 1881 sin6->__sin6_src_id = 0; 1882 break; 1883 } 1884 WAKE_SCTP(sctp); 1885 return (err); 1886 } 1887 1888 /* 1889 * Return a list of IP addresses of the peer endpoint of this sctp_t. 1890 * The parameter paddrs is supposed to be either (struct sockaddr_in *) or 1891 * (struct sockaddr_in6 *) depending on the address family of the sctp_t. 1892 */ 1893 int 1894 sctp_getpeeraddrs(sctp_t *sctp, void *paddrs, int *addrcnt) 1895 { 1896 int family; 1897 struct sockaddr_in *sin4; 1898 struct sockaddr_in6 *sin6; 1899 int max; 1900 int cnt; 1901 sctp_faddr_t *fp = sctp->sctp_faddrs; 1902 in6_addr_t addr; 1903 1904 ASSERT(sctp != NULL); 1905 1906 if (sctp->sctp_faddrs == NULL) 1907 return (ENOTCONN); 1908 1909 family = sctp->sctp_family; 1910 max = *addrcnt; 1911 1912 /* If we want only one, give the primary */ 1913 if (max == 1) { 1914 addr = sctp->sctp_primary->faddr; 1915 switch (family) { 1916 case AF_INET: 1917 sin4 = paddrs; 1918 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1919 sin4->sin_port = sctp->sctp_fport; 1920 sin4->sin_family = AF_INET; 1921 break; 1922 1923 case AF_INET6: 1924 sin6 = paddrs; 1925 sin6->sin6_addr = addr; 1926 sin6->sin6_port = sctp->sctp_fport; 1927 sin6->sin6_family = AF_INET6; 1928 break; 1929 } 1930 return (0); 1931 } 1932 1933 for (cnt = 0; cnt < max && fp != NULL; cnt++, fp = fp->next) { 1934 addr = fp->faddr; 1935 switch (family) { 1936 case AF_INET: 1937 ASSERT(IN6_IS_ADDR_V4MAPPED(&addr)); 1938 sin4 = (struct sockaddr_in *)paddrs + cnt; 1939 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1940 sin4->sin_port = sctp->sctp_fport; 1941 sin4->sin_family = AF_INET; 1942 break; 1943 case AF_INET6: 1944 sin6 = (struct sockaddr_in6 *)paddrs + cnt; 1945 sin6->sin6_addr = addr; 1946 sin6->sin6_port = sctp->sctp_fport; 1947 sin6->sin6_family = AF_INET6; 1948 break; 1949 } 1950 } 1951 *addrcnt = cnt; 1952 return (0); 1953 } 1954