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