10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51676Sjpk * Common Development and Distribution License (the "License"). 61676Sjpk * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate 220Sstevel@tonic-gate /* 23*11042SErik.Nordmark@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #include <sys/socket.h> 280Sstevel@tonic-gate #include <sys/ddi.h> 290Sstevel@tonic-gate #include <sys/sunddi.h> 301676Sjpk #include <sys/tsol/tndb.h> 311676Sjpk #include <sys/tsol/tnet.h> 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <netinet/in.h> 340Sstevel@tonic-gate #include <netinet/ip6.h> 350Sstevel@tonic-gate 360Sstevel@tonic-gate #include <inet/common.h> 370Sstevel@tonic-gate #include <inet/ip.h> 380Sstevel@tonic-gate #include <inet/ip6.h> 390Sstevel@tonic-gate #include <inet/ipclassifier.h> 400Sstevel@tonic-gate #include <inet/ipsec_impl.h> 410Sstevel@tonic-gate #include <inet/ipp_common.h> 420Sstevel@tonic-gate #include <inet/sctp_ip.h> 430Sstevel@tonic-gate 440Sstevel@tonic-gate #include "sctp_impl.h" 450Sstevel@tonic-gate #include "sctp_addr.h" 460Sstevel@tonic-gate 470Sstevel@tonic-gate /* Default association hash size. The size must be a power of 2. */ 480Sstevel@tonic-gate #define SCTP_CONN_HASH_SIZE 8192 490Sstevel@tonic-gate 503448Sdh155122 uint_t sctp_conn_hash_size = SCTP_CONN_HASH_SIZE; /* /etc/system */ 510Sstevel@tonic-gate 52852Svi117747 /* 53852Svi117747 * Cluster networking hook for traversing current assoc list. 54852Svi117747 * This routine is used to extract the current list of live associations 55852Svi117747 * which must continue to to be dispatched to this node. 56852Svi117747 */ 57852Svi117747 int cl_sctp_walk_list(int (*cl_callback)(cl_sctp_info_t *, void *), void *, 58852Svi117747 boolean_t); 593448Sdh155122 static int cl_sctp_walk_list_stack(int (*cl_callback)(cl_sctp_info_t *, 603448Sdh155122 void *), void *arg, boolean_t cansleep, sctp_stack_t *sctps); 61852Svi117747 620Sstevel@tonic-gate void 633448Sdh155122 sctp_hash_init(sctp_stack_t *sctps) 640Sstevel@tonic-gate { 650Sstevel@tonic-gate int i; 660Sstevel@tonic-gate 673448Sdh155122 /* Start with /etc/system value */ 683448Sdh155122 sctps->sctps_conn_hash_size = sctp_conn_hash_size; 693448Sdh155122 703448Sdh155122 if (sctps->sctps_conn_hash_size & (sctps->sctps_conn_hash_size - 1)) { 710Sstevel@tonic-gate /* Not a power of two. Round up to nearest power of two */ 720Sstevel@tonic-gate for (i = 0; i < 31; i++) { 733448Sdh155122 if (sctps->sctps_conn_hash_size < (1 << i)) 740Sstevel@tonic-gate break; 750Sstevel@tonic-gate } 763448Sdh155122 sctps->sctps_conn_hash_size = 1 << i; 770Sstevel@tonic-gate } 783448Sdh155122 if (sctps->sctps_conn_hash_size < SCTP_CONN_HASH_SIZE) { 793448Sdh155122 sctps->sctps_conn_hash_size = SCTP_CONN_HASH_SIZE; 800Sstevel@tonic-gate cmn_err(CE_CONT, "using sctp_conn_hash_size = %u\n", 813448Sdh155122 sctps->sctps_conn_hash_size); 820Sstevel@tonic-gate } 833448Sdh155122 sctps->sctps_conn_fanout = 847480SKacheong.Poon@Sun.COM (sctp_tf_t *)kmem_zalloc(sctps->sctps_conn_hash_size * 85*11042SErik.Nordmark@Sun.COM sizeof (sctp_tf_t), KM_SLEEP); 863448Sdh155122 for (i = 0; i < sctps->sctps_conn_hash_size; i++) { 873448Sdh155122 mutex_init(&sctps->sctps_conn_fanout[i].tf_lock, NULL, 887480SKacheong.Poon@Sun.COM MUTEX_DEFAULT, NULL); 890Sstevel@tonic-gate } 903448Sdh155122 sctps->sctps_listen_fanout = kmem_zalloc(SCTP_LISTEN_FANOUT_SIZE * 913448Sdh155122 sizeof (sctp_tf_t), KM_SLEEP); 923448Sdh155122 for (i = 0; i < SCTP_LISTEN_FANOUT_SIZE; i++) { 933448Sdh155122 mutex_init(&sctps->sctps_listen_fanout[i].tf_lock, NULL, 940Sstevel@tonic-gate MUTEX_DEFAULT, NULL); 950Sstevel@tonic-gate } 963448Sdh155122 sctps->sctps_bind_fanout = kmem_zalloc(SCTP_BIND_FANOUT_SIZE * 973448Sdh155122 sizeof (sctp_tf_t), KM_SLEEP); 983448Sdh155122 for (i = 0; i < SCTP_BIND_FANOUT_SIZE; i++) { 993448Sdh155122 mutex_init(&sctps->sctps_bind_fanout[i].tf_lock, NULL, 1000Sstevel@tonic-gate MUTEX_DEFAULT, NULL); 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate } 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate void 1053448Sdh155122 sctp_hash_destroy(sctp_stack_t *sctps) 1060Sstevel@tonic-gate { 1070Sstevel@tonic-gate int i; 1080Sstevel@tonic-gate 1093448Sdh155122 for (i = 0; i < sctps->sctps_conn_hash_size; i++) { 1103448Sdh155122 mutex_destroy(&sctps->sctps_conn_fanout[i].tf_lock); 1113448Sdh155122 } 1123448Sdh155122 kmem_free(sctps->sctps_conn_fanout, sctps->sctps_conn_hash_size * 1133448Sdh155122 sizeof (sctp_tf_t)); 1143448Sdh155122 sctps->sctps_conn_fanout = NULL; 1153448Sdh155122 1163448Sdh155122 for (i = 0; i < SCTP_LISTEN_FANOUT_SIZE; i++) { 1173448Sdh155122 mutex_destroy(&sctps->sctps_listen_fanout[i].tf_lock); 1180Sstevel@tonic-gate } 1193448Sdh155122 kmem_free(sctps->sctps_listen_fanout, SCTP_LISTEN_FANOUT_SIZE * 1203448Sdh155122 sizeof (sctp_tf_t)); 1213448Sdh155122 sctps->sctps_listen_fanout = NULL; 1223448Sdh155122 1233448Sdh155122 for (i = 0; i < SCTP_BIND_FANOUT_SIZE; i++) { 1243448Sdh155122 mutex_destroy(&sctps->sctps_bind_fanout[i].tf_lock); 1250Sstevel@tonic-gate } 1263448Sdh155122 kmem_free(sctps->sctps_bind_fanout, SCTP_BIND_FANOUT_SIZE * 1273448Sdh155122 sizeof (sctp_tf_t)); 1283448Sdh155122 sctps->sctps_bind_fanout = NULL; 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate 1311932Svi117747 /* 132852Svi117747 * Exported routine for extracting active SCTP associations. 133852Svi117747 * Like TCP, we terminate the walk if the callback returns non-zero. 1343448Sdh155122 * 1353448Sdh155122 * Need to walk all sctp_stack_t instances since this clustering 1363448Sdh155122 * interface is assumed global for all instances 137852Svi117747 */ 138852Svi117747 int 1393448Sdh155122 cl_sctp_walk_list(int (*cl_callback)(cl_sctp_info_t *, void *), 1403448Sdh155122 void *arg, boolean_t cansleep) 1413448Sdh155122 { 1423448Sdh155122 netstack_handle_t nh; 1433448Sdh155122 netstack_t *ns; 1443448Sdh155122 int ret = 0; 1453448Sdh155122 1463448Sdh155122 netstack_next_init(&nh); 1473448Sdh155122 while ((ns = netstack_next(&nh)) != NULL) { 1483448Sdh155122 ret = cl_sctp_walk_list_stack(cl_callback, arg, cansleep, 1493448Sdh155122 ns->netstack_sctp); 1503448Sdh155122 netstack_rele(ns); 1513448Sdh155122 } 1523448Sdh155122 netstack_next_fini(&nh); 1533448Sdh155122 return (ret); 1543448Sdh155122 } 1553448Sdh155122 1563448Sdh155122 static int 1573448Sdh155122 cl_sctp_walk_list_stack(int (*cl_callback)(cl_sctp_info_t *, void *), 1583448Sdh155122 void *arg, boolean_t cansleep, sctp_stack_t *sctps) 159852Svi117747 { 160852Svi117747 sctp_t *sctp; 161852Svi117747 sctp_t *sctp_prev; 162852Svi117747 cl_sctp_info_t cl_sctpi; 163852Svi117747 uchar_t *slist; 164852Svi117747 uchar_t *flist; 165852Svi117747 166852Svi117747 sctp_prev = NULL; 1673448Sdh155122 mutex_enter(&sctps->sctps_g_lock); 168*11042SErik.Nordmark@Sun.COM sctp = list_head(&sctps->sctps_g_list); 169852Svi117747 while (sctp != NULL) { 170852Svi117747 size_t ssize; 171852Svi117747 size_t fsize; 172852Svi117747 173852Svi117747 mutex_enter(&sctp->sctp_reflock); 174852Svi117747 if (sctp->sctp_condemned || sctp->sctp_state <= SCTPS_LISTEN) { 175852Svi117747 mutex_exit(&sctp->sctp_reflock); 1763448Sdh155122 sctp = list_next(&sctps->sctps_g_list, sctp); 177852Svi117747 continue; 178852Svi117747 } 179852Svi117747 sctp->sctp_refcnt++; 180852Svi117747 mutex_exit(&sctp->sctp_reflock); 1813448Sdh155122 mutex_exit(&sctps->sctps_g_lock); 182852Svi117747 if (sctp_prev != NULL) 183852Svi117747 SCTP_REFRELE(sctp_prev); 184852Svi117747 RUN_SCTP(sctp); 185852Svi117747 ssize = sizeof (in6_addr_t) * sctp->sctp_nsaddrs; 186852Svi117747 fsize = sizeof (in6_addr_t) * sctp->sctp_nfaddrs; 187852Svi117747 188852Svi117747 slist = kmem_alloc(ssize, cansleep ? KM_SLEEP : KM_NOSLEEP); 189852Svi117747 flist = kmem_alloc(fsize, cansleep ? KM_SLEEP : KM_NOSLEEP); 190852Svi117747 if (slist == NULL || flist == NULL) { 191852Svi117747 WAKE_SCTP(sctp); 192852Svi117747 if (slist != NULL) 193852Svi117747 kmem_free(slist, ssize); 194852Svi117747 if (flist != NULL) 195852Svi117747 kmem_free(flist, fsize); 196852Svi117747 SCTP_REFRELE(sctp); 197852Svi117747 return (1); 198852Svi117747 } 199852Svi117747 cl_sctpi.cl_sctpi_version = CL_SCTPI_V1; 200852Svi117747 sctp_get_saddr_list(sctp, slist, ssize); 201852Svi117747 sctp_get_faddr_list(sctp, flist, fsize); 202852Svi117747 cl_sctpi.cl_sctpi_nladdr = sctp->sctp_nsaddrs; 203852Svi117747 cl_sctpi.cl_sctpi_nfaddr = sctp->sctp_nfaddrs; 204*11042SErik.Nordmark@Sun.COM cl_sctpi.cl_sctpi_family = sctp->sctp_connp->conn_family; 205*11042SErik.Nordmark@Sun.COM if (cl_sctpi.cl_sctpi_family == AF_INET) 206*11042SErik.Nordmark@Sun.COM cl_sctpi.cl_sctpi_ipversion = IPV4_VERSION; 207*11042SErik.Nordmark@Sun.COM else 208*11042SErik.Nordmark@Sun.COM cl_sctpi.cl_sctpi_ipversion = IPV6_VERSION; 209852Svi117747 cl_sctpi.cl_sctpi_state = sctp->sctp_state; 210*11042SErik.Nordmark@Sun.COM cl_sctpi.cl_sctpi_lport = sctp->sctp_connp->conn_lport; 211*11042SErik.Nordmark@Sun.COM cl_sctpi.cl_sctpi_fport = sctp->sctp_connp->conn_fport; 212852Svi117747 cl_sctpi.cl_sctpi_handle = (cl_sctp_handle_t)sctp; 213852Svi117747 WAKE_SCTP(sctp); 214852Svi117747 cl_sctpi.cl_sctpi_laddrp = slist; 215852Svi117747 cl_sctpi.cl_sctpi_faddrp = flist; 216852Svi117747 if ((*cl_callback)(&cl_sctpi, arg) != 0) { 217852Svi117747 kmem_free(slist, ssize); 218852Svi117747 kmem_free(flist, fsize); 219852Svi117747 SCTP_REFRELE(sctp); 220852Svi117747 return (1); 221852Svi117747 } 222852Svi117747 /* list will be freed by cl_callback */ 223852Svi117747 sctp_prev = sctp; 2243448Sdh155122 mutex_enter(&sctps->sctps_g_lock); 2253448Sdh155122 sctp = list_next(&sctps->sctps_g_list, sctp); 226852Svi117747 } 2273448Sdh155122 mutex_exit(&sctps->sctps_g_lock); 228852Svi117747 if (sctp_prev != NULL) 229852Svi117747 SCTP_REFRELE(sctp_prev); 230852Svi117747 return (0); 231852Svi117747 } 232852Svi117747 2330Sstevel@tonic-gate sctp_t * 2340Sstevel@tonic-gate sctp_conn_match(in6_addr_t *faddr, in6_addr_t *laddr, uint32_t ports, 235*11042SErik.Nordmark@Sun.COM zoneid_t zoneid, iaflags_t iraflags, sctp_stack_t *sctps) 2360Sstevel@tonic-gate { 2370Sstevel@tonic-gate sctp_tf_t *tf; 2380Sstevel@tonic-gate sctp_t *sctp; 2390Sstevel@tonic-gate sctp_faddr_t *fp; 240*11042SErik.Nordmark@Sun.COM conn_t *connp; 2410Sstevel@tonic-gate 2423448Sdh155122 tf = &(sctps->sctps_conn_fanout[SCTP_CONN_HASH(sctps, ports)]); 2430Sstevel@tonic-gate mutex_enter(&tf->tf_lock); 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_conn_hash_next) { 246*11042SErik.Nordmark@Sun.COM connp = sctp->sctp_connp; 247*11042SErik.Nordmark@Sun.COM if (ports != connp->conn_ports) 2480Sstevel@tonic-gate continue; 249*11042SErik.Nordmark@Sun.COM if (!(connp->conn_zoneid == zoneid || 250*11042SErik.Nordmark@Sun.COM connp->conn_allzones || 251*11042SErik.Nordmark@Sun.COM ((connp->conn_mac_mode != CONN_MAC_DEFAULT) && 252*11042SErik.Nordmark@Sun.COM (iraflags & IRAF_TX_MAC_EXEMPTABLE) && 253*11042SErik.Nordmark@Sun.COM (iraflags & IRAF_TX_SHARED_ADDR)))) 254*11042SErik.Nordmark@Sun.COM continue; 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate /* check for faddr match */ 2570Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp; fp = fp->next) { 2580Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(faddr, &fp->faddr)) { 2590Sstevel@tonic-gate break; 2600Sstevel@tonic-gate } 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2633510Svi117747 /* no faddr match; keep looking */ 2643510Svi117747 if (fp == NULL) 2650Sstevel@tonic-gate continue; 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate /* check for laddr match */ 2683510Svi117747 if (sctp_saddr_lookup(sctp, laddr, 0) != NULL) { 2693510Svi117747 SCTP_REFHOLD(sctp); 2703510Svi117747 goto done; 2713510Svi117747 } 2720Sstevel@tonic-gate /* no match; continue to the next in the chain */ 2730Sstevel@tonic-gate } 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate done: 2760Sstevel@tonic-gate mutex_exit(&tf->tf_lock); 2770Sstevel@tonic-gate return (sctp); 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate static sctp_t * 2813510Svi117747 listen_match(in6_addr_t *laddr, uint32_t ports, zoneid_t zoneid, 282*11042SErik.Nordmark@Sun.COM iaflags_t iraflags, sctp_stack_t *sctps) 2830Sstevel@tonic-gate { 2840Sstevel@tonic-gate sctp_t *sctp; 2850Sstevel@tonic-gate sctp_tf_t *tf; 2860Sstevel@tonic-gate uint16_t lport; 287*11042SErik.Nordmark@Sun.COM conn_t *connp; 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate lport = ((uint16_t *)&ports)[1]; 2900Sstevel@tonic-gate 2913448Sdh155122 tf = &(sctps->sctps_listen_fanout[SCTP_LISTEN_HASH(ntohs(lport))]); 2920Sstevel@tonic-gate mutex_enter(&tf->tf_lock); 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_listen_hash_next) { 295*11042SErik.Nordmark@Sun.COM connp = sctp->sctp_connp; 296*11042SErik.Nordmark@Sun.COM if (lport != connp->conn_lport) 2970Sstevel@tonic-gate continue; 298*11042SErik.Nordmark@Sun.COM 299*11042SErik.Nordmark@Sun.COM if (!(connp->conn_zoneid == zoneid || 300*11042SErik.Nordmark@Sun.COM connp->conn_allzones || 301*11042SErik.Nordmark@Sun.COM ((connp->conn_mac_mode != CONN_MAC_DEFAULT) && 302*11042SErik.Nordmark@Sun.COM (iraflags & IRAF_TX_MAC_EXEMPTABLE) && 303*11042SErik.Nordmark@Sun.COM (iraflags & IRAF_TX_SHARED_ADDR)))) 304*11042SErik.Nordmark@Sun.COM continue; 3050Sstevel@tonic-gate 3063510Svi117747 if (sctp_saddr_lookup(sctp, laddr, 0) != NULL) { 3073510Svi117747 SCTP_REFHOLD(sctp); 3083510Svi117747 goto done; 3090Sstevel@tonic-gate } 3100Sstevel@tonic-gate /* no match; continue to the next in the chain */ 3110Sstevel@tonic-gate } 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate done: 3140Sstevel@tonic-gate mutex_exit(&tf->tf_lock); 3150Sstevel@tonic-gate return (sctp); 3160Sstevel@tonic-gate } 3170Sstevel@tonic-gate 3181676Sjpk /* called by ipsec_sctp_pol */ 3190Sstevel@tonic-gate conn_t * 3200Sstevel@tonic-gate sctp_find_conn(in6_addr_t *src, in6_addr_t *dst, uint32_t ports, 321*11042SErik.Nordmark@Sun.COM zoneid_t zoneid, iaflags_t iraflags, sctp_stack_t *sctps) 3220Sstevel@tonic-gate { 3230Sstevel@tonic-gate sctp_t *sctp; 3240Sstevel@tonic-gate 325*11042SErik.Nordmark@Sun.COM sctp = sctp_conn_match(src, dst, ports, zoneid, iraflags, sctps); 326*11042SErik.Nordmark@Sun.COM if (sctp == NULL) { 3270Sstevel@tonic-gate /* Not in conn fanout; check listen fanout */ 328*11042SErik.Nordmark@Sun.COM sctp = listen_match(dst, ports, zoneid, iraflags, sctps); 329*11042SErik.Nordmark@Sun.COM if (sctp == NULL) 3300Sstevel@tonic-gate return (NULL); 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate return (sctp->sctp_connp); 3330Sstevel@tonic-gate } 3340Sstevel@tonic-gate 335*11042SErik.Nordmark@Sun.COM /* 336*11042SErik.Nordmark@Sun.COM * Fanout to a sctp instance. 337*11042SErik.Nordmark@Sun.COM */ 3381676Sjpk conn_t * 3391676Sjpk sctp_fanout(in6_addr_t *src, in6_addr_t *dst, uint32_t ports, 340*11042SErik.Nordmark@Sun.COM ip_recv_attr_t *ira, mblk_t *mp, sctp_stack_t *sctps) 3411676Sjpk { 342*11042SErik.Nordmark@Sun.COM zoneid_t zoneid = ira->ira_zoneid; 343*11042SErik.Nordmark@Sun.COM iaflags_t iraflags = ira->ira_flags; 3441676Sjpk sctp_t *sctp; 3451676Sjpk 346*11042SErik.Nordmark@Sun.COM sctp = sctp_conn_match(src, dst, ports, zoneid, iraflags, sctps); 347*11042SErik.Nordmark@Sun.COM if (sctp == NULL) { 3481676Sjpk /* Not in conn fanout; check listen fanout */ 349*11042SErik.Nordmark@Sun.COM sctp = listen_match(dst, ports, zoneid, iraflags, sctps); 350*11042SErik.Nordmark@Sun.COM if (sctp == NULL) 3511676Sjpk return (NULL); 3522776Skp158701 /* 3532776Skp158701 * On systems running trusted extensions, check if dst 3542776Skp158701 * should accept the packet. "IPV6_VERSION" indicates 3552776Skp158701 * that dst is in 16 byte AF_INET6 format. IPv4-mapped 3562776Skp158701 * IPv6 addresses are supported. 3572776Skp158701 */ 358*11042SErik.Nordmark@Sun.COM if ((iraflags & IRAF_SYSTEM_LABELED) && 359*11042SErik.Nordmark@Sun.COM !tsol_receive_local(mp, dst, IPV6_VERSION, ira, 360*11042SErik.Nordmark@Sun.COM sctp->sctp_connp)) { 3612776Skp158701 DTRACE_PROBE3( 3622776Skp158701 tx__ip__log__info__classify__sctp, 3632776Skp158701 char *, 3642776Skp158701 "connp(1) could not receive mp(2)", 3652776Skp158701 conn_t *, sctp->sctp_connp, mblk_t *, mp); 3662776Skp158701 SCTP_REFRELE(sctp); 3672776Skp158701 return (NULL); 3682776Skp158701 } 3691676Sjpk } 370*11042SErik.Nordmark@Sun.COM /* 371*11042SErik.Nordmark@Sun.COM * For labeled systems, there's no need to check the 372*11042SErik.Nordmark@Sun.COM * label here. It's known to be good as we checked 373*11042SErik.Nordmark@Sun.COM * before allowing the connection to become bound. 374*11042SErik.Nordmark@Sun.COM */ 3751676Sjpk return (sctp->sctp_connp); 3761676Sjpk } 3771676Sjpk 3780Sstevel@tonic-gate /* 379*11042SErik.Nordmark@Sun.COM * Fanout for ICMP errors for SCTP 3800Sstevel@tonic-gate * The caller puts <fport, lport> in the ports parameter. 3810Sstevel@tonic-gate */ 3820Sstevel@tonic-gate void 383*11042SErik.Nordmark@Sun.COM ip_fanout_sctp(mblk_t *mp, ipha_t *ipha, ip6_t *ip6h, uint32_t ports, 384*11042SErik.Nordmark@Sun.COM ip_recv_attr_t *ira) 3850Sstevel@tonic-gate { 386*11042SErik.Nordmark@Sun.COM sctp_t *sctp; 387*11042SErik.Nordmark@Sun.COM conn_t *connp; 388*11042SErik.Nordmark@Sun.COM in6_addr_t map_src, map_dst; 389*11042SErik.Nordmark@Sun.COM in6_addr_t *src, *dst; 390*11042SErik.Nordmark@Sun.COM boolean_t secure; 391*11042SErik.Nordmark@Sun.COM ill_t *ill = ira->ira_ill; 392*11042SErik.Nordmark@Sun.COM ip_stack_t *ipst = ill->ill_ipst; 393*11042SErik.Nordmark@Sun.COM netstack_t *ns = ipst->ips_netstack; 394*11042SErik.Nordmark@Sun.COM ipsec_stack_t *ipss = ns->netstack_ipsec; 395*11042SErik.Nordmark@Sun.COM sctp_stack_t *sctps = ns->netstack_sctp; 396*11042SErik.Nordmark@Sun.COM iaflags_t iraflags = ira->ira_flags; 397*11042SErik.Nordmark@Sun.COM ill_t *rill = ira->ira_rill; 3983448Sdh155122 399*11042SErik.Nordmark@Sun.COM ASSERT(iraflags & IRAF_ICMP_ERROR); 4000Sstevel@tonic-gate 401*11042SErik.Nordmark@Sun.COM secure = iraflags & IRAF_IPSEC_SECURE; 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate /* Assume IP provides aligned packets - otherwise toss */ 4040Sstevel@tonic-gate if (!OK_32PTR(mp->b_rptr)) { 405*11042SErik.Nordmark@Sun.COM BUMP_MIB(ill->ill_ip_mib, ipIfStatsInDiscards); 406*11042SErik.Nordmark@Sun.COM ip_drop_input("ipIfStatsInDiscards", mp, ill); 407*11042SErik.Nordmark@Sun.COM freemsg(mp); 4080Sstevel@tonic-gate return; 4090Sstevel@tonic-gate } 4100Sstevel@tonic-gate 411*11042SErik.Nordmark@Sun.COM if (!(iraflags & IRAF_IS_IPV4)) { 4120Sstevel@tonic-gate src = &ip6h->ip6_src; 4130Sstevel@tonic-gate dst = &ip6h->ip6_dst; 4140Sstevel@tonic-gate } else { 4150Sstevel@tonic-gate IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &map_src); 4160Sstevel@tonic-gate IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &map_dst); 4170Sstevel@tonic-gate src = &map_src; 4180Sstevel@tonic-gate dst = &map_dst; 4190Sstevel@tonic-gate } 420*11042SErik.Nordmark@Sun.COM connp = sctp_fanout(src, dst, ports, ira, mp, sctps); 4213448Sdh155122 if (connp == NULL) { 422*11042SErik.Nordmark@Sun.COM ip_fanout_sctp_raw(mp, ipha, ip6h, ports, ira); 4230Sstevel@tonic-gate return; 4240Sstevel@tonic-gate } 4250Sstevel@tonic-gate sctp = CONN2SCTP(connp); 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate /* 4280Sstevel@tonic-gate * We check some fields in conn_t without holding a lock. 4290Sstevel@tonic-gate * This should be fine. 4300Sstevel@tonic-gate */ 431*11042SErik.Nordmark@Sun.COM if (((iraflags & IRAF_IS_IPV4) ? 432*11042SErik.Nordmark@Sun.COM CONN_INBOUND_POLICY_PRESENT(connp, ipss) : 433*11042SErik.Nordmark@Sun.COM CONN_INBOUND_POLICY_PRESENT_V6(connp, ipss)) || 434*11042SErik.Nordmark@Sun.COM secure) { 435*11042SErik.Nordmark@Sun.COM mp = ipsec_check_inbound_policy(mp, connp, ipha, 436*11042SErik.Nordmark@Sun.COM ip6h, ira); 437*11042SErik.Nordmark@Sun.COM if (mp == NULL) { 4380Sstevel@tonic-gate SCTP_REFRELE(sctp); 4390Sstevel@tonic-gate return; 4400Sstevel@tonic-gate } 4410Sstevel@tonic-gate } 4420Sstevel@tonic-gate 443*11042SErik.Nordmark@Sun.COM ira->ira_ill = ira->ira_rill = NULL; 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate mutex_enter(&sctp->sctp_lock); 4460Sstevel@tonic-gate if (sctp->sctp_running) { 447*11042SErik.Nordmark@Sun.COM sctp_add_recvq(sctp, mp, B_FALSE, ira); 4480Sstevel@tonic-gate mutex_exit(&sctp->sctp_lock); 4490Sstevel@tonic-gate } else { 4500Sstevel@tonic-gate sctp->sctp_running = B_TRUE; 4510Sstevel@tonic-gate mutex_exit(&sctp->sctp_lock); 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate mutex_enter(&sctp->sctp_recvq_lock); 4540Sstevel@tonic-gate if (sctp->sctp_recvq != NULL) { 455*11042SErik.Nordmark@Sun.COM sctp_add_recvq(sctp, mp, B_TRUE, ira); 4560Sstevel@tonic-gate mutex_exit(&sctp->sctp_recvq_lock); 4570Sstevel@tonic-gate WAKE_SCTP(sctp); 4580Sstevel@tonic-gate } else { 4590Sstevel@tonic-gate mutex_exit(&sctp->sctp_recvq_lock); 460*11042SErik.Nordmark@Sun.COM if (ira->ira_flags & IRAF_ICMP_ERROR) { 461*11042SErik.Nordmark@Sun.COM sctp_icmp_error(sctp, mp); 462*11042SErik.Nordmark@Sun.COM } else { 463*11042SErik.Nordmark@Sun.COM sctp_input_data(sctp, mp, ira); 464*11042SErik.Nordmark@Sun.COM } 4650Sstevel@tonic-gate WAKE_SCTP(sctp); 4660Sstevel@tonic-gate } 4670Sstevel@tonic-gate } 4680Sstevel@tonic-gate SCTP_REFRELE(sctp); 469*11042SErik.Nordmark@Sun.COM ira->ira_ill = ill; 470*11042SErik.Nordmark@Sun.COM ira->ira_rill = rill; 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate void 4740Sstevel@tonic-gate sctp_conn_hash_remove(sctp_t *sctp) 4750Sstevel@tonic-gate { 4760Sstevel@tonic-gate sctp_tf_t *tf = sctp->sctp_conn_tfp; 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate if (!tf) { 4790Sstevel@tonic-gate return; 4800Sstevel@tonic-gate } 481852Svi117747 /* 482852Svi117747 * On a clustered note send this notification to the clustering 483852Svi117747 * subsystem. 484852Svi117747 */ 485852Svi117747 if (cl_sctp_disconnect != NULL) { 486*11042SErik.Nordmark@Sun.COM (*cl_sctp_disconnect)(sctp->sctp_connp->conn_family, 487852Svi117747 (cl_sctp_handle_t)sctp); 488852Svi117747 } 489852Svi117747 4900Sstevel@tonic-gate mutex_enter(&tf->tf_lock); 4910Sstevel@tonic-gate ASSERT(tf->tf_sctp); 4920Sstevel@tonic-gate if (tf->tf_sctp == sctp) { 4930Sstevel@tonic-gate tf->tf_sctp = sctp->sctp_conn_hash_next; 4940Sstevel@tonic-gate if (sctp->sctp_conn_hash_next) { 4950Sstevel@tonic-gate ASSERT(tf->tf_sctp->sctp_conn_hash_prev == sctp); 4960Sstevel@tonic-gate tf->tf_sctp->sctp_conn_hash_prev = NULL; 4970Sstevel@tonic-gate } 4980Sstevel@tonic-gate } else { 4990Sstevel@tonic-gate ASSERT(sctp->sctp_conn_hash_prev); 5000Sstevel@tonic-gate ASSERT(sctp->sctp_conn_hash_prev->sctp_conn_hash_next == sctp); 5010Sstevel@tonic-gate sctp->sctp_conn_hash_prev->sctp_conn_hash_next = 5020Sstevel@tonic-gate sctp->sctp_conn_hash_next; 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate if (sctp->sctp_conn_hash_next) { 5050Sstevel@tonic-gate ASSERT(sctp->sctp_conn_hash_next->sctp_conn_hash_prev 5060Sstevel@tonic-gate == sctp); 5070Sstevel@tonic-gate sctp->sctp_conn_hash_next->sctp_conn_hash_prev = 5080Sstevel@tonic-gate sctp->sctp_conn_hash_prev; 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate } 5110Sstevel@tonic-gate sctp->sctp_conn_hash_next = NULL; 5120Sstevel@tonic-gate sctp->sctp_conn_hash_prev = NULL; 5130Sstevel@tonic-gate sctp->sctp_conn_tfp = NULL; 5140Sstevel@tonic-gate mutex_exit(&tf->tf_lock); 5150Sstevel@tonic-gate } 5160Sstevel@tonic-gate 5170Sstevel@tonic-gate void 5180Sstevel@tonic-gate sctp_conn_hash_insert(sctp_tf_t *tf, sctp_t *sctp, int caller_holds_lock) 5190Sstevel@tonic-gate { 5200Sstevel@tonic-gate if (sctp->sctp_conn_tfp) { 5210Sstevel@tonic-gate sctp_conn_hash_remove(sctp); 5220Sstevel@tonic-gate } 5230Sstevel@tonic-gate 5240Sstevel@tonic-gate if (!caller_holds_lock) { 5250Sstevel@tonic-gate mutex_enter(&tf->tf_lock); 5260Sstevel@tonic-gate } else { 5270Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tf->tf_lock)); 5280Sstevel@tonic-gate } 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate sctp->sctp_conn_hash_next = tf->tf_sctp; 5310Sstevel@tonic-gate if (tf->tf_sctp) { 5320Sstevel@tonic-gate tf->tf_sctp->sctp_conn_hash_prev = sctp; 5330Sstevel@tonic-gate } 5340Sstevel@tonic-gate sctp->sctp_conn_hash_prev = NULL; 5350Sstevel@tonic-gate tf->tf_sctp = sctp; 5360Sstevel@tonic-gate sctp->sctp_conn_tfp = tf; 5370Sstevel@tonic-gate if (!caller_holds_lock) { 5380Sstevel@tonic-gate mutex_exit(&tf->tf_lock); 5390Sstevel@tonic-gate } 5400Sstevel@tonic-gate } 5410Sstevel@tonic-gate 5420Sstevel@tonic-gate void 5430Sstevel@tonic-gate sctp_listen_hash_remove(sctp_t *sctp) 5440Sstevel@tonic-gate { 5450Sstevel@tonic-gate sctp_tf_t *tf = sctp->sctp_listen_tfp; 546*11042SErik.Nordmark@Sun.COM conn_t *connp = sctp->sctp_connp; 5470Sstevel@tonic-gate 5480Sstevel@tonic-gate if (!tf) { 5490Sstevel@tonic-gate return; 5500Sstevel@tonic-gate } 551852Svi117747 /* 552852Svi117747 * On a clustered note send this notification to the clustering 553852Svi117747 * subsystem. 554852Svi117747 */ 555852Svi117747 if (cl_sctp_unlisten != NULL) { 556852Svi117747 uchar_t *slist; 557852Svi117747 ssize_t ssize; 558852Svi117747 559852Svi117747 ssize = sizeof (in6_addr_t) * sctp->sctp_nsaddrs; 560852Svi117747 slist = kmem_alloc(ssize, KM_SLEEP); 561852Svi117747 sctp_get_saddr_list(sctp, slist, ssize); 562*11042SErik.Nordmark@Sun.COM (*cl_sctp_unlisten)(connp->conn_family, slist, 563*11042SErik.Nordmark@Sun.COM sctp->sctp_nsaddrs, connp->conn_lport); 564852Svi117747 /* list will be freed by the clustering module */ 565852Svi117747 } 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate mutex_enter(&tf->tf_lock); 5680Sstevel@tonic-gate ASSERT(tf->tf_sctp); 5690Sstevel@tonic-gate if (tf->tf_sctp == sctp) { 5700Sstevel@tonic-gate tf->tf_sctp = sctp->sctp_listen_hash_next; 5717480SKacheong.Poon@Sun.COM if (sctp->sctp_listen_hash_next != NULL) { 5720Sstevel@tonic-gate ASSERT(tf->tf_sctp->sctp_listen_hash_prev == sctp); 5730Sstevel@tonic-gate tf->tf_sctp->sctp_listen_hash_prev = NULL; 5740Sstevel@tonic-gate } 5750Sstevel@tonic-gate } else { 5760Sstevel@tonic-gate ASSERT(sctp->sctp_listen_hash_prev); 5770Sstevel@tonic-gate ASSERT(sctp->sctp_listen_hash_prev->sctp_listen_hash_next == 5780Sstevel@tonic-gate sctp); 5797480SKacheong.Poon@Sun.COM ASSERT(sctp->sctp_listen_hash_next == NULL || 5807480SKacheong.Poon@Sun.COM sctp->sctp_listen_hash_next->sctp_listen_hash_prev == sctp); 5817480SKacheong.Poon@Sun.COM 5820Sstevel@tonic-gate sctp->sctp_listen_hash_prev->sctp_listen_hash_next = 5830Sstevel@tonic-gate sctp->sctp_listen_hash_next; 5840Sstevel@tonic-gate 5857480SKacheong.Poon@Sun.COM if (sctp->sctp_listen_hash_next != NULL) { 586*11042SErik.Nordmark@Sun.COM sctp_t *next = sctp->sctp_listen_hash_next; 587*11042SErik.Nordmark@Sun.COM 588*11042SErik.Nordmark@Sun.COM ASSERT(next->sctp_listen_hash_prev == sctp); 589*11042SErik.Nordmark@Sun.COM next->sctp_listen_hash_prev = 5900Sstevel@tonic-gate sctp->sctp_listen_hash_prev; 5910Sstevel@tonic-gate } 5920Sstevel@tonic-gate } 5930Sstevel@tonic-gate sctp->sctp_listen_hash_next = NULL; 5940Sstevel@tonic-gate sctp->sctp_listen_hash_prev = NULL; 5950Sstevel@tonic-gate sctp->sctp_listen_tfp = NULL; 5960Sstevel@tonic-gate mutex_exit(&tf->tf_lock); 5970Sstevel@tonic-gate } 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate void 6000Sstevel@tonic-gate sctp_listen_hash_insert(sctp_tf_t *tf, sctp_t *sctp) 6010Sstevel@tonic-gate { 602*11042SErik.Nordmark@Sun.COM conn_t *connp = sctp->sctp_connp; 603*11042SErik.Nordmark@Sun.COM 6040Sstevel@tonic-gate if (sctp->sctp_listen_tfp) { 6050Sstevel@tonic-gate sctp_listen_hash_remove(sctp); 6060Sstevel@tonic-gate } 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate mutex_enter(&tf->tf_lock); 6090Sstevel@tonic-gate sctp->sctp_listen_hash_next = tf->tf_sctp; 6100Sstevel@tonic-gate if (tf->tf_sctp) { 6110Sstevel@tonic-gate tf->tf_sctp->sctp_listen_hash_prev = sctp; 6120Sstevel@tonic-gate } 6130Sstevel@tonic-gate sctp->sctp_listen_hash_prev = NULL; 6140Sstevel@tonic-gate tf->tf_sctp = sctp; 6150Sstevel@tonic-gate sctp->sctp_listen_tfp = tf; 6160Sstevel@tonic-gate mutex_exit(&tf->tf_lock); 617852Svi117747 /* 618852Svi117747 * On a clustered note send this notification to the clustering 619852Svi117747 * subsystem. 620852Svi117747 */ 621852Svi117747 if (cl_sctp_listen != NULL) { 622852Svi117747 uchar_t *slist; 623852Svi117747 ssize_t ssize; 624852Svi117747 625852Svi117747 ssize = sizeof (in6_addr_t) * sctp->sctp_nsaddrs; 626852Svi117747 slist = kmem_alloc(ssize, KM_SLEEP); 627852Svi117747 sctp_get_saddr_list(sctp, slist, ssize); 628*11042SErik.Nordmark@Sun.COM (*cl_sctp_listen)(connp->conn_family, slist, 629*11042SErik.Nordmark@Sun.COM sctp->sctp_nsaddrs, connp->conn_lport); 630852Svi117747 /* list will be freed by the clustering module */ 631852Svi117747 } 6320Sstevel@tonic-gate } 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate /* 6350Sstevel@tonic-gate * Hash list insertion routine for sctp_t structures. 6360Sstevel@tonic-gate * Inserts entries with the ones bound to a specific IP address first 6370Sstevel@tonic-gate * followed by those bound to INADDR_ANY. 6380Sstevel@tonic-gate */ 6390Sstevel@tonic-gate void 6400Sstevel@tonic-gate sctp_bind_hash_insert(sctp_tf_t *tbf, sctp_t *sctp, int caller_holds_lock) 6410Sstevel@tonic-gate { 6420Sstevel@tonic-gate sctp_t **sctpp; 6430Sstevel@tonic-gate sctp_t *sctpnext; 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate if (sctp->sctp_ptpbhn != NULL) { 6460Sstevel@tonic-gate ASSERT(!caller_holds_lock); 6470Sstevel@tonic-gate sctp_bind_hash_remove(sctp); 6480Sstevel@tonic-gate } 6490Sstevel@tonic-gate sctpp = &tbf->tf_sctp; 6500Sstevel@tonic-gate if (!caller_holds_lock) { 6510Sstevel@tonic-gate mutex_enter(&tbf->tf_lock); 6520Sstevel@tonic-gate } else { 6530Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tbf->tf_lock)); 6540Sstevel@tonic-gate } 6550Sstevel@tonic-gate sctpnext = sctpp[0]; 6560Sstevel@tonic-gate if (sctpnext) { 6570Sstevel@tonic-gate sctpnext->sctp_ptpbhn = &sctp->sctp_bind_hash; 6580Sstevel@tonic-gate } 6590Sstevel@tonic-gate sctp->sctp_bind_hash = sctpnext; 6600Sstevel@tonic-gate sctp->sctp_ptpbhn = sctpp; 6610Sstevel@tonic-gate sctpp[0] = sctp; 6620Sstevel@tonic-gate /* For sctp_*_hash_remove */ 6630Sstevel@tonic-gate sctp->sctp_bind_lockp = &tbf->tf_lock; 6640Sstevel@tonic-gate if (!caller_holds_lock) 6650Sstevel@tonic-gate mutex_exit(&tbf->tf_lock); 6660Sstevel@tonic-gate } 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate /* 6690Sstevel@tonic-gate * Hash list removal routine for sctp_t structures. 6700Sstevel@tonic-gate */ 6710Sstevel@tonic-gate void 6720Sstevel@tonic-gate sctp_bind_hash_remove(sctp_t *sctp) 6730Sstevel@tonic-gate { 6740Sstevel@tonic-gate sctp_t *sctpnext; 6750Sstevel@tonic-gate kmutex_t *lockp; 6760Sstevel@tonic-gate 6770Sstevel@tonic-gate lockp = sctp->sctp_bind_lockp; 6780Sstevel@tonic-gate 6790Sstevel@tonic-gate if (sctp->sctp_ptpbhn == NULL) 6800Sstevel@tonic-gate return; 6810Sstevel@tonic-gate 6820Sstevel@tonic-gate ASSERT(lockp != NULL); 6830Sstevel@tonic-gate mutex_enter(lockp); 6840Sstevel@tonic-gate if (sctp->sctp_ptpbhn) { 6850Sstevel@tonic-gate sctpnext = sctp->sctp_bind_hash; 6860Sstevel@tonic-gate if (sctpnext) { 6870Sstevel@tonic-gate sctpnext->sctp_ptpbhn = sctp->sctp_ptpbhn; 6880Sstevel@tonic-gate sctp->sctp_bind_hash = NULL; 6890Sstevel@tonic-gate } 6900Sstevel@tonic-gate *sctp->sctp_ptpbhn = sctpnext; 6910Sstevel@tonic-gate sctp->sctp_ptpbhn = NULL; 6920Sstevel@tonic-gate } 6930Sstevel@tonic-gate mutex_exit(lockp); 6940Sstevel@tonic-gate sctp->sctp_bind_lockp = NULL; 6950Sstevel@tonic-gate } 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate /* 6987480SKacheong.Poon@Sun.COM * Similar to but different from sctp_conn_match(). 6990Sstevel@tonic-gate * 7000Sstevel@tonic-gate * Matches sets of addresses as follows: if the argument addr set is 7010Sstevel@tonic-gate * a complete subset of the corresponding addr set in the sctp_t, it 7020Sstevel@tonic-gate * is a match. 7030Sstevel@tonic-gate * 7040Sstevel@tonic-gate * Caller must hold tf->tf_lock. 7050Sstevel@tonic-gate * 7060Sstevel@tonic-gate * Returns with a SCTP_REFHOLD sctp structure. Caller must do a SCTP_REFRELE. 7070Sstevel@tonic-gate */ 7080Sstevel@tonic-gate sctp_t * 7090Sstevel@tonic-gate sctp_lookup(sctp_t *sctp1, in6_addr_t *faddr, sctp_tf_t *tf, uint32_t *ports, 7100Sstevel@tonic-gate int min_state) 7110Sstevel@tonic-gate { 7120Sstevel@tonic-gate sctp_t *sctp; 7130Sstevel@tonic-gate sctp_faddr_t *fp; 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate ASSERT(MUTEX_HELD(&tf->tf_lock)); 7160Sstevel@tonic-gate 7177480SKacheong.Poon@Sun.COM for (sctp = tf->tf_sctp; sctp != NULL; 7187480SKacheong.Poon@Sun.COM sctp = sctp->sctp_conn_hash_next) { 719*11042SErik.Nordmark@Sun.COM if (*ports != sctp->sctp_connp->conn_ports || 720*11042SErik.Nordmark@Sun.COM sctp->sctp_state < min_state) { 7210Sstevel@tonic-gate continue; 7220Sstevel@tonic-gate } 7230Sstevel@tonic-gate 7240Sstevel@tonic-gate /* check for faddr match */ 7257480SKacheong.Poon@Sun.COM for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { 7260Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(faddr, &fp->faddr)) { 7270Sstevel@tonic-gate break; 7280Sstevel@tonic-gate } 7290Sstevel@tonic-gate } 7300Sstevel@tonic-gate 7317480SKacheong.Poon@Sun.COM if (fp == NULL) { 7320Sstevel@tonic-gate /* no faddr match; keep looking */ 7330Sstevel@tonic-gate continue; 7340Sstevel@tonic-gate } 7350Sstevel@tonic-gate 7367480SKacheong.Poon@Sun.COM /* 7377480SKacheong.Poon@Sun.COM * There is an existing association with the same peer 7387480SKacheong.Poon@Sun.COM * address. So now we need to check if our local address 7397480SKacheong.Poon@Sun.COM * set overlaps with the one of the existing association. 7407480SKacheong.Poon@Sun.COM * If they overlap, we should return it. 7417480SKacheong.Poon@Sun.COM */ 7427480SKacheong.Poon@Sun.COM if (sctp_compare_saddrs(sctp1, sctp) <= SCTP_ADDR_OVERLAP) { 7430Sstevel@tonic-gate goto done; 7440Sstevel@tonic-gate } 7450Sstevel@tonic-gate 7460Sstevel@tonic-gate /* no match; continue searching */ 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate 7490Sstevel@tonic-gate done: 7507480SKacheong.Poon@Sun.COM if (sctp != NULL) { 7510Sstevel@tonic-gate SCTP_REFHOLD(sctp); 7520Sstevel@tonic-gate } 7530Sstevel@tonic-gate return (sctp); 7540Sstevel@tonic-gate } 755