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 2008 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 /* 1226 * Insist on a receive window that is at least 1227 * sctp_recv_hiwat_minmss * MSS (default 4*MSS) 1228 * to avoid funny interactions of Nagle 1229 * algorithm, SWS avoidance and delayed 1230 * acknowledgement. 1231 */ 1232 *i1 = MAX(*i1, 1233 sctps->sctps_recv_hiwat_minmss * 1234 sctp->sctp_mss); 1235 sctp->sctp_rwnd = *i1; 1236 sctp->sctp_irwnd = sctp->sctp_rwnd; 1237 sctp->sctp_pd_point = sctp->sctp_rwnd; 1238 } 1239 /* 1240 * XXX should we return the rwnd here 1241 * and sctp_opt_get ? 1242 */ 1243 break; 1244 case SO_ALLZONES: 1245 if (secpolicy_ip(sctp->sctp_credp, OP_CONFIG, 1246 B_TRUE)) { 1247 retval = EACCES; 1248 break; 1249 } 1250 if (sctp->sctp_state >= SCTPS_BOUND) { 1251 retval = EINVAL; 1252 break; 1253 } 1254 sctp->sctp_allzones = onoff; 1255 break; 1256 case SO_MAC_EXEMPT: 1257 if (secpolicy_net_mac_aware(sctp->sctp_credp) != 0) { 1258 retval = EACCES; 1259 break; 1260 } 1261 if (sctp->sctp_state >= SCTPS_BOUND) { 1262 retval = EINVAL; 1263 break; 1264 } 1265 connp->conn_mac_exempt = onoff; 1266 break; 1267 default: 1268 retval = ENOPROTOOPT; 1269 break; 1270 } 1271 break; 1272 1273 case IPPROTO_SCTP: 1274 if (inlen < sizeof (int32_t)) { 1275 retval = EINVAL; 1276 break; 1277 } 1278 switch (name) { 1279 case SCTP_RTOINFO: 1280 retval = sctp_set_rtoinfo(sctp, invalp, inlen); 1281 break; 1282 case SCTP_ASSOCINFO: 1283 retval = sctp_set_assocparams(sctp, invalp, inlen); 1284 break; 1285 case SCTP_INITMSG: 1286 retval = sctp_set_initmsg(sctp, invalp, inlen); 1287 break; 1288 case SCTP_NODELAY: 1289 sctp->sctp_ndelay = ONOFF(*i1); 1290 break; 1291 case SCTP_AUTOCLOSE: 1292 if (SEC_TO_TICK(*i1) < 0) { 1293 retval = EINVAL; 1294 break; 1295 } 1296 /* Convert the number of seconds to ticks. */ 1297 sctp->sctp_autoclose = SEC_TO_TICK(*i1); 1298 sctp_heartbeat_timer(sctp); 1299 break; 1300 case SCTP_SET_PEER_PRIMARY_ADDR: 1301 retval = sctp_set_peerprim(sctp, invalp, inlen); 1302 break; 1303 case SCTP_PRIMARY_ADDR: 1304 retval = sctp_set_prim(sctp, invalp, inlen); 1305 break; 1306 case SCTP_ADAPTATION_LAYER: { 1307 struct sctp_setadaptation *ssb; 1308 1309 if (inlen < sizeof (struct sctp_setadaptation)) { 1310 retval = EINVAL; 1311 break; 1312 } 1313 ssb = (struct sctp_setadaptation *)invalp; 1314 sctp->sctp_send_adaptation = 1; 1315 sctp->sctp_tx_adaptation_code = ssb->ssb_adaptation_ind; 1316 break; 1317 } 1318 case SCTP_PEER_ADDR_PARAMS: 1319 retval = sctp_set_peer_addr_params(sctp, invalp, 1320 inlen); 1321 break; 1322 case SCTP_DEFAULT_SEND_PARAM: 1323 retval = sctp_set_def_send_params(sctp, invalp, inlen); 1324 break; 1325 case SCTP_EVENTS: { 1326 struct sctp_event_subscribe *ev; 1327 1328 if (inlen < sizeof (struct sctp_event_subscribe)) { 1329 retval = EINVAL; 1330 break; 1331 } 1332 ev = (struct sctp_event_subscribe *)invalp; 1333 sctp->sctp_recvsndrcvinfo = 1334 ONOFF(ev->sctp_data_io_event); 1335 sctp->sctp_recvassocevnt = 1336 ONOFF(ev->sctp_association_event); 1337 sctp->sctp_recvpathevnt = 1338 ONOFF(ev->sctp_address_event); 1339 sctp->sctp_recvsendfailevnt = 1340 ONOFF(ev->sctp_send_failure_event); 1341 sctp->sctp_recvpeererr = 1342 ONOFF(ev->sctp_peer_error_event); 1343 sctp->sctp_recvshutdownevnt = 1344 ONOFF(ev->sctp_shutdown_event); 1345 sctp->sctp_recvpdevnt = 1346 ONOFF(ev->sctp_partial_delivery_event); 1347 sctp->sctp_recvalevnt = 1348 ONOFF(ev->sctp_adaptation_layer_event); 1349 break; 1350 } 1351 case SCTP_ADD_ADDR: 1352 case SCTP_REM_ADDR: 1353 /* 1354 * The sctp_t has to be bound first before 1355 * the address list can be changed. 1356 */ 1357 if (sctp->sctp_state < SCTPS_BOUND) { 1358 retval = EINVAL; 1359 break; 1360 } 1361 if (sctp->sctp_family == AF_INET) { 1362 addrcnt = inlen / sizeof (struct sockaddr_in); 1363 } else { 1364 ASSERT(sctp->sctp_family == AF_INET6); 1365 addrcnt = inlen / sizeof (struct sockaddr_in6); 1366 } 1367 if (name == SCTP_ADD_ADDR) { 1368 retval = sctp_bind_add(sctp, invalp, addrcnt, 1369 B_TRUE, sctp->sctp_lport); 1370 } else { 1371 retval = sctp_bind_del(sctp, invalp, addrcnt, 1372 B_TRUE); 1373 } 1374 break; 1375 case SCTP_UC_SWAP: { 1376 struct sctp_uc_swap *us; 1377 1378 /* 1379 * Change handle & upcalls. 1380 */ 1381 if (inlen < sizeof (*us)) { 1382 retval = EINVAL; 1383 break; 1384 } 1385 us = (struct sctp_uc_swap *)invalp; 1386 sctp->sctp_ulpd = us->sus_handle; 1387 sctp->sctp_upcalls = us->sus_upcalls; 1388 #if 0 1389 bcopy(us->sus_upcalls, &sctp->sctp_upcalls, 1390 sizeof (sctp_upcalls_t)); 1391 #endif 1392 break; 1393 } 1394 case SCTP_PRSCTP: 1395 sctp->sctp_prsctp_aware = onoff; 1396 break; 1397 case SCTP_I_WANT_MAPPED_V4_ADDR: 1398 case SCTP_MAXSEG: 1399 case SCTP_DISABLE_FRAGMENTS: 1400 /* Not yet supported. */ 1401 default: 1402 retval = ENOPROTOOPT; 1403 break; 1404 } 1405 break; 1406 1407 case IPPROTO_IP: 1408 if (sctp->sctp_family != AF_INET) { 1409 retval = ENOPROTOOPT; 1410 break; 1411 } 1412 if ((name != IP_OPTIONS) && (inlen < sizeof (int32_t))) { 1413 retval = EINVAL; 1414 break; 1415 } 1416 switch (name) { 1417 case IP_OPTIONS: 1418 case T_IP_OPTIONS: 1419 retval = sctp_opt_set_header(sctp, invalp, inlen); 1420 break; 1421 case IP_TOS: 1422 case T_IP_TOS: 1423 sctp->sctp_ipha->ipha_type_of_service = (uchar_t)*i1; 1424 break; 1425 case IP_TTL: 1426 sctp->sctp_ipha->ipha_ttl = (uchar_t)*i1; 1427 break; 1428 case IP_SEC_OPT: 1429 /* 1430 * We should not allow policy setting after 1431 * we start listening for connections. 1432 */ 1433 if (sctp->sctp_state >= SCTPS_LISTEN) { 1434 retval = EINVAL; 1435 } else { 1436 retval = ipsec_set_req(sctp->sctp_credp, 1437 sctp->sctp_connp, (ipsec_req_t *)invalp); 1438 } 1439 break; 1440 /* IP level options */ 1441 case IP_UNSPEC_SRC: 1442 connp->conn_unspec_src = onoff; 1443 break; 1444 case IP_NEXTHOP: { 1445 ipaddr_t addr = *i1; 1446 ipif_t *ipif = NULL; 1447 ill_t *ill; 1448 ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip; 1449 1450 if (secpolicy_ip(sctp->sctp_credp, OP_CONFIG, 1451 B_TRUE) == 0) { 1452 ipif = ipif_lookup_onlink_addr(addr, 1453 connp->conn_zoneid, ipst); 1454 if (ipif == NULL) { 1455 retval = EHOSTUNREACH; 1456 break; 1457 } 1458 ill = ipif->ipif_ill; 1459 mutex_enter(&ill->ill_lock); 1460 if ((ill->ill_state_flags & ILL_CONDEMNED) || 1461 (ipif->ipif_state_flags & IPIF_CONDEMNED)) { 1462 mutex_exit(&ill->ill_lock); 1463 ipif_refrele(ipif); 1464 retval = EHOSTUNREACH; 1465 break; 1466 } 1467 mutex_exit(&ill->ill_lock); 1468 ipif_refrele(ipif); 1469 mutex_enter(&connp->conn_lock); 1470 connp->conn_nexthop_v4 = addr; 1471 connp->conn_nexthop_set = B_TRUE; 1472 mutex_exit(&connp->conn_lock); 1473 } 1474 break; 1475 } 1476 default: 1477 retval = ENOPROTOOPT; 1478 break; 1479 } 1480 break; 1481 case IPPROTO_IPV6: { 1482 if (sctp->sctp_family != AF_INET6) { 1483 retval = ENOPROTOOPT; 1484 break; 1485 } 1486 1487 switch (name) { 1488 case IPV6_UNICAST_HOPS: 1489 if (inlen < sizeof (int32_t)) { 1490 retval = EINVAL; 1491 break; 1492 } 1493 if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) { 1494 retval = EINVAL; 1495 break; 1496 } 1497 if (*i1 == -1) { 1498 ipp->ipp_unicast_hops = 1499 sctps->sctps_ipv6_hoplimit; 1500 ipp->ipp_fields &= ~IPPF_UNICAST_HOPS; 1501 } else { 1502 ipp->ipp_unicast_hops = (uint8_t)*i1; 1503 ipp->ipp_fields |= IPPF_UNICAST_HOPS; 1504 } 1505 retval = sctp_build_hdrs(sctp); 1506 break; 1507 case IPV6_UNSPEC_SRC: 1508 if (inlen < sizeof (int32_t)) { 1509 retval = EINVAL; 1510 break; 1511 } 1512 connp->conn_unspec_src = onoff; 1513 break; 1514 case IPV6_RECVPKTINFO: 1515 if (inlen < sizeof (int32_t)) { 1516 retval = EINVAL; 1517 break; 1518 } 1519 if (onoff) 1520 sctp->sctp_ipv6_recvancillary |= 1521 SCTP_IPV6_RECVPKTINFO; 1522 else 1523 sctp->sctp_ipv6_recvancillary &= 1524 ~SCTP_IPV6_RECVPKTINFO; 1525 /* Send it with the next msg */ 1526 sctp->sctp_recvifindex = 0; 1527 connp->conn_ip_recvpktinfo = onoff; 1528 break; 1529 case IPV6_RECVHOPLIMIT: 1530 if (inlen < sizeof (int32_t)) { 1531 retval = EINVAL; 1532 break; 1533 } 1534 if (onoff) 1535 sctp->sctp_ipv6_recvancillary |= 1536 SCTP_IPV6_RECVHOPLIMIT; 1537 else 1538 sctp->sctp_ipv6_recvancillary &= 1539 ~SCTP_IPV6_RECVHOPLIMIT; 1540 sctp->sctp_recvhops = 0xffffffffU; 1541 connp->conn_ipv6_recvhoplimit = onoff; 1542 break; 1543 case IPV6_RECVHOPOPTS: 1544 if (inlen < sizeof (int32_t)) { 1545 retval = EINVAL; 1546 break; 1547 } 1548 if (onoff) 1549 sctp->sctp_ipv6_recvancillary |= 1550 SCTP_IPV6_RECVHOPOPTS; 1551 else 1552 sctp->sctp_ipv6_recvancillary &= 1553 ~SCTP_IPV6_RECVHOPOPTS; 1554 connp->conn_ipv6_recvhopopts = onoff; 1555 break; 1556 case IPV6_RECVDSTOPTS: 1557 if (inlen < sizeof (int32_t)) { 1558 retval = EINVAL; 1559 break; 1560 } 1561 if (onoff) 1562 sctp->sctp_ipv6_recvancillary |= 1563 SCTP_IPV6_RECVDSTOPTS; 1564 else 1565 sctp->sctp_ipv6_recvancillary &= 1566 ~SCTP_IPV6_RECVDSTOPTS; 1567 connp->conn_ipv6_recvdstopts = onoff; 1568 break; 1569 case IPV6_RECVRTHDR: 1570 if (inlen < sizeof (int32_t)) { 1571 retval = EINVAL; 1572 break; 1573 } 1574 if (onoff) 1575 sctp->sctp_ipv6_recvancillary |= 1576 SCTP_IPV6_RECVRTHDR; 1577 else 1578 sctp->sctp_ipv6_recvancillary &= 1579 ~SCTP_IPV6_RECVRTHDR; 1580 connp->conn_ipv6_recvrthdr = onoff; 1581 break; 1582 case IPV6_RECVRTHDRDSTOPTS: 1583 if (inlen < sizeof (int32_t)) { 1584 retval = EINVAL; 1585 break; 1586 } 1587 if (onoff) 1588 sctp->sctp_ipv6_recvancillary |= 1589 SCTP_IPV6_RECVRTDSTOPTS; 1590 else 1591 sctp->sctp_ipv6_recvancillary &= 1592 ~SCTP_IPV6_RECVRTDSTOPTS; 1593 connp->conn_ipv6_recvrtdstopts = onoff; 1594 break; 1595 case IPV6_PKTINFO: 1596 if (inlen != 0 && 1597 inlen != sizeof (struct in6_pktinfo)) { 1598 retval = EINVAL; 1599 break; 1600 } 1601 1602 if (inlen == 0) { 1603 ipp->ipp_fields &= ~(IPPF_IFINDEX |IPPF_ADDR); 1604 } else { 1605 struct in6_pktinfo *pkti; 1606 1607 pkti = (struct in6_pktinfo *)invalp; 1608 /* XXX Need to check if the index exists */ 1609 ipp->ipp_ifindex = pkti->ipi6_ifindex; 1610 ipp->ipp_addr = pkti->ipi6_addr; 1611 if (ipp->ipp_ifindex != 0) 1612 ipp->ipp_fields |= IPPF_IFINDEX; 1613 else 1614 ipp->ipp_fields &= ~IPPF_IFINDEX; 1615 if (!IN6_IS_ADDR_UNSPECIFIED(&ipp->ipp_addr)) 1616 ipp->ipp_fields |= IPPF_ADDR; 1617 else 1618 ipp->ipp_fields &= ~IPPF_ADDR; 1619 } 1620 retval = sctp_build_hdrs(sctp); 1621 break; 1622 case IPV6_NEXTHOP: { 1623 struct sockaddr_in6 *sin6; 1624 ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip; 1625 1626 if (inlen != 0 && inlen != sizeof (sin6_t)) { 1627 retval = EINVAL; 1628 break; 1629 } 1630 1631 if (inlen == 0) { 1632 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1633 } else { 1634 sin6 = (struct sockaddr_in6 *)invalp; 1635 if (sin6->sin6_family != AF_INET6) { 1636 retval = EAFNOSUPPORT; 1637 break; 1638 } 1639 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 1640 retval = EADDRNOTAVAIL; 1641 break; 1642 } 1643 ipp->ipp_nexthop = sin6->sin6_addr; 1644 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1645 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1646 } else { 1647 ire_t *ire; 1648 1649 ire = ire_route_lookup_v6( 1650 &sin6->sin6_addr, NULL, NULL, 0, 1651 NULL, NULL, ALL_ZONES, NULL, 1652 MATCH_IRE_DEFAULT, ipst); 1653 if (ire == NULL) { 1654 retval = EHOSTUNREACH; 1655 break; 1656 } 1657 ire_refrele(ire); 1658 ipp->ipp_fields |= IPPF_NEXTHOP; 1659 } 1660 } 1661 retval = sctp_build_hdrs(sctp); 1662 break; 1663 } 1664 case IPV6_HOPOPTS: { 1665 ip6_hbh_t *hopts = (ip6_hbh_t *)invalp; 1666 1667 if (inlen != 0 && 1668 inlen != (8 * (hopts->ip6h_len + 1))) { 1669 retval = EINVAL; 1670 break; 1671 } 1672 1673 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1674 B_TRUE, (uchar_t **)&ipp->ipp_hopopts, 1675 &ipp->ipp_hopoptslen, sctp->sctp_v6label_len); 1676 if (retval != 0) 1677 break; 1678 if (ipp->ipp_hopoptslen == 0) 1679 ipp->ipp_fields &= ~IPPF_HOPOPTS; 1680 else 1681 ipp->ipp_fields |= IPPF_HOPOPTS; 1682 retval = sctp_build_hdrs(sctp); 1683 break; 1684 } 1685 case IPV6_RTHDRDSTOPTS: { 1686 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1687 1688 if (inlen != 0 && 1689 inlen != (8 * (dopts->ip6d_len + 1))) { 1690 retval = EINVAL; 1691 break; 1692 } 1693 1694 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1695 B_TRUE, (uchar_t **)&ipp->ipp_rtdstopts, 1696 &ipp->ipp_rtdstoptslen, 0); 1697 if (retval != 0) 1698 break; 1699 if (ipp->ipp_rtdstoptslen == 0) 1700 ipp->ipp_fields &= ~IPPF_RTDSTOPTS; 1701 else 1702 ipp->ipp_fields |= IPPF_RTDSTOPTS; 1703 retval = sctp_build_hdrs(sctp); 1704 break; 1705 } 1706 case IPV6_DSTOPTS: { 1707 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1708 1709 if (inlen != 0 && 1710 inlen != (8 * (dopts->ip6d_len + 1))) { 1711 retval = EINVAL; 1712 break; 1713 } 1714 1715 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1716 B_TRUE, (uchar_t **)&ipp->ipp_dstopts, 1717 &ipp->ipp_dstoptslen, 0); 1718 if (retval != 0) 1719 break; 1720 if (ipp->ipp_dstoptslen == 0) 1721 ipp->ipp_fields &= ~IPPF_DSTOPTS; 1722 else 1723 ipp->ipp_fields |= IPPF_DSTOPTS; 1724 retval = sctp_build_hdrs(sctp); 1725 break; 1726 } 1727 case IPV6_RTHDR: { 1728 ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp; 1729 1730 if (inlen != 0 && 1731 inlen != (8 * (rt->ip6r_len + 1))) { 1732 retval = EINVAL; 1733 break; 1734 } 1735 1736 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1737 B_TRUE, (uchar_t **)&ipp->ipp_rthdr, 1738 &ipp->ipp_rthdrlen, 0); 1739 if (retval != 0) 1740 break; 1741 if (ipp->ipp_rthdrlen == 0) 1742 ipp->ipp_fields &= ~IPPF_RTHDR; 1743 else 1744 ipp->ipp_fields |= IPPF_RTHDR; 1745 retval = sctp_build_hdrs(sctp); 1746 break; 1747 } 1748 case IPV6_SEC_OPT: 1749 /* 1750 * We should not allow policy setting after 1751 * we start listening for connections. 1752 */ 1753 if (sctp->sctp_state >= SCTPS_LISTEN) { 1754 retval = EINVAL; 1755 } else { 1756 retval = ipsec_set_req(sctp->sctp_credp, 1757 sctp->sctp_connp, (ipsec_req_t *)invalp); 1758 } 1759 break; 1760 case IPV6_V6ONLY: 1761 /* 1762 * After the bound state, setting the v6only option 1763 * is too late. 1764 */ 1765 if (sctp->sctp_state >= SCTPS_BOUND) { 1766 retval = EINVAL; 1767 } else { 1768 sctp->sctp_connp->conn_ipv6_v6only = onoff; 1769 } 1770 break; 1771 default: 1772 retval = ENOPROTOOPT; 1773 break; 1774 } 1775 break; 1776 } 1777 default: 1778 retval = ENOPROTOOPT; 1779 break; 1780 } 1781 1782 WAKE_SCTP(sctp); 1783 return (retval); 1784 } 1785 1786 /* 1787 * SCTP exported kernel interface for geting the first source address of 1788 * a sctp_t. The parameter addr is assumed to have enough space to hold 1789 * one socket address. 1790 */ 1791 int 1792 sctp_getsockname(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1793 { 1794 int err = 0; 1795 int addrcnt = 1; 1796 sin_t *sin4; 1797 sin6_t *sin6; 1798 1799 ASSERT(sctp != NULL); 1800 1801 RUN_SCTP(sctp); 1802 addr->sa_family = sctp->sctp_family; 1803 switch (sctp->sctp_family) { 1804 case AF_INET: 1805 sin4 = (sin_t *)addr; 1806 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1807 sctp->sctp_bound_to_all) { 1808 sin4->sin_addr.s_addr = INADDR_ANY; 1809 sin4->sin_port = sctp->sctp_lport; 1810 } else { 1811 err = sctp_getmyaddrs(sctp, sin4, &addrcnt); 1812 if (err != 0) { 1813 *addrlen = 0; 1814 break; 1815 } 1816 } 1817 *addrlen = sizeof (struct sockaddr_in); 1818 break; 1819 case AF_INET6: 1820 sin6 = (sin6_t *)addr; 1821 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1822 sctp->sctp_bound_to_all) { 1823 bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr)); 1824 sin6->sin6_port = sctp->sctp_lport; 1825 } else { 1826 err = sctp_getmyaddrs(sctp, sin6, &addrcnt); 1827 if (err != 0) { 1828 *addrlen = 0; 1829 break; 1830 } 1831 } 1832 *addrlen = sizeof (struct sockaddr_in6); 1833 sin6->sin6_flowinfo = sctp->sctp_ip6h->ip6_vcf & 1834 ~IPV6_VERS_AND_FLOW_MASK; 1835 sin6->sin6_scope_id = 0; 1836 sin6->__sin6_src_id = 0; 1837 break; 1838 } 1839 WAKE_SCTP(sctp); 1840 return (err); 1841 } 1842 1843 /* 1844 * SCTP exported kernel interface for geting the primary peer address of 1845 * a sctp_t. The parameter addr is assumed to have enough space to hold 1846 * one socket address. 1847 */ 1848 int 1849 sctp_getpeername(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1850 { 1851 int err = 0; 1852 int addrcnt = 1; 1853 sin6_t *sin6; 1854 1855 ASSERT(sctp != NULL); 1856 1857 RUN_SCTP(sctp); 1858 addr->sa_family = sctp->sctp_family; 1859 switch (sctp->sctp_family) { 1860 case AF_INET: 1861 err = sctp_getpeeraddrs(sctp, addr, &addrcnt); 1862 if (err != 0) { 1863 *addrlen = 0; 1864 break; 1865 } 1866 *addrlen = sizeof (struct sockaddr_in); 1867 break; 1868 case AF_INET6: 1869 sin6 = (sin6_t *)addr; 1870 err = sctp_getpeeraddrs(sctp, sin6, &addrcnt); 1871 if (err != 0) { 1872 *addrlen = 0; 1873 break; 1874 } 1875 *addrlen = sizeof (struct sockaddr_in6); 1876 sin6->sin6_flowinfo = 0; 1877 sin6->sin6_scope_id = 0; 1878 sin6->__sin6_src_id = 0; 1879 break; 1880 } 1881 WAKE_SCTP(sctp); 1882 return (err); 1883 } 1884 1885 /* 1886 * Return a list of IP addresses of the peer endpoint of this sctp_t. 1887 * The parameter paddrs is supposed to be either (struct sockaddr_in *) or 1888 * (struct sockaddr_in6 *) depending on the address family of the sctp_t. 1889 */ 1890 int 1891 sctp_getpeeraddrs(sctp_t *sctp, void *paddrs, int *addrcnt) 1892 { 1893 int family; 1894 struct sockaddr_in *sin4; 1895 struct sockaddr_in6 *sin6; 1896 int max; 1897 int cnt; 1898 sctp_faddr_t *fp = sctp->sctp_faddrs; 1899 in6_addr_t addr; 1900 1901 ASSERT(sctp != NULL); 1902 1903 if (sctp->sctp_faddrs == NULL) 1904 return (ENOTCONN); 1905 1906 family = sctp->sctp_family; 1907 max = *addrcnt; 1908 1909 /* If we want only one, give the primary */ 1910 if (max == 1) { 1911 addr = sctp->sctp_primary->faddr; 1912 switch (family) { 1913 case AF_INET: 1914 sin4 = paddrs; 1915 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1916 sin4->sin_port = sctp->sctp_fport; 1917 sin4->sin_family = AF_INET; 1918 break; 1919 1920 case AF_INET6: 1921 sin6 = paddrs; 1922 sin6->sin6_addr = addr; 1923 sin6->sin6_port = sctp->sctp_fport; 1924 sin6->sin6_family = AF_INET6; 1925 break; 1926 } 1927 return (0); 1928 } 1929 1930 for (cnt = 0; cnt < max && fp != NULL; cnt++, fp = fp->next) { 1931 addr = fp->faddr; 1932 switch (family) { 1933 case AF_INET: 1934 ASSERT(IN6_IS_ADDR_V4MAPPED(&addr)); 1935 sin4 = (struct sockaddr_in *)paddrs + cnt; 1936 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1937 sin4->sin_port = sctp->sctp_fport; 1938 sin4->sin_family = AF_INET; 1939 break; 1940 case AF_INET6: 1941 sin6 = (struct sockaddr_in6 *)paddrs + cnt; 1942 sin6->sin6_addr = addr; 1943 sin6->sin6_port = sctp->sctp_fport; 1944 sin6->sin6_family = AF_INET6; 1945 break; 1946 } 1947 } 1948 *addrcnt = cnt; 1949 return (0); 1950 } 1951