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