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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <sys/socket.h> 31 #include <sys/ddi.h> 32 #include <sys/sunddi.h> 33 #include <sys/strsun.h> 34 35 #include <netinet/in.h> 36 #include <netinet/ip6.h> 37 38 #include <inet/common.h> 39 #include <inet/ip.h> 40 #include <inet/ip6.h> 41 #include <inet/ipclassifier.h> 42 #include <inet/ipsec_impl.h> 43 #include <inet/ipp_common.h> 44 #include <inet/sctp_ip.h> 45 46 #include "sctp_impl.h" 47 #include "sctp_addr.h" 48 49 /* SCTP bind hash list - all sctp_t with state >= BOUND. */ 50 sctp_tf_t sctp_bind_fanout[SCTP_BIND_FANOUT_SIZE]; 51 /* SCTP listen hash list - all sctp_t with state == LISTEN. */ 52 sctp_tf_t sctp_listen_fanout[SCTP_LISTEN_FANOUT_SIZE]; 53 54 /* Default association hash size. The size must be a power of 2. */ 55 #define SCTP_CONN_HASH_SIZE 8192 56 57 sctp_tf_t *sctp_conn_fanout; 58 uint_t sctp_conn_hash_size = SCTP_CONN_HASH_SIZE; 59 60 void 61 sctp_hash_init() 62 { 63 int i; 64 65 if (sctp_conn_hash_size & (sctp_conn_hash_size - 1)) { 66 /* Not a power of two. Round up to nearest power of two */ 67 for (i = 0; i < 31; i++) { 68 if (sctp_conn_hash_size < (1 << i)) 69 break; 70 } 71 sctp_conn_hash_size = 1 << i; 72 } 73 if (sctp_conn_hash_size < SCTP_CONN_HASH_SIZE) { 74 sctp_conn_hash_size = SCTP_CONN_HASH_SIZE; 75 cmn_err(CE_CONT, "using sctp_conn_hash_size = %u\n", 76 sctp_conn_hash_size); 77 } 78 sctp_conn_fanout = 79 (sctp_tf_t *)kmem_zalloc(sctp_conn_hash_size * 80 sizeof (sctp_tf_t), KM_SLEEP); 81 for (i = 0; i < sctp_conn_hash_size; i++) { 82 mutex_init(&sctp_conn_fanout[i].tf_lock, NULL, 83 MUTEX_DEFAULT, NULL); 84 } 85 for (i = 0; i < A_CNT(sctp_listen_fanout); i++) { 86 mutex_init(&sctp_listen_fanout[i].tf_lock, NULL, 87 MUTEX_DEFAULT, NULL); 88 } 89 for (i = 0; i < A_CNT(sctp_bind_fanout); i++) { 90 mutex_init(&sctp_bind_fanout[i].tf_lock, NULL, 91 MUTEX_DEFAULT, NULL); 92 } 93 } 94 95 void 96 sctp_hash_destroy() 97 { 98 int i; 99 100 for (i = 0; i < sctp_conn_hash_size; i++) { 101 mutex_destroy(&sctp_conn_fanout[i].tf_lock); 102 } 103 kmem_free(sctp_conn_fanout, sctp_conn_hash_size * sizeof (sctp_tf_t)); 104 for (i = 0; i < A_CNT(sctp_listen_fanout); i++) { 105 mutex_destroy(&sctp_listen_fanout[i].tf_lock); 106 } 107 for (i = 0; i < A_CNT(sctp_bind_fanout); i++) { 108 mutex_destroy(&sctp_bind_fanout[i].tf_lock); 109 } 110 } 111 112 /* Walk the SCTP global list and refrele the ire for this ipif */ 113 void 114 sctp_ire_cache_flush(ipif_t *ipif) 115 { 116 sctp_t *sctp; 117 sctp_t *sctp_prev = NULL; 118 sctp_faddr_t *fp; 119 conn_t *connp; 120 ire_t *ire; 121 122 sctp = gsctp; 123 mutex_enter(&sctp_g_lock); 124 while (sctp != NULL) { 125 mutex_enter(&sctp->sctp_reflock); 126 if (sctp->sctp_condemned) { 127 mutex_exit(&sctp->sctp_reflock); 128 sctp = list_next(&sctp_g_list, sctp); 129 continue; 130 } 131 sctp->sctp_refcnt++; 132 mutex_exit(&sctp->sctp_reflock); 133 mutex_exit(&sctp_g_lock); 134 if (sctp_prev != NULL) 135 SCTP_REFRELE(sctp_prev); 136 137 RUN_SCTP(sctp); 138 connp = sctp->sctp_connp; 139 mutex_enter(&connp->conn_lock); 140 ire = connp->conn_ire_cache; 141 if (ire != NULL && 142 (ipif == NULL || ire->ire_ipif == ipif)) { 143 connp->conn_ire_cache = NULL; 144 mutex_exit(&connp->conn_lock); 145 IRE_REFRELE_NOTR(ire); 146 } else { 147 mutex_exit(&connp->conn_lock); 148 } 149 /* check for ires cached in faddr */ 150 for (fp = sctp->sctp_faddrs; fp != NULL; 151 fp = fp->next) { 152 ire = fp->ire; 153 if (ire != NULL && (ipif == NULL || 154 ire->ire_ipif == ipif)) { 155 fp->ire = NULL; 156 IRE_REFRELE_NOTR(ire); 157 } 158 } 159 WAKE_SCTP(sctp); 160 sctp_prev = sctp; 161 mutex_enter(&sctp_g_lock); 162 sctp = list_next(&sctp_g_list, sctp); 163 } 164 mutex_exit(&sctp_g_lock); 165 if (sctp_prev != NULL) 166 SCTP_REFRELE(sctp_prev); 167 } 168 169 sctp_t * 170 sctp_conn_match(in6_addr_t *faddr, in6_addr_t *laddr, uint32_t ports, 171 uint_t ipif_seqid, zoneid_t zoneid) 172 { 173 sctp_tf_t *tf; 174 sctp_t *sctp; 175 sctp_faddr_t *fp; 176 177 tf = &(sctp_conn_fanout[SCTP_CONN_HASH(ports)]); 178 mutex_enter(&tf->tf_lock); 179 180 for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_conn_hash_next) { 181 if (ports != sctp->sctp_ports || (zoneid != ALL_ZONES && 182 zoneid != sctp->sctp_zoneid)) { 183 continue; 184 } 185 186 /* check for faddr match */ 187 for (fp = sctp->sctp_faddrs; fp; fp = fp->next) { 188 if (IN6_ARE_ADDR_EQUAL(faddr, &fp->faddr)) { 189 break; 190 } 191 } 192 193 if (!fp) { 194 /* no faddr match; keep looking */ 195 continue; 196 } 197 198 /* check for laddr match */ 199 if (ipif_seqid == 0) { 200 if (sctp_saddr_lookup(sctp, laddr) != NULL) { 201 SCTP_REFHOLD(sctp); 202 goto done; 203 } 204 } else { 205 if (sctp_ipif_lookup(sctp, ipif_seqid) != NULL) { 206 SCTP_REFHOLD(sctp); 207 goto done; 208 } 209 /* no match; continue to the next in the chain */ 210 } 211 } 212 213 done: 214 mutex_exit(&tf->tf_lock); 215 return (sctp); 216 } 217 218 static sctp_t * 219 listen_match(in6_addr_t *laddr, uint32_t ports, uint_t ipif_seqid, 220 zoneid_t zoneid) 221 { 222 sctp_t *sctp; 223 sctp_tf_t *tf; 224 uint16_t lport; 225 226 lport = ((uint16_t *)&ports)[1]; 227 228 tf = &(sctp_listen_fanout[SCTP_LISTEN_HASH(ntohs(lport))]); 229 mutex_enter(&tf->tf_lock); 230 231 for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_listen_hash_next) { 232 if (lport != sctp->sctp_lport || (zoneid != ALL_ZONES && 233 zoneid != sctp->sctp_zoneid)) { 234 continue; 235 } 236 237 if (ipif_seqid == 0) { 238 if (sctp_saddr_lookup(sctp, laddr) != NULL) { 239 SCTP_REFHOLD(sctp); 240 goto done; 241 } 242 } else { 243 if (sctp_ipif_lookup(sctp, ipif_seqid) != NULL) { 244 SCTP_REFHOLD(sctp); 245 goto done; 246 } 247 } 248 /* no match; continue to the next in the chain */ 249 } 250 251 done: 252 mutex_exit(&tf->tf_lock); 253 return (sctp); 254 } 255 256 conn_t * 257 sctp_find_conn(in6_addr_t *src, in6_addr_t *dst, uint32_t ports, 258 uint_t ipif_seqid, zoneid_t zoneid) 259 { 260 sctp_t *sctp; 261 262 if ((sctp = sctp_conn_match(src, dst, ports, ipif_seqid, 263 zoneid)) == NULL) { 264 /* Not in conn fanout; check listen fanout */ 265 if ((sctp = listen_match(dst, ports, ipif_seqid, 266 zoneid)) == NULL) { 267 return (NULL); 268 } 269 } 270 return (sctp->sctp_connp); 271 } 272 273 /* 274 * Fanout for SCTP packets 275 * The caller puts <fport, lport> in the ports parameter. 276 */ 277 /* ARGSUSED */ 278 void 279 ip_fanout_sctp(mblk_t *mp, ill_t *recv_ill, ipha_t *ipha, 280 uint32_t ports, uint_t flags, boolean_t mctl_present, boolean_t ip_policy, 281 uint_t ipif_seqid, zoneid_t zoneid) 282 { 283 sctp_t *sctp; 284 boolean_t isv4; 285 conn_t *connp; 286 mblk_t *first_mp; 287 ip6_t *ip6h; 288 in6_addr_t map_src, map_dst; 289 in6_addr_t *src, *dst; 290 291 first_mp = mp; 292 if (mctl_present) { 293 mp = first_mp->b_cont; 294 ASSERT(mp != NULL); 295 } 296 297 /* Assume IP provides aligned packets - otherwise toss */ 298 if (!OK_32PTR(mp->b_rptr)) { 299 BUMP_MIB(&ip_mib, ipInDiscards); 300 freemsg(first_mp); 301 return; 302 } 303 304 if (IPH_HDR_VERSION(ipha) == IPV6_VERSION) { 305 ip6h = (ip6_t *)ipha; 306 src = &ip6h->ip6_src; 307 dst = &ip6h->ip6_dst; 308 isv4 = B_FALSE; 309 } else { 310 ip6h = NULL; 311 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &map_src); 312 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &map_dst); 313 src = &map_src; 314 dst = &map_dst; 315 isv4 = B_TRUE; 316 } 317 if ((connp = sctp_find_conn(src, dst, ports, ipif_seqid, zoneid)) == 318 NULL) { 319 ip_fanout_sctp_raw(mp, recv_ill, ipha, isv4, 320 ports, mctl_present, flags, ip_policy, 321 ipif_seqid, zoneid); 322 return; 323 } 324 sctp = CONN2SCTP(connp); 325 326 /* Found a client; up it goes */ 327 BUMP_MIB(&ip_mib, ipInDelivers); 328 329 /* 330 * We check some fields in conn_t without holding a lock. 331 * This should be fine. 332 */ 333 if (CONN_INBOUND_POLICY_PRESENT(connp) || mctl_present) { 334 first_mp = ipsec_check_inbound_policy(first_mp, connp, 335 ipha, NULL, mctl_present); 336 if (first_mp == NULL) { 337 SCTP_REFRELE(sctp); 338 return; 339 } 340 } 341 342 /* Initiate IPPF processing for fastpath */ 343 if (IPP_ENABLED(IPP_LOCAL_IN)) { 344 ip_process(IPP_LOCAL_IN, &mp, 345 recv_ill->ill_phyint->phyint_ifindex); 346 if (mp == NULL) { 347 SCTP_REFRELE(sctp); 348 if (mctl_present) 349 freeb(first_mp); 350 return; 351 } else if (mctl_present) { 352 /* 353 * ip_process might return a new mp. 354 */ 355 ASSERT(first_mp != mp); 356 first_mp->b_cont = mp; 357 } else { 358 first_mp = mp; 359 } 360 } 361 362 if (connp->conn_recvif || connp->conn_recvslla || 363 connp->conn_ipv6_recvpktinfo) { 364 int in_flags = 0; 365 366 if (connp->conn_recvif || connp->conn_ipv6_recvpktinfo) { 367 in_flags = IPF_RECVIF; 368 } 369 if (connp->conn_recvslla) { 370 in_flags |= IPF_RECVSLLA; 371 } 372 if (isv4) { 373 mp = ip_add_info(mp, recv_ill, in_flags); 374 } else { 375 mp = ip_add_info_v6(mp, recv_ill, &ip6h->ip6_dst); 376 } 377 if (mp == NULL) { 378 SCTP_REFRELE(sctp); 379 if (mctl_present) 380 freeb(first_mp); 381 return; 382 } else if (mctl_present) { 383 /* 384 * ip_add_info might return a new mp. 385 */ 386 ASSERT(first_mp != mp); 387 first_mp->b_cont = mp; 388 } else { 389 first_mp = mp; 390 } 391 } 392 393 mutex_enter(&sctp->sctp_lock); 394 if (sctp->sctp_running) { 395 if (mctl_present) 396 mp->b_prev = first_mp; 397 if (!sctp_add_recvq(sctp, mp, B_FALSE)) { 398 BUMP_MIB(&ip_mib, ipInDiscards); 399 freemsg(first_mp); 400 } 401 mutex_exit(&sctp->sctp_lock); 402 } else { 403 sctp->sctp_running = B_TRUE; 404 mutex_exit(&sctp->sctp_lock); 405 406 mutex_enter(&sctp->sctp_recvq_lock); 407 if (sctp->sctp_recvq != NULL) { 408 if (mctl_present) 409 mp->b_prev = first_mp; 410 if (!sctp_add_recvq(sctp, mp, B_TRUE)) { 411 BUMP_MIB(&ip_mib, ipInDiscards); 412 freemsg(first_mp); 413 } 414 mutex_exit(&sctp->sctp_recvq_lock); 415 WAKE_SCTP(sctp); 416 } else { 417 mutex_exit(&sctp->sctp_recvq_lock); 418 sctp_input_data(sctp, mp, (mctl_present ? first_mp : 419 NULL)); 420 WAKE_SCTP(sctp); 421 sctp_process_sendq(sctp); 422 } 423 } 424 SCTP_REFRELE(sctp); 425 } 426 427 void 428 sctp_conn_hash_remove(sctp_t *sctp) 429 { 430 sctp_tf_t *tf = sctp->sctp_conn_tfp; 431 432 if (!tf) { 433 return; 434 } 435 mutex_enter(&tf->tf_lock); 436 ASSERT(tf->tf_sctp); 437 if (tf->tf_sctp == sctp) { 438 tf->tf_sctp = sctp->sctp_conn_hash_next; 439 if (sctp->sctp_conn_hash_next) { 440 ASSERT(tf->tf_sctp->sctp_conn_hash_prev == sctp); 441 tf->tf_sctp->sctp_conn_hash_prev = NULL; 442 } 443 } else { 444 ASSERT(sctp->sctp_conn_hash_prev); 445 ASSERT(sctp->sctp_conn_hash_prev->sctp_conn_hash_next == sctp); 446 sctp->sctp_conn_hash_prev->sctp_conn_hash_next = 447 sctp->sctp_conn_hash_next; 448 449 if (sctp->sctp_conn_hash_next) { 450 ASSERT(sctp->sctp_conn_hash_next->sctp_conn_hash_prev 451 == sctp); 452 sctp->sctp_conn_hash_next->sctp_conn_hash_prev = 453 sctp->sctp_conn_hash_prev; 454 } 455 } 456 sctp->sctp_conn_hash_next = NULL; 457 sctp->sctp_conn_hash_prev = NULL; 458 sctp->sctp_conn_tfp = NULL; 459 mutex_exit(&tf->tf_lock); 460 } 461 462 void 463 sctp_conn_hash_insert(sctp_tf_t *tf, sctp_t *sctp, int caller_holds_lock) 464 { 465 if (sctp->sctp_conn_tfp) { 466 sctp_conn_hash_remove(sctp); 467 } 468 469 if (!caller_holds_lock) { 470 mutex_enter(&tf->tf_lock); 471 } else { 472 ASSERT(MUTEX_HELD(&tf->tf_lock)); 473 } 474 475 sctp->sctp_conn_hash_next = tf->tf_sctp; 476 if (tf->tf_sctp) { 477 tf->tf_sctp->sctp_conn_hash_prev = sctp; 478 } 479 sctp->sctp_conn_hash_prev = NULL; 480 tf->tf_sctp = sctp; 481 sctp->sctp_conn_tfp = tf; 482 if (!caller_holds_lock) { 483 mutex_exit(&tf->tf_lock); 484 } 485 } 486 487 void 488 sctp_listen_hash_remove(sctp_t *sctp) 489 { 490 sctp_tf_t *tf = sctp->sctp_listen_tfp; 491 492 if (!tf) { 493 return; 494 } 495 496 mutex_enter(&tf->tf_lock); 497 ASSERT(tf->tf_sctp); 498 if (tf->tf_sctp == sctp) { 499 tf->tf_sctp = sctp->sctp_listen_hash_next; 500 if (sctp->sctp_listen_hash_next) { 501 ASSERT(tf->tf_sctp->sctp_listen_hash_prev == sctp); 502 tf->tf_sctp->sctp_listen_hash_prev = NULL; 503 } 504 } else { 505 ASSERT(sctp->sctp_listen_hash_prev); 506 ASSERT(sctp->sctp_listen_hash_prev->sctp_listen_hash_next == 507 sctp); 508 sctp->sctp_listen_hash_prev->sctp_listen_hash_next = 509 sctp->sctp_listen_hash_next; 510 511 if (sctp->sctp_listen_hash_next) { 512 ASSERT( 513 sctp->sctp_listen_hash_next->sctp_listen_hash_prev == 514 sctp); 515 sctp->sctp_listen_hash_next->sctp_listen_hash_prev = 516 sctp->sctp_listen_hash_prev; 517 } 518 } 519 sctp->sctp_listen_hash_next = NULL; 520 sctp->sctp_listen_hash_prev = NULL; 521 sctp->sctp_listen_tfp = NULL; 522 mutex_exit(&tf->tf_lock); 523 } 524 525 void 526 sctp_listen_hash_insert(sctp_tf_t *tf, sctp_t *sctp) 527 { 528 if (sctp->sctp_listen_tfp) { 529 sctp_listen_hash_remove(sctp); 530 } 531 532 mutex_enter(&tf->tf_lock); 533 sctp->sctp_listen_hash_next = tf->tf_sctp; 534 if (tf->tf_sctp) { 535 tf->tf_sctp->sctp_listen_hash_prev = sctp; 536 } 537 sctp->sctp_listen_hash_prev = NULL; 538 tf->tf_sctp = sctp; 539 sctp->sctp_listen_tfp = tf; 540 mutex_exit(&tf->tf_lock); 541 } 542 543 /* 544 * Hash list insertion routine for sctp_t structures. 545 * Inserts entries with the ones bound to a specific IP address first 546 * followed by those bound to INADDR_ANY. 547 */ 548 void 549 sctp_bind_hash_insert(sctp_tf_t *tbf, sctp_t *sctp, int caller_holds_lock) 550 { 551 sctp_t **sctpp; 552 sctp_t *sctpnext; 553 554 if (sctp->sctp_ptpbhn != NULL) { 555 ASSERT(!caller_holds_lock); 556 sctp_bind_hash_remove(sctp); 557 } 558 sctpp = &tbf->tf_sctp; 559 if (!caller_holds_lock) { 560 mutex_enter(&tbf->tf_lock); 561 } else { 562 ASSERT(MUTEX_HELD(&tbf->tf_lock)); 563 } 564 sctpnext = sctpp[0]; 565 if (sctpnext) { 566 sctpnext->sctp_ptpbhn = &sctp->sctp_bind_hash; 567 } 568 sctp->sctp_bind_hash = sctpnext; 569 sctp->sctp_ptpbhn = sctpp; 570 sctpp[0] = sctp; 571 /* For sctp_*_hash_remove */ 572 sctp->sctp_bind_lockp = &tbf->tf_lock; 573 if (!caller_holds_lock) 574 mutex_exit(&tbf->tf_lock); 575 } 576 577 /* 578 * Hash list removal routine for sctp_t structures. 579 */ 580 void 581 sctp_bind_hash_remove(sctp_t *sctp) 582 { 583 sctp_t *sctpnext; 584 kmutex_t *lockp; 585 586 lockp = sctp->sctp_bind_lockp; 587 588 if (sctp->sctp_ptpbhn == NULL) 589 return; 590 591 ASSERT(lockp != NULL); 592 mutex_enter(lockp); 593 if (sctp->sctp_ptpbhn) { 594 sctpnext = sctp->sctp_bind_hash; 595 if (sctpnext) { 596 sctpnext->sctp_ptpbhn = sctp->sctp_ptpbhn; 597 sctp->sctp_bind_hash = NULL; 598 } 599 *sctp->sctp_ptpbhn = sctpnext; 600 sctp->sctp_ptpbhn = NULL; 601 } 602 mutex_exit(lockp); 603 sctp->sctp_bind_lockp = NULL; 604 } 605 606 /* 607 * Similar to but more general than ip_sctp's conn_match(). 608 * 609 * Matches sets of addresses as follows: if the argument addr set is 610 * a complete subset of the corresponding addr set in the sctp_t, it 611 * is a match. 612 * 613 * Caller must hold tf->tf_lock. 614 * 615 * Returns with a SCTP_REFHOLD sctp structure. Caller must do a SCTP_REFRELE. 616 */ 617 sctp_t * 618 sctp_lookup(sctp_t *sctp1, in6_addr_t *faddr, sctp_tf_t *tf, uint32_t *ports, 619 int min_state) 620 { 621 622 sctp_t *sctp; 623 sctp_faddr_t *fp; 624 625 ASSERT(MUTEX_HELD(&tf->tf_lock)); 626 627 for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_conn_hash_next) { 628 if (*ports != sctp->sctp_ports || sctp->sctp_state < 629 min_state) { 630 continue; 631 } 632 633 /* check for faddr match */ 634 for (fp = sctp->sctp_faddrs; fp; fp = fp->next) { 635 if (IN6_ARE_ADDR_EQUAL(faddr, &fp->faddr)) { 636 break; 637 } 638 } 639 640 if (!fp) { 641 /* no faddr match; keep looking */ 642 continue; 643 } 644 645 /* check for laddr subset match */ 646 if (sctp_compare_saddrs(sctp1, sctp) <= SCTP_ADDR_SUBSET) { 647 goto done; 648 } 649 650 /* no match; continue searching */ 651 } 652 653 done: 654 if (sctp) { 655 SCTP_REFHOLD(sctp); 656 } 657 return (sctp); 658 } 659 660 boolean_t 661 ip_fanout_sctp_raw_match(conn_t *connp, uint32_t ports, ipha_t *ipha) 662 { 663 uint16_t lport; 664 665 if (connp->conn_fully_bound) { 666 return (IPCL_CONN_MATCH(connp, IPPROTO_SCTP, ipha->ipha_src, 667 ipha->ipha_dst, ports)); 668 } else { 669 lport = htons(ntohl(ports) & 0xFFFF); 670 return (IPCL_BIND_MATCH(connp, IPPROTO_SCTP, ipha->ipha_dst, 671 lport)); 672 } 673 } 674 675 boolean_t 676 ip_fanout_sctp_raw_match_v6(conn_t *connp, uint32_t ports, ip6_t *ip6h, 677 boolean_t for_v4) 678 { 679 uint16_t lport; 680 in6_addr_t v6dst; 681 682 if (!for_v4 && connp->conn_fully_bound) { 683 return (IPCL_CONN_MATCH_V6(connp, IPPROTO_SCTP, ip6h->ip6_src, 684 ip6h->ip6_dst, ports)); 685 } else { 686 lport = htons(ntohl(ports) & 0xFFFF); 687 if (for_v4) 688 v6dst = ipv6_all_zeros; 689 else 690 v6dst = ip6h->ip6_dst; 691 return (IPCL_BIND_MATCH_V6(connp, IPPROTO_SCTP, v6dst, lport)); 692 } 693 } 694