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