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_exempt; 738 break; 739 case SO_PROTOTYPE: 740 *i1 = IPPROTO_SCTP; 741 break; 742 case SO_DOMAIN: 743 *i1 = sctp->sctp_family; 744 break; 745 default: 746 retval = ENOPROTOOPT; 747 break; 748 } 749 break; 750 751 case IPPROTO_SCTP: 752 switch (name) { 753 case SCTP_RTOINFO: 754 if (buflen < sizeof (struct sctp_rtoinfo)) { 755 retval = EINVAL; 756 break; 757 } 758 *optlen = sctp_get_rtoinfo(sctp, ptr); 759 break; 760 case SCTP_ASSOCINFO: 761 if (buflen < sizeof (struct sctp_assocparams)) { 762 retval = EINVAL; 763 break; 764 } 765 *optlen = sctp_get_assocparams(sctp, ptr); 766 break; 767 case SCTP_INITMSG: 768 if (buflen < sizeof (struct sctp_initmsg)) { 769 retval = EINVAL; 770 break; 771 } 772 *optlen = sctp_get_initmsg(sctp, ptr); 773 break; 774 case SCTP_NODELAY: 775 *i1 = sctp->sctp_ndelay; 776 break; 777 case SCTP_AUTOCLOSE: 778 *i1 = TICK_TO_SEC(sctp->sctp_autoclose); 779 break; 780 case SCTP_ADAPTATION_LAYER: 781 if (buflen < sizeof (struct sctp_setadaptation)) { 782 retval = EINVAL; 783 break; 784 } 785 ((struct sctp_setadaptation *)ptr)->ssb_adaptation_ind = 786 sctp->sctp_tx_adaptation_code; 787 break; 788 case SCTP_PEER_ADDR_PARAMS: 789 if (buflen < sizeof (struct sctp_paddrparams)) { 790 retval = EINVAL; 791 break; 792 } 793 *optlen = sctp_get_peer_addr_params(sctp, ptr); 794 break; 795 case SCTP_DEFAULT_SEND_PARAM: 796 if (buflen < sizeof (struct sctp_sndrcvinfo)) { 797 retval = EINVAL; 798 break; 799 } 800 *optlen = sctp_get_def_send_params(sctp, ptr); 801 break; 802 case SCTP_EVENTS: { 803 struct sctp_event_subscribe *ev; 804 805 if (buflen < sizeof (struct sctp_event_subscribe)) { 806 retval = EINVAL; 807 break; 808 } 809 ev = (struct sctp_event_subscribe *)ptr; 810 ev->sctp_data_io_event = 811 ONOFF(sctp->sctp_recvsndrcvinfo); 812 ev->sctp_association_event = 813 ONOFF(sctp->sctp_recvassocevnt); 814 ev->sctp_address_event = 815 ONOFF(sctp->sctp_recvpathevnt); 816 ev->sctp_send_failure_event = 817 ONOFF(sctp->sctp_recvsendfailevnt); 818 ev->sctp_peer_error_event = 819 ONOFF(sctp->sctp_recvpeererr); 820 ev->sctp_shutdown_event = 821 ONOFF(sctp->sctp_recvshutdownevnt); 822 ev->sctp_partial_delivery_event = 823 ONOFF(sctp->sctp_recvpdevnt); 824 ev->sctp_adaptation_layer_event = 825 ONOFF(sctp->sctp_recvalevnt); 826 *optlen = sizeof (struct sctp_event_subscribe); 827 break; 828 } 829 case SCTP_STATUS: 830 if (buflen < sizeof (struct sctp_status)) { 831 retval = EINVAL; 832 break; 833 } 834 *optlen = sctp_get_status(sctp, ptr); 835 break; 836 case SCTP_GET_PEER_ADDR_INFO: 837 if (buflen < sizeof (struct sctp_paddrinfo)) { 838 retval = EINVAL; 839 break; 840 } 841 retval = sctp_get_paddrinfo(sctp, ptr, optlen); 842 break; 843 case SCTP_GET_NLADDRS: 844 *(int32_t *)ptr = sctp->sctp_nsaddrs; 845 break; 846 case SCTP_GET_LADDRS: { 847 int addr_cnt; 848 int addr_size; 849 850 if (sctp->sctp_family == AF_INET) 851 addr_size = sizeof (struct sockaddr_in); 852 else 853 addr_size = sizeof (struct sockaddr_in6); 854 addr_cnt = buflen / addr_size; 855 retval = sctp_getmyaddrs(sctp, ptr, &addr_cnt); 856 if (retval == 0) 857 *optlen = addr_cnt * addr_size; 858 break; 859 } 860 case SCTP_GET_NPADDRS: { 861 int i; 862 sctp_faddr_t *fp; 863 864 for (i = 0, fp = sctp->sctp_faddrs; fp != NULL; 865 i++, fp = fp->next) 866 ; 867 *(int32_t *)ptr = i; 868 break; 869 } 870 case SCTP_GET_PADDRS: { 871 int addr_cnt; 872 int addr_size; 873 874 if (sctp->sctp_family == AF_INET) 875 addr_size = sizeof (struct sockaddr_in); 876 else 877 addr_size = sizeof (struct sockaddr_in6); 878 addr_cnt = buflen / addr_size; 879 retval = sctp_getpeeraddrs(sctp, ptr, &addr_cnt); 880 if (retval == 0) 881 *optlen = addr_cnt * addr_size; 882 break; 883 } 884 case SCTP_PRSCTP: 885 *i1 = sctp->sctp_prsctp_aware ? 1 : 0; 886 break; 887 888 case SCTP_GET_ASSOC_STATS: { 889 sctp_assoc_stats_t *sas; 890 891 if (buflen < sizeof (sctp_assoc_stats_t)) { 892 retval = EINVAL; 893 break; 894 } 895 896 sas = (sctp_assoc_stats_t *)ptr; 897 898 /* 899 * Copy the current stats to the stats struct. 900 */ 901 sas->sas_rtxchunks = sctp->sctp_rxtchunks; 902 sas->sas_gapcnt = sctp->sctp_gapcnt; 903 sas->sas_outseqtsns = sctp->sctp_outseqtsns; 904 sas->sas_osacks = sctp->sctp_osacks; 905 sas->sas_isacks = sctp->sctp_isacks; 906 sas->sas_octrlchunks = sctp->sctp_obchunks; 907 sas->sas_ictrlchunks = sctp->sctp_ibchunks; 908 sas->sas_oodchunks = sctp->sctp_odchunks; 909 sas->sas_iodchunks = sctp->sctp_idchunks; 910 sas->sas_ouodchunks = sctp->sctp_oudchunks; 911 sas->sas_iuodchunks = sctp->sctp_iudchunks; 912 sas->sas_idupchunks = sctp->sctp_idupchunks; 913 914 /* 915 * Copy out the maximum observed RTO since the 916 * time this data was last requested 917 */ 918 if (sctp->sctp_maxrto == 0) { 919 /* unchanged during obervation period */ 920 sas->sas_maxrto = sctp->sctp_prev_maxrto; 921 } else { 922 /* record new period maximum */ 923 sas->sas_maxrto = sctp->sctp_maxrto; 924 } 925 /* Record the value sent to the user this period */ 926 sctp->sctp_prev_maxrto = sas->sas_maxrto; 927 928 /* Mark beginning of a new observation period */ 929 sctp->sctp_maxrto = 0; 930 931 *optlen = sizeof (sctp_assoc_stats_t); 932 break; 933 } 934 case SCTP_I_WANT_MAPPED_V4_ADDR: 935 case SCTP_MAXSEG: 936 case SCTP_DISABLE_FRAGMENTS: 937 /* Not yet supported. */ 938 default: 939 retval = ENOPROTOOPT; 940 break; 941 } 942 break; 943 944 case IPPROTO_IP: 945 if (sctp->sctp_family != AF_INET) { 946 retval = EINVAL; 947 break; 948 } 949 switch (name) { 950 case IP_OPTIONS: 951 case T_IP_OPTIONS: { 952 /* 953 * This is compatible with BSD in that in only return 954 * the reverse source route with the final destination 955 * as the last entry. The first 4 bytes of the option 956 * will contain the final destination. Allocate a 957 * buffer large enough to hold all the options, we 958 * add IP_ADDR_LEN to SCTP_MAX_IP_OPTIONS_LENGTH since 959 * ip_opt_get_user() adds the final destination 960 * at the start. 961 */ 962 char *opt_ptr; 963 int opt_len; 964 uchar_t obuf[SCTP_MAX_IP_OPTIONS_LENGTH + IP_ADDR_LEN]; 965 966 opt_ptr = (char *)sctp->sctp_ipha + 967 IP_SIMPLE_HDR_LENGTH; 968 opt_len = (char *)sctp->sctp_sctph - opt_ptr; 969 /* Caller ensures enough space */ 970 if (opt_len > 0) { 971 /* 972 * TODO: Do we have to handle getsockopt on an 973 * initiator as well? 974 */ 975 opt_len = ip_opt_get_user(sctp->sctp_ipha, 976 obuf); 977 ASSERT(opt_len <= sizeof (obuf)); 978 } else { 979 opt_len = 0; 980 } 981 if (buflen < opt_len) { 982 /* Silently truncate */ 983 opt_len = buflen; 984 } 985 *optlen = opt_len; 986 bcopy(obuf, ptr, opt_len); 987 break; 988 } 989 case IP_TOS: 990 case T_IP_TOS: 991 *i1 = (int)sctp->sctp_ipha->ipha_type_of_service; 992 break; 993 case IP_TTL: 994 *i1 = (int)sctp->sctp_ipha->ipha_ttl; 995 break; 996 case IP_NEXTHOP: 997 if (connp->conn_nexthop_set) { 998 *(ipaddr_t *)ptr = connp->conn_nexthop_v4; 999 *optlen = sizeof (ipaddr_t); 1000 } else { 1001 *optlen = 0; 1002 } 1003 break; 1004 default: 1005 retval = ENOPROTOOPT; 1006 break; 1007 } 1008 break; 1009 case IPPROTO_IPV6: 1010 if (sctp->sctp_family != AF_INET6) { 1011 retval = EINVAL; 1012 break; 1013 } 1014 switch (name) { 1015 case IPV6_UNICAST_HOPS: 1016 *i1 = (unsigned int) sctp->sctp_ip6h->ip6_hops; 1017 break; /* goto sizeof (int) option return */ 1018 case IPV6_RECVPKTINFO: 1019 if (sctp->sctp_ipv6_recvancillary & 1020 SCTP_IPV6_RECVPKTINFO) { 1021 *i1 = 1; 1022 } else { 1023 *i1 = 0; 1024 } 1025 break; /* goto sizeof (int) option return */ 1026 case IPV6_RECVHOPLIMIT: 1027 if (sctp->sctp_ipv6_recvancillary & 1028 SCTP_IPV6_RECVHOPLIMIT) { 1029 *i1 = 1; 1030 } else { 1031 *i1 = 0; 1032 } 1033 break; /* goto sizeof (int) option return */ 1034 case IPV6_RECVHOPOPTS: 1035 if (sctp->sctp_ipv6_recvancillary & 1036 SCTP_IPV6_RECVHOPOPTS) { 1037 *i1 = 1; 1038 } else { 1039 *i1 = 0; 1040 } 1041 break; /* goto sizeof (int) option return */ 1042 case IPV6_RECVDSTOPTS: 1043 if (sctp->sctp_ipv6_recvancillary & 1044 SCTP_IPV6_RECVDSTOPTS) { 1045 *i1 = 1; 1046 } else { 1047 *i1 = 0; 1048 } 1049 break; /* goto sizeof (int) option return */ 1050 case IPV6_RECVRTHDR: 1051 if (sctp->sctp_ipv6_recvancillary & 1052 SCTP_IPV6_RECVRTHDR) { 1053 *i1 = 1; 1054 } else { 1055 *i1 = 0; 1056 } 1057 break; /* goto sizeof (int) option return */ 1058 case IPV6_RECVRTHDRDSTOPTS: 1059 if (sctp->sctp_ipv6_recvancillary & 1060 SCTP_IPV6_RECVRTDSTOPTS) { 1061 *i1 = 1; 1062 } else { 1063 *i1 = 0; 1064 } 1065 break; /* goto sizeof (int) option return */ 1066 case IPV6_PKTINFO: { 1067 struct in6_pktinfo *pkti; 1068 1069 if (buflen < sizeof (struct in6_pktinfo)) { 1070 retval = EINVAL; 1071 break; 1072 } 1073 pkti = (struct in6_pktinfo *)ptr; 1074 if (ipp->ipp_fields & IPPF_IFINDEX) 1075 pkti->ipi6_ifindex = ipp->ipp_ifindex; 1076 else 1077 pkti->ipi6_ifindex = 0; 1078 if (ipp->ipp_fields & IPPF_ADDR) 1079 pkti->ipi6_addr = ipp->ipp_addr; 1080 else 1081 pkti->ipi6_addr = ipv6_all_zeros; 1082 *optlen = sizeof (struct in6_pktinfo); 1083 break; 1084 } 1085 case IPV6_NEXTHOP: { 1086 sin6_t *sin6; 1087 1088 if (buflen < sizeof (sin6_t)) { 1089 retval = EINVAL; 1090 break; 1091 } 1092 sin6 = (sin6_t *)ptr; 1093 if (!(ipp->ipp_fields & IPPF_NEXTHOP)) 1094 break; 1095 *sin6 = sctp_sin6_null; 1096 sin6->sin6_family = AF_INET6; 1097 sin6->sin6_addr = ipp->ipp_nexthop; 1098 *optlen = sizeof (sin6_t); 1099 break; 1100 } 1101 case IPV6_HOPOPTS: { 1102 int len; 1103 1104 if (!(ipp->ipp_fields & IPPF_HOPOPTS)) 1105 break; 1106 len = ipp->ipp_hopoptslen - sctp->sctp_v6label_len; 1107 if (len <= 0) 1108 break; 1109 if (buflen < len) { 1110 retval = EINVAL; 1111 break; 1112 } 1113 bcopy((char *)ipp->ipp_hopopts + 1114 sctp->sctp_v6label_len, ptr, len); 1115 if (sctp->sctp_v6label_len > 0) { 1116 char *cptr = ptr; 1117 1118 /* 1119 * If the label length is greater than zero, 1120 * then we need to hide the label from user. 1121 * Make it look as though a normal Hop-By-Hop 1122 * Options Header is present here. 1123 */ 1124 cptr[0] = ((char *)ipp->ipp_hopopts)[0]; 1125 cptr[1] = (len + 7) / 8 - 1; 1126 } 1127 *optlen = len; 1128 break; 1129 } 1130 case IPV6_RTHDRDSTOPTS: 1131 if (!(ipp->ipp_fields & IPPF_RTDSTOPTS)) 1132 break; 1133 if (buflen < ipp->ipp_rtdstoptslen) { 1134 retval = EINVAL; 1135 break; 1136 } 1137 bcopy(ipp->ipp_rtdstopts, ptr, ipp->ipp_rtdstoptslen); 1138 *optlen = ipp->ipp_rtdstoptslen; 1139 break; 1140 case IPV6_RTHDR: 1141 if (!(ipp->ipp_fields & IPPF_RTHDR)) 1142 break; 1143 if (buflen < ipp->ipp_rthdrlen) { 1144 retval = EINVAL; 1145 break; 1146 } 1147 bcopy(ipp->ipp_rthdr, ptr, ipp->ipp_rthdrlen); 1148 *optlen = ipp->ipp_rthdrlen; 1149 break; 1150 case IPV6_DSTOPTS: 1151 if (!(ipp->ipp_fields & IPPF_DSTOPTS)) 1152 break; 1153 if (buflen < ipp->ipp_dstoptslen) { 1154 retval = EINVAL; 1155 break; 1156 } 1157 bcopy(ipp->ipp_dstopts, ptr, ipp->ipp_dstoptslen); 1158 *optlen = ipp->ipp_dstoptslen; 1159 break; 1160 case IPV6_V6ONLY: 1161 *i1 = sctp->sctp_connp->conn_ipv6_v6only; 1162 break; 1163 default: 1164 retval = ENOPROTOOPT; 1165 break; 1166 } 1167 break; 1168 1169 default: 1170 retval = ENOPROTOOPT; 1171 break; 1172 } 1173 WAKE_SCTP(sctp); 1174 return (retval); 1175 } 1176 1177 int 1178 sctp_set_opt(sctp_t *sctp, int level, int name, const void *invalp, 1179 socklen_t inlen) 1180 { 1181 ip6_pkt_t *ipp = &sctp->sctp_sticky_ipp; 1182 int *i1 = (int *)invalp; 1183 boolean_t onoff; 1184 int retval = 0, addrcnt; 1185 conn_t *connp = sctp->sctp_connp; 1186 sctp_stack_t *sctps = sctp->sctp_sctps; 1187 1188 /* In all cases, the size of the option must be bigger than int */ 1189 if (inlen >= sizeof (int32_t)) { 1190 onoff = ONOFF(*i1); 1191 } 1192 retval = 0; 1193 1194 RUN_SCTP(sctp); 1195 1196 if (connp->conn_state_flags & CONN_CLOSING) { 1197 WAKE_SCTP(sctp); 1198 return (EINVAL); 1199 } 1200 1201 switch (level) { 1202 case SOL_SOCKET: 1203 if (inlen < sizeof (int32_t)) { 1204 retval = EINVAL; 1205 break; 1206 } 1207 switch (name) { 1208 case SO_LINGER: { 1209 struct linger *lgr; 1210 1211 if (inlen != sizeof (struct linger)) { 1212 retval = EINVAL; 1213 break; 1214 } 1215 lgr = (struct linger *)invalp; 1216 if (lgr->l_onoff != 0) { 1217 sctp->sctp_linger = 1; 1218 sctp->sctp_lingertime = MSEC_TO_TICK( 1219 lgr->l_linger); 1220 } else { 1221 sctp->sctp_linger = 0; 1222 sctp->sctp_lingertime = 0; 1223 } 1224 break; 1225 } 1226 case SO_DEBUG: 1227 sctp->sctp_debug = onoff; 1228 break; 1229 case SO_KEEPALIVE: 1230 break; 1231 case SO_DONTROUTE: 1232 /* 1233 * SO_DONTROUTE, SO_USELOOPBACK and SO_BROADCAST are 1234 * only of interest to IP. 1235 */ 1236 connp->conn_dontroute = onoff; 1237 break; 1238 case SO_USELOOPBACK: 1239 connp->conn_loopback = onoff; 1240 break; 1241 case SO_BROADCAST: 1242 connp->conn_broadcast = onoff; 1243 break; 1244 case SO_REUSEADDR: 1245 connp->conn_reuseaddr = onoff; 1246 break; 1247 case SO_DGRAM_ERRIND: 1248 sctp->sctp_dgram_errind = onoff; 1249 break; 1250 case SO_SNDBUF: 1251 if (*i1 > sctps->sctps_max_buf) { 1252 retval = ENOBUFS; 1253 break; 1254 } 1255 if (*i1 < 0) { 1256 retval = EINVAL; 1257 break; 1258 } 1259 sctp->sctp_xmit_hiwater = *i1; 1260 if (sctps->sctps_snd_lowat_fraction != 0) 1261 sctp->sctp_xmit_lowater = 1262 sctp->sctp_xmit_hiwater / 1263 sctps->sctps_snd_lowat_fraction; 1264 break; 1265 case SO_RCVBUF: 1266 if (*i1 > sctps->sctps_max_buf) { 1267 retval = ENOBUFS; 1268 break; 1269 } 1270 /* Silently ignore zero */ 1271 if (*i1 != 0) { 1272 struct sock_proto_props sopp; 1273 1274 /* 1275 * Insist on a receive window that is at least 1276 * sctp_recv_hiwat_minmss * MSS (default 4*MSS) 1277 * to avoid funny interactions of Nagle 1278 * algorithm, SWS avoidance and delayed 1279 * acknowledgement. 1280 */ 1281 *i1 = MAX(*i1, 1282 sctps->sctps_recv_hiwat_minmss * 1283 sctp->sctp_mss); 1284 sctp->sctp_rwnd = *i1; 1285 sctp->sctp_irwnd = sctp->sctp_rwnd; 1286 sctp->sctp_pd_point = sctp->sctp_rwnd; 1287 1288 sopp.sopp_flags = SOCKOPT_RCVHIWAT; 1289 sopp.sopp_rxhiwat = *i1; 1290 sctp->sctp_ulp_prop(sctp->sctp_ulpd, &sopp); 1291 1292 } 1293 /* 1294 * XXX should we return the rwnd here 1295 * and sctp_opt_get ? 1296 */ 1297 break; 1298 case SO_ALLZONES: 1299 if (secpolicy_ip(sctp->sctp_credp, OP_CONFIG, 1300 B_TRUE)) { 1301 retval = EACCES; 1302 break; 1303 } 1304 if (sctp->sctp_state >= SCTPS_BOUND) { 1305 retval = EINVAL; 1306 break; 1307 } 1308 sctp->sctp_allzones = onoff; 1309 break; 1310 case SO_MAC_EXEMPT: 1311 if (secpolicy_net_mac_aware(sctp->sctp_credp) != 0) { 1312 retval = EACCES; 1313 break; 1314 } 1315 if (sctp->sctp_state >= SCTPS_BOUND) { 1316 retval = EINVAL; 1317 break; 1318 } 1319 connp->conn_mac_exempt = onoff; 1320 break; 1321 default: 1322 retval = ENOPROTOOPT; 1323 break; 1324 } 1325 break; 1326 1327 case IPPROTO_SCTP: 1328 if (inlen < sizeof (int32_t)) { 1329 retval = EINVAL; 1330 break; 1331 } 1332 switch (name) { 1333 case SCTP_RTOINFO: 1334 retval = sctp_set_rtoinfo(sctp, invalp, inlen); 1335 break; 1336 case SCTP_ASSOCINFO: 1337 retval = sctp_set_assocparams(sctp, invalp, inlen); 1338 break; 1339 case SCTP_INITMSG: 1340 retval = sctp_set_initmsg(sctp, invalp, inlen); 1341 break; 1342 case SCTP_NODELAY: 1343 sctp->sctp_ndelay = ONOFF(*i1); 1344 break; 1345 case SCTP_AUTOCLOSE: 1346 if (SEC_TO_TICK(*i1) < 0) { 1347 retval = EINVAL; 1348 break; 1349 } 1350 /* Convert the number of seconds to ticks. */ 1351 sctp->sctp_autoclose = SEC_TO_TICK(*i1); 1352 sctp_heartbeat_timer(sctp); 1353 break; 1354 case SCTP_SET_PEER_PRIMARY_ADDR: 1355 retval = sctp_set_peerprim(sctp, invalp, inlen); 1356 break; 1357 case SCTP_PRIMARY_ADDR: 1358 retval = sctp_set_prim(sctp, invalp, inlen); 1359 break; 1360 case SCTP_ADAPTATION_LAYER: { 1361 struct sctp_setadaptation *ssb; 1362 1363 if (inlen < sizeof (struct sctp_setadaptation)) { 1364 retval = EINVAL; 1365 break; 1366 } 1367 ssb = (struct sctp_setadaptation *)invalp; 1368 sctp->sctp_send_adaptation = 1; 1369 sctp->sctp_tx_adaptation_code = ssb->ssb_adaptation_ind; 1370 break; 1371 } 1372 case SCTP_PEER_ADDR_PARAMS: 1373 retval = sctp_set_peer_addr_params(sctp, invalp, 1374 inlen); 1375 break; 1376 case SCTP_DEFAULT_SEND_PARAM: 1377 retval = sctp_set_def_send_params(sctp, invalp, inlen); 1378 break; 1379 case SCTP_EVENTS: { 1380 struct sctp_event_subscribe *ev; 1381 1382 if (inlen < sizeof (struct sctp_event_subscribe)) { 1383 retval = EINVAL; 1384 break; 1385 } 1386 ev = (struct sctp_event_subscribe *)invalp; 1387 sctp->sctp_recvsndrcvinfo = 1388 ONOFF(ev->sctp_data_io_event); 1389 sctp->sctp_recvassocevnt = 1390 ONOFF(ev->sctp_association_event); 1391 sctp->sctp_recvpathevnt = 1392 ONOFF(ev->sctp_address_event); 1393 sctp->sctp_recvsendfailevnt = 1394 ONOFF(ev->sctp_send_failure_event); 1395 sctp->sctp_recvpeererr = 1396 ONOFF(ev->sctp_peer_error_event); 1397 sctp->sctp_recvshutdownevnt = 1398 ONOFF(ev->sctp_shutdown_event); 1399 sctp->sctp_recvpdevnt = 1400 ONOFF(ev->sctp_partial_delivery_event); 1401 sctp->sctp_recvalevnt = 1402 ONOFF(ev->sctp_adaptation_layer_event); 1403 break; 1404 } 1405 case SCTP_ADD_ADDR: 1406 case SCTP_REM_ADDR: 1407 /* 1408 * The sctp_t has to be bound first before 1409 * the address list can be changed. 1410 */ 1411 if (sctp->sctp_state < SCTPS_BOUND) { 1412 retval = EINVAL; 1413 break; 1414 } 1415 if (sctp->sctp_family == AF_INET) { 1416 addrcnt = inlen / sizeof (struct sockaddr_in); 1417 } else { 1418 ASSERT(sctp->sctp_family == AF_INET6); 1419 addrcnt = inlen / sizeof (struct sockaddr_in6); 1420 } 1421 if (name == SCTP_ADD_ADDR) { 1422 retval = sctp_bind_add(sctp, invalp, addrcnt, 1423 B_TRUE, sctp->sctp_lport); 1424 } else { 1425 retval = sctp_bind_del(sctp, invalp, addrcnt, 1426 B_TRUE); 1427 } 1428 break; 1429 case SCTP_UC_SWAP: { 1430 struct sctp_uc_swap *us; 1431 1432 /* 1433 * Change handle & upcalls. 1434 */ 1435 if (inlen < sizeof (*us)) { 1436 retval = EINVAL; 1437 break; 1438 } 1439 us = (struct sctp_uc_swap *)invalp; 1440 sctp->sctp_ulpd = us->sus_handle; 1441 sctp->sctp_upcalls = us->sus_upcalls; 1442 break; 1443 } 1444 case SCTP_PRSCTP: 1445 sctp->sctp_prsctp_aware = onoff; 1446 break; 1447 case SCTP_I_WANT_MAPPED_V4_ADDR: 1448 case SCTP_MAXSEG: 1449 case SCTP_DISABLE_FRAGMENTS: 1450 /* Not yet supported. */ 1451 default: 1452 retval = ENOPROTOOPT; 1453 break; 1454 } 1455 break; 1456 1457 case IPPROTO_IP: 1458 if (sctp->sctp_family != AF_INET) { 1459 retval = ENOPROTOOPT; 1460 break; 1461 } 1462 if ((name != IP_OPTIONS) && (inlen < sizeof (int32_t))) { 1463 retval = EINVAL; 1464 break; 1465 } 1466 switch (name) { 1467 case IP_OPTIONS: 1468 case T_IP_OPTIONS: 1469 retval = sctp_opt_set_header(sctp, invalp, inlen); 1470 break; 1471 case IP_TOS: 1472 case T_IP_TOS: 1473 sctp->sctp_ipha->ipha_type_of_service = (uchar_t)*i1; 1474 break; 1475 case IP_TTL: 1476 sctp->sctp_ipha->ipha_ttl = (uchar_t)*i1; 1477 break; 1478 case IP_SEC_OPT: 1479 /* 1480 * We should not allow policy setting after 1481 * we start listening for connections. 1482 */ 1483 if (sctp->sctp_state >= SCTPS_LISTEN) { 1484 retval = EINVAL; 1485 } else { 1486 retval = ipsec_set_req(sctp->sctp_credp, 1487 sctp->sctp_connp, (ipsec_req_t *)invalp); 1488 } 1489 break; 1490 /* IP level options */ 1491 case IP_UNSPEC_SRC: 1492 connp->conn_unspec_src = onoff; 1493 break; 1494 case IP_NEXTHOP: { 1495 ipaddr_t addr = *i1; 1496 ipif_t *ipif = NULL; 1497 ill_t *ill; 1498 ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip; 1499 1500 if (secpolicy_ip(sctp->sctp_credp, OP_CONFIG, 1501 B_TRUE) == 0) { 1502 ipif = ipif_lookup_onlink_addr(addr, 1503 connp->conn_zoneid, ipst); 1504 if (ipif == NULL) { 1505 retval = EHOSTUNREACH; 1506 break; 1507 } 1508 ill = ipif->ipif_ill; 1509 mutex_enter(&ill->ill_lock); 1510 if ((ill->ill_state_flags & ILL_CONDEMNED) || 1511 (ipif->ipif_state_flags & IPIF_CONDEMNED)) { 1512 mutex_exit(&ill->ill_lock); 1513 ipif_refrele(ipif); 1514 retval = EHOSTUNREACH; 1515 break; 1516 } 1517 mutex_exit(&ill->ill_lock); 1518 ipif_refrele(ipif); 1519 mutex_enter(&connp->conn_lock); 1520 connp->conn_nexthop_v4 = addr; 1521 connp->conn_nexthop_set = B_TRUE; 1522 mutex_exit(&connp->conn_lock); 1523 } 1524 break; 1525 } 1526 default: 1527 retval = ENOPROTOOPT; 1528 break; 1529 } 1530 break; 1531 case IPPROTO_IPV6: { 1532 if (sctp->sctp_family != AF_INET6) { 1533 retval = ENOPROTOOPT; 1534 break; 1535 } 1536 1537 switch (name) { 1538 case IPV6_UNICAST_HOPS: 1539 if (inlen < sizeof (int32_t)) { 1540 retval = EINVAL; 1541 break; 1542 } 1543 if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) { 1544 retval = EINVAL; 1545 break; 1546 } 1547 if (*i1 == -1) { 1548 ipp->ipp_unicast_hops = 1549 sctps->sctps_ipv6_hoplimit; 1550 ipp->ipp_fields &= ~IPPF_UNICAST_HOPS; 1551 } else { 1552 ipp->ipp_unicast_hops = (uint8_t)*i1; 1553 ipp->ipp_fields |= IPPF_UNICAST_HOPS; 1554 } 1555 retval = sctp_build_hdrs(sctp); 1556 break; 1557 case IPV6_UNSPEC_SRC: 1558 if (inlen < sizeof (int32_t)) { 1559 retval = EINVAL; 1560 break; 1561 } 1562 connp->conn_unspec_src = onoff; 1563 break; 1564 case IPV6_RECVPKTINFO: 1565 if (inlen < sizeof (int32_t)) { 1566 retval = EINVAL; 1567 break; 1568 } 1569 if (onoff) 1570 sctp->sctp_ipv6_recvancillary |= 1571 SCTP_IPV6_RECVPKTINFO; 1572 else 1573 sctp->sctp_ipv6_recvancillary &= 1574 ~SCTP_IPV6_RECVPKTINFO; 1575 /* Send it with the next msg */ 1576 sctp->sctp_recvifindex = 0; 1577 connp->conn_ip_recvpktinfo = onoff; 1578 break; 1579 case IPV6_RECVHOPLIMIT: 1580 if (inlen < sizeof (int32_t)) { 1581 retval = EINVAL; 1582 break; 1583 } 1584 if (onoff) 1585 sctp->sctp_ipv6_recvancillary |= 1586 SCTP_IPV6_RECVHOPLIMIT; 1587 else 1588 sctp->sctp_ipv6_recvancillary &= 1589 ~SCTP_IPV6_RECVHOPLIMIT; 1590 sctp->sctp_recvhops = 0xffffffffU; 1591 connp->conn_ipv6_recvhoplimit = onoff; 1592 break; 1593 case IPV6_RECVHOPOPTS: 1594 if (inlen < sizeof (int32_t)) { 1595 retval = EINVAL; 1596 break; 1597 } 1598 if (onoff) 1599 sctp->sctp_ipv6_recvancillary |= 1600 SCTP_IPV6_RECVHOPOPTS; 1601 else 1602 sctp->sctp_ipv6_recvancillary &= 1603 ~SCTP_IPV6_RECVHOPOPTS; 1604 connp->conn_ipv6_recvhopopts = onoff; 1605 break; 1606 case IPV6_RECVDSTOPTS: 1607 if (inlen < sizeof (int32_t)) { 1608 retval = EINVAL; 1609 break; 1610 } 1611 if (onoff) 1612 sctp->sctp_ipv6_recvancillary |= 1613 SCTP_IPV6_RECVDSTOPTS; 1614 else 1615 sctp->sctp_ipv6_recvancillary &= 1616 ~SCTP_IPV6_RECVDSTOPTS; 1617 connp->conn_ipv6_recvdstopts = onoff; 1618 break; 1619 case IPV6_RECVRTHDR: 1620 if (inlen < sizeof (int32_t)) { 1621 retval = EINVAL; 1622 break; 1623 } 1624 if (onoff) 1625 sctp->sctp_ipv6_recvancillary |= 1626 SCTP_IPV6_RECVRTHDR; 1627 else 1628 sctp->sctp_ipv6_recvancillary &= 1629 ~SCTP_IPV6_RECVRTHDR; 1630 connp->conn_ipv6_recvrthdr = onoff; 1631 break; 1632 case IPV6_RECVRTHDRDSTOPTS: 1633 if (inlen < sizeof (int32_t)) { 1634 retval = EINVAL; 1635 break; 1636 } 1637 if (onoff) 1638 sctp->sctp_ipv6_recvancillary |= 1639 SCTP_IPV6_RECVRTDSTOPTS; 1640 else 1641 sctp->sctp_ipv6_recvancillary &= 1642 ~SCTP_IPV6_RECVRTDSTOPTS; 1643 connp->conn_ipv6_recvrtdstopts = onoff; 1644 break; 1645 case IPV6_PKTINFO: 1646 if (inlen != 0 && 1647 inlen != sizeof (struct in6_pktinfo)) { 1648 retval = EINVAL; 1649 break; 1650 } 1651 1652 if (inlen == 0) { 1653 ipp->ipp_fields &= ~(IPPF_IFINDEX |IPPF_ADDR); 1654 } else { 1655 struct in6_pktinfo *pkti; 1656 1657 pkti = (struct in6_pktinfo *)invalp; 1658 /* XXX Need to check if the index exists */ 1659 ipp->ipp_ifindex = pkti->ipi6_ifindex; 1660 ipp->ipp_addr = pkti->ipi6_addr; 1661 if (ipp->ipp_ifindex != 0) 1662 ipp->ipp_fields |= IPPF_IFINDEX; 1663 else 1664 ipp->ipp_fields &= ~IPPF_IFINDEX; 1665 if (!IN6_IS_ADDR_UNSPECIFIED(&ipp->ipp_addr)) 1666 ipp->ipp_fields |= IPPF_ADDR; 1667 else 1668 ipp->ipp_fields &= ~IPPF_ADDR; 1669 } 1670 retval = sctp_build_hdrs(sctp); 1671 break; 1672 case IPV6_NEXTHOP: { 1673 struct sockaddr_in6 *sin6; 1674 ip_stack_t *ipst = sctps->sctps_netstack->netstack_ip; 1675 1676 if (inlen != 0 && inlen != sizeof (sin6_t)) { 1677 retval = EINVAL; 1678 break; 1679 } 1680 1681 if (inlen == 0) { 1682 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1683 } else { 1684 sin6 = (struct sockaddr_in6 *)invalp; 1685 if (sin6->sin6_family != AF_INET6) { 1686 retval = EAFNOSUPPORT; 1687 break; 1688 } 1689 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 1690 retval = EADDRNOTAVAIL; 1691 break; 1692 } 1693 ipp->ipp_nexthop = sin6->sin6_addr; 1694 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 1695 ipp->ipp_fields &= ~IPPF_NEXTHOP; 1696 } else { 1697 ire_t *ire; 1698 1699 ire = ire_route_lookup_v6( 1700 &sin6->sin6_addr, NULL, NULL, 0, 1701 NULL, NULL, ALL_ZONES, NULL, 1702 MATCH_IRE_DEFAULT, ipst); 1703 if (ire == NULL) { 1704 retval = EHOSTUNREACH; 1705 break; 1706 } 1707 ire_refrele(ire); 1708 ipp->ipp_fields |= IPPF_NEXTHOP; 1709 } 1710 } 1711 retval = sctp_build_hdrs(sctp); 1712 break; 1713 } 1714 case IPV6_HOPOPTS: { 1715 ip6_hbh_t *hopts = (ip6_hbh_t *)invalp; 1716 1717 if (inlen != 0 && 1718 inlen != (8 * (hopts->ip6h_len + 1))) { 1719 retval = EINVAL; 1720 break; 1721 } 1722 1723 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1724 B_TRUE, (uchar_t **)&ipp->ipp_hopopts, 1725 &ipp->ipp_hopoptslen, sctp->sctp_v6label_len); 1726 if (retval != 0) 1727 break; 1728 if (ipp->ipp_hopoptslen == 0) 1729 ipp->ipp_fields &= ~IPPF_HOPOPTS; 1730 else 1731 ipp->ipp_fields |= IPPF_HOPOPTS; 1732 retval = sctp_build_hdrs(sctp); 1733 break; 1734 } 1735 case IPV6_RTHDRDSTOPTS: { 1736 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1737 1738 if (inlen != 0 && 1739 inlen != (8 * (dopts->ip6d_len + 1))) { 1740 retval = EINVAL; 1741 break; 1742 } 1743 1744 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1745 B_TRUE, (uchar_t **)&ipp->ipp_rtdstopts, 1746 &ipp->ipp_rtdstoptslen, 0); 1747 if (retval != 0) 1748 break; 1749 if (ipp->ipp_rtdstoptslen == 0) 1750 ipp->ipp_fields &= ~IPPF_RTDSTOPTS; 1751 else 1752 ipp->ipp_fields |= IPPF_RTDSTOPTS; 1753 retval = sctp_build_hdrs(sctp); 1754 break; 1755 } 1756 case IPV6_DSTOPTS: { 1757 ip6_dest_t *dopts = (ip6_dest_t *)invalp; 1758 1759 if (inlen != 0 && 1760 inlen != (8 * (dopts->ip6d_len + 1))) { 1761 retval = EINVAL; 1762 break; 1763 } 1764 1765 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1766 B_TRUE, (uchar_t **)&ipp->ipp_dstopts, 1767 &ipp->ipp_dstoptslen, 0); 1768 if (retval != 0) 1769 break; 1770 if (ipp->ipp_dstoptslen == 0) 1771 ipp->ipp_fields &= ~IPPF_DSTOPTS; 1772 else 1773 ipp->ipp_fields |= IPPF_DSTOPTS; 1774 retval = sctp_build_hdrs(sctp); 1775 break; 1776 } 1777 case IPV6_RTHDR: { 1778 ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp; 1779 1780 if (inlen != 0 && 1781 inlen != (8 * (rt->ip6r_len + 1))) { 1782 retval = EINVAL; 1783 break; 1784 } 1785 1786 retval = optcom_pkt_set((uchar_t *)invalp, inlen, 1787 B_TRUE, (uchar_t **)&ipp->ipp_rthdr, 1788 &ipp->ipp_rthdrlen, 0); 1789 if (retval != 0) 1790 break; 1791 if (ipp->ipp_rthdrlen == 0) 1792 ipp->ipp_fields &= ~IPPF_RTHDR; 1793 else 1794 ipp->ipp_fields |= IPPF_RTHDR; 1795 retval = sctp_build_hdrs(sctp); 1796 break; 1797 } 1798 case IPV6_SEC_OPT: 1799 /* 1800 * We should not allow policy setting after 1801 * we start listening for connections. 1802 */ 1803 if (sctp->sctp_state >= SCTPS_LISTEN) { 1804 retval = EINVAL; 1805 } else { 1806 retval = ipsec_set_req(sctp->sctp_credp, 1807 sctp->sctp_connp, (ipsec_req_t *)invalp); 1808 } 1809 break; 1810 case IPV6_V6ONLY: 1811 /* 1812 * After the bound state, setting the v6only option 1813 * is too late. 1814 */ 1815 if (sctp->sctp_state >= SCTPS_BOUND) { 1816 retval = EINVAL; 1817 } else { 1818 sctp->sctp_connp->conn_ipv6_v6only = onoff; 1819 } 1820 break; 1821 default: 1822 retval = ENOPROTOOPT; 1823 break; 1824 } 1825 break; 1826 } 1827 default: 1828 retval = ENOPROTOOPT; 1829 break; 1830 } 1831 1832 WAKE_SCTP(sctp); 1833 return (retval); 1834 } 1835 1836 /* 1837 * SCTP exported kernel interface for geting the first source address of 1838 * a sctp_t. The parameter addr is assumed to have enough space to hold 1839 * one socket address. 1840 */ 1841 int 1842 sctp_getsockname(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1843 { 1844 int err = 0; 1845 int addrcnt = 1; 1846 sin_t *sin4; 1847 sin6_t *sin6; 1848 1849 ASSERT(sctp != NULL); 1850 1851 RUN_SCTP(sctp); 1852 addr->sa_family = sctp->sctp_family; 1853 switch (sctp->sctp_family) { 1854 case AF_INET: 1855 sin4 = (sin_t *)addr; 1856 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1857 sctp->sctp_bound_to_all) { 1858 sin4->sin_addr.s_addr = INADDR_ANY; 1859 sin4->sin_port = sctp->sctp_lport; 1860 } else { 1861 err = sctp_getmyaddrs(sctp, sin4, &addrcnt); 1862 if (err != 0) { 1863 *addrlen = 0; 1864 break; 1865 } 1866 } 1867 *addrlen = sizeof (struct sockaddr_in); 1868 break; 1869 case AF_INET6: 1870 sin6 = (sin6_t *)addr; 1871 if ((sctp->sctp_state <= SCTPS_LISTEN) && 1872 sctp->sctp_bound_to_all) { 1873 bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr)); 1874 sin6->sin6_port = sctp->sctp_lport; 1875 } else { 1876 err = sctp_getmyaddrs(sctp, sin6, &addrcnt); 1877 if (err != 0) { 1878 *addrlen = 0; 1879 break; 1880 } 1881 } 1882 *addrlen = sizeof (struct sockaddr_in6); 1883 sin6->sin6_flowinfo = sctp->sctp_ip6h->ip6_vcf & 1884 ~IPV6_VERS_AND_FLOW_MASK; 1885 sin6->sin6_scope_id = 0; 1886 sin6->__sin6_src_id = 0; 1887 break; 1888 } 1889 WAKE_SCTP(sctp); 1890 return (err); 1891 } 1892 1893 /* 1894 * SCTP exported kernel interface for geting the primary peer address of 1895 * a sctp_t. The parameter addr is assumed to have enough space to hold 1896 * one socket address. 1897 */ 1898 int 1899 sctp_getpeername(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen) 1900 { 1901 int err = 0; 1902 int addrcnt = 1; 1903 sin6_t *sin6; 1904 1905 ASSERT(sctp != NULL); 1906 1907 RUN_SCTP(sctp); 1908 addr->sa_family = sctp->sctp_family; 1909 switch (sctp->sctp_family) { 1910 case AF_INET: 1911 err = sctp_getpeeraddrs(sctp, addr, &addrcnt); 1912 if (err != 0) { 1913 *addrlen = 0; 1914 break; 1915 } 1916 *addrlen = sizeof (struct sockaddr_in); 1917 break; 1918 case AF_INET6: 1919 sin6 = (sin6_t *)addr; 1920 err = sctp_getpeeraddrs(sctp, sin6, &addrcnt); 1921 if (err != 0) { 1922 *addrlen = 0; 1923 break; 1924 } 1925 *addrlen = sizeof (struct sockaddr_in6); 1926 sin6->sin6_flowinfo = 0; 1927 sin6->sin6_scope_id = 0; 1928 sin6->__sin6_src_id = 0; 1929 break; 1930 } 1931 WAKE_SCTP(sctp); 1932 return (err); 1933 } 1934 1935 /* 1936 * Return a list of IP addresses of the peer endpoint of this sctp_t. 1937 * The parameter paddrs is supposed to be either (struct sockaddr_in *) or 1938 * (struct sockaddr_in6 *) depending on the address family of the sctp_t. 1939 */ 1940 int 1941 sctp_getpeeraddrs(sctp_t *sctp, void *paddrs, int *addrcnt) 1942 { 1943 int family; 1944 struct sockaddr_in *sin4; 1945 struct sockaddr_in6 *sin6; 1946 int max; 1947 int cnt; 1948 sctp_faddr_t *fp = sctp->sctp_faddrs; 1949 in6_addr_t addr; 1950 1951 ASSERT(sctp != NULL); 1952 1953 if (sctp->sctp_faddrs == NULL) 1954 return (ENOTCONN); 1955 1956 family = sctp->sctp_family; 1957 max = *addrcnt; 1958 1959 /* If we want only one, give the primary */ 1960 if (max == 1) { 1961 addr = sctp->sctp_primary->faddr; 1962 switch (family) { 1963 case AF_INET: 1964 sin4 = paddrs; 1965 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1966 sin4->sin_port = sctp->sctp_fport; 1967 sin4->sin_family = AF_INET; 1968 break; 1969 1970 case AF_INET6: 1971 sin6 = paddrs; 1972 sin6->sin6_addr = addr; 1973 sin6->sin6_port = sctp->sctp_fport; 1974 sin6->sin6_family = AF_INET6; 1975 break; 1976 } 1977 return (0); 1978 } 1979 1980 for (cnt = 0; cnt < max && fp != NULL; cnt++, fp = fp->next) { 1981 addr = fp->faddr; 1982 switch (family) { 1983 case AF_INET: 1984 ASSERT(IN6_IS_ADDR_V4MAPPED(&addr)); 1985 sin4 = (struct sockaddr_in *)paddrs + cnt; 1986 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1987 sin4->sin_port = sctp->sctp_fport; 1988 sin4->sin_family = AF_INET; 1989 break; 1990 case AF_INET6: 1991 sin6 = (struct sockaddr_in6 *)paddrs + cnt; 1992 sin6->sin6_addr = addr; 1993 sin6->sin6_port = sctp->sctp_fport; 1994 sin6->sin6_family = AF_INET6; 1995 break; 1996 } 1997 } 1998 *addrcnt = cnt; 1999 return (0); 2000 } 2001