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