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