1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1676 jpk * Common Development and Distribution License (the "License"). 6 1676 jpk * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 0 stevel /* 22 8485 Peter * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 0 stevel * Use is subject to license terms. 24 0 stevel */ 25 0 stevel 26 0 stevel #include <sys/types.h> 27 0 stevel #include <sys/systm.h> 28 0 stevel #include <sys/stream.h> 29 4311 vi117747 #include <sys/cmn_err.h> 30 0 stevel #include <sys/ddi.h> 31 0 stevel #include <sys/sunddi.h> 32 0 stevel #include <sys/kmem.h> 33 0 stevel #include <sys/socket.h> 34 0 stevel #include <sys/sysmacros.h> 35 0 stevel #include <sys/list.h> 36 0 stevel 37 0 stevel #include <netinet/in.h> 38 0 stevel #include <netinet/ip6.h> 39 0 stevel #include <netinet/sctp.h> 40 0 stevel 41 0 stevel #include <inet/common.h> 42 0 stevel #include <inet/ip.h> 43 0 stevel #include <inet/ip6.h> 44 11042 Erik #include <inet/ip_ire.h> 45 0 stevel #include <inet/ip_if.h> 46 0 stevel #include <inet/ipclassifier.h> 47 0 stevel #include <inet/sctp_ip.h> 48 0 stevel #include "sctp_impl.h" 49 0 stevel #include "sctp_addr.h" 50 0 stevel 51 0 stevel static void sctp_ipif_inactive(sctp_ipif_t *); 52 0 stevel static sctp_ipif_t *sctp_lookup_ipif_addr(in6_addr_t *, boolean_t, 53 3510 vi117747 zoneid_t, boolean_t, uint_t, uint_t, boolean_t, 54 3510 vi117747 sctp_stack_t *); 55 0 stevel static int sctp_get_all_ipifs(sctp_t *, int); 56 432 vi117747 static int sctp_ipif_hash_insert(sctp_t *, sctp_ipif_t *, int, 57 3510 vi117747 boolean_t, boolean_t); 58 0 stevel static void sctp_ipif_hash_remove(sctp_t *, sctp_ipif_t *); 59 4818 kcpoon static void sctp_fix_saddr(sctp_t *, in6_addr_t *); 60 0 stevel static int sctp_compare_ipif_list(sctp_ipif_hash_t *, 61 0 stevel sctp_ipif_hash_t *); 62 0 stevel static int sctp_copy_ipifs(sctp_ipif_hash_t *, sctp_t *, int); 63 3510 vi117747 64 3510 vi117747 #define SCTP_ADDR4_HASH(addr) \ 65 3510 vi117747 (((addr) ^ ((addr) >> 8) ^ ((addr) >> 16) ^ ((addr) >> 24)) & \ 66 3510 vi117747 (SCTP_IPIF_HASH - 1)) 67 3510 vi117747 68 3510 vi117747 #define SCTP_ADDR6_HASH(addr) \ 69 3510 vi117747 (((addr).s6_addr32[3] ^ \ 70 3510 vi117747 (((addr).s6_addr32[3] ^ (addr).s6_addr32[2]) >> 12)) & \ 71 3510 vi117747 (SCTP_IPIF_HASH - 1)) 72 3510 vi117747 73 3510 vi117747 #define SCTP_IPIF_ADDR_HASH(addr, isv6) \ 74 3510 vi117747 ((isv6) ? SCTP_ADDR6_HASH((addr)) : \ 75 3510 vi117747 SCTP_ADDR4_HASH((addr)._S6_un._S6_u32[3])) 76 432 vi117747 77 0 stevel #define SCTP_IPIF_USABLE(sctp_ipif_state) \ 78 0 stevel ((sctp_ipif_state) == SCTP_IPIFS_UP || \ 79 432 vi117747 (sctp_ipif_state) == SCTP_IPIFS_DOWN) 80 432 vi117747 81 432 vi117747 #define SCTP_IPIF_DISCARD(sctp_ipif_flags) \ 82 432 vi117747 ((sctp_ipif_flags) & (IPIF_PRIVATE | IPIF_DEPRECATED)) 83 432 vi117747 84 852 vi117747 #define SCTP_IS_IPIF_LOOPBACK(ipif) \ 85 852 vi117747 ((ipif)->sctp_ipif_ill->sctp_ill_flags & PHYI_LOOPBACK) 86 852 vi117747 87 852 vi117747 #define SCTP_IS_IPIF_LINKLOCAL(ipif) \ 88 852 vi117747 ((ipif)->sctp_ipif_isv6 && \ 89 852 vi117747 IN6_IS_ADDR_LINKLOCAL(&(ipif)->sctp_ipif_saddr)) 90 432 vi117747 91 432 vi117747 #define SCTP_UNSUPP_AF(ipif, supp_af) \ 92 432 vi117747 ((!(ipif)->sctp_ipif_isv6 && !((supp_af) & PARM_SUPP_V4)) || \ 93 432 vi117747 ((ipif)->sctp_ipif_isv6 && !((supp_af) & PARM_SUPP_V6))) 94 2263 sommerfe 95 2263 sommerfe #define SCTP_IPIF_ZONE_MATCH(sctp, ipif) \ 96 2263 sommerfe IPCL_ZONE_MATCH((sctp)->sctp_connp, (ipif)->sctp_ipif_zoneid) 97 0 stevel 98 0 stevel #define SCTP_ILL_HASH_FN(index) ((index) % SCTP_ILL_HASH) 99 0 stevel #define SCTP_ILL_TO_PHYINDEX(ill) ((ill)->ill_phyint->phyint_ifindex) 100 0 stevel 101 0 stevel /* 102 0 stevel * SCTP Interface list manipulation functions, locking used. 103 0 stevel */ 104 0 stevel 105 0 stevel /* 106 0 stevel * Delete an SCTP IPIF from the list if the refcount goes to 0 and it is 107 0 stevel * marked as condemned. Also, check if the ILL needs to go away. 108 0 stevel */ 109 0 stevel static void 110 0 stevel sctp_ipif_inactive(sctp_ipif_t *sctp_ipif) 111 0 stevel { 112 0 stevel sctp_ill_t *sctp_ill; 113 3510 vi117747 uint_t hindex; 114 0 stevel uint_t ill_index; 115 3448 dh155122 sctp_stack_t *sctps = sctp_ipif->sctp_ipif_ill-> 116 3448 dh155122 sctp_ill_netstack->netstack_sctp; 117 0 stevel 118 3448 dh155122 rw_enter(&sctps->sctps_g_ills_lock, RW_READER); 119 3448 dh155122 rw_enter(&sctps->sctps_g_ipifs_lock, RW_WRITER); 120 0 stevel 121 3510 vi117747 hindex = SCTP_IPIF_ADDR_HASH(sctp_ipif->sctp_ipif_saddr, 122 3510 vi117747 sctp_ipif->sctp_ipif_isv6); 123 3510 vi117747 124 0 stevel sctp_ill = sctp_ipif->sctp_ipif_ill; 125 0 stevel ASSERT(sctp_ill != NULL); 126 0 stevel ill_index = SCTP_ILL_HASH_FN(sctp_ill->sctp_ill_index); 127 0 stevel if (sctp_ipif->sctp_ipif_state != SCTP_IPIFS_CONDEMNED || 128 0 stevel sctp_ipif->sctp_ipif_refcnt != 0) { 129 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 130 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 131 0 stevel return; 132 0 stevel } 133 3510 vi117747 list_remove(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list, 134 3448 dh155122 sctp_ipif); 135 3510 vi117747 sctps->sctps_g_ipifs[hindex].ipif_count--; 136 3448 dh155122 sctps->sctps_g_ipifs_count--; 137 0 stevel rw_destroy(&sctp_ipif->sctp_ipif_lock); 138 0 stevel kmem_free(sctp_ipif, sizeof (sctp_ipif_t)); 139 0 stevel 140 0 stevel (void) atomic_add_32_nv(&sctp_ill->sctp_ill_ipifcnt, -1); 141 3448 dh155122 if (rw_tryupgrade(&sctps->sctps_g_ills_lock) != 0) { 142 3448 dh155122 rw_downgrade(&sctps->sctps_g_ipifs_lock); 143 0 stevel if (sctp_ill->sctp_ill_ipifcnt == 0 && 144 0 stevel sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) { 145 3448 dh155122 list_remove(&sctps->sctps_g_ills[ill_index]. 146 3448 dh155122 sctp_ill_list, (void *)sctp_ill); 147 3448 dh155122 sctps->sctps_g_ills[ill_index].ill_count--; 148 3448 dh155122 sctps->sctps_ills_count--; 149 0 stevel kmem_free(sctp_ill->sctp_ill_name, 150 0 stevel sctp_ill->sctp_ill_name_length); 151 0 stevel kmem_free(sctp_ill, sizeof (sctp_ill_t)); 152 0 stevel } 153 0 stevel } 154 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 155 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 156 0 stevel } 157 0 stevel 158 0 stevel /* 159 0 stevel * Lookup an SCTP IPIF given an IP address. Increments sctp_ipif refcnt. 160 3510 vi117747 * We are either looking for a IPIF with the given address before 161 3510 vi117747 * inserting it into the global list or looking for an IPIF for an 162 3510 vi117747 * address given an SCTP. In the former case we always check the zoneid, 163 3510 vi117747 * but for the latter case, check_zid could be B_FALSE if the connp 164 3510 vi117747 * for the sctp has conn_all_zones set. When looking for an address we 165 3510 vi117747 * give preference to one that is up, so even though we may find one that 166 3510 vi117747 * is not up we keep looking if there is one up, we hold the down addr 167 3510 vi117747 * in backup_ipif in case we don't find one that is up - i.e. we return 168 3510 vi117747 * the backup_ipif in that case. Note that if we are looking for. If we 169 3510 vi117747 * are specifically looking for an up address, then usable will be set 170 3510 vi117747 * to true. 171 0 stevel */ 172 0 stevel static sctp_ipif_t * 173 3510 vi117747 sctp_lookup_ipif_addr(in6_addr_t *addr, boolean_t refhold, zoneid_t zoneid, 174 3510 vi117747 boolean_t check_zid, uint_t ifindex, uint_t seqid, boolean_t usable, 175 3510 vi117747 sctp_stack_t *sctps) 176 0 stevel { 177 0 stevel int j; 178 0 stevel sctp_ipif_t *sctp_ipif; 179 3510 vi117747 sctp_ipif_t *backup_ipif = NULL; 180 3510 vi117747 int hindex; 181 0 stevel 182 3510 vi117747 hindex = SCTP_IPIF_ADDR_HASH(*addr, !IN6_IS_ADDR_V4MAPPED(addr)); 183 3510 vi117747 184 3448 dh155122 rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER); 185 3510 vi117747 if (sctps->sctps_g_ipifs[hindex].ipif_count == 0) { 186 3510 vi117747 rw_exit(&sctps->sctps_g_ipifs_lock); 187 3510 vi117747 return (NULL); 188 3510 vi117747 } 189 3510 vi117747 sctp_ipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list); 190 3510 vi117747 for (j = 0; j < sctps->sctps_g_ipifs[hindex].ipif_count; j++) { 191 3510 vi117747 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER); 192 3510 vi117747 if ((!check_zid || 193 3510 vi117747 (sctp_ipif->sctp_ipif_zoneid == ALL_ZONES || 194 3510 vi117747 zoneid == sctp_ipif->sctp_ipif_zoneid)) && 195 3510 vi117747 (ifindex == 0 || ifindex == 196 3510 vi117747 sctp_ipif->sctp_ipif_ill->sctp_ill_index) && 197 3510 vi117747 ((seqid != 0 && seqid == sctp_ipif->sctp_ipif_id) || 198 3510 vi117747 (IN6_ARE_ADDR_EQUAL(&sctp_ipif->sctp_ipif_saddr, 199 3510 vi117747 addr)))) { 200 3510 vi117747 if (!usable || sctp_ipif->sctp_ipif_state == 201 3510 vi117747 SCTP_IPIFS_UP) { 202 0 stevel rw_exit(&sctp_ipif->sctp_ipif_lock); 203 0 stevel if (refhold) 204 0 stevel SCTP_IPIF_REFHOLD(sctp_ipif); 205 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 206 0 stevel return (sctp_ipif); 207 3510 vi117747 } else if (sctp_ipif->sctp_ipif_state == 208 3510 vi117747 SCTP_IPIFS_DOWN && backup_ipif == NULL) { 209 3510 vi117747 backup_ipif = sctp_ipif; 210 0 stevel } 211 0 stevel } 212 3510 vi117747 rw_exit(&sctp_ipif->sctp_ipif_lock); 213 3510 vi117747 sctp_ipif = list_next( 214 3510 vi117747 &sctps->sctps_g_ipifs[hindex].sctp_ipif_list, sctp_ipif); 215 3510 vi117747 } 216 3510 vi117747 if (backup_ipif != NULL) { 217 3510 vi117747 if (refhold) 218 3510 vi117747 SCTP_IPIF_REFHOLD(backup_ipif); 219 3510 vi117747 rw_exit(&sctps->sctps_g_ipifs_lock); 220 3510 vi117747 return (backup_ipif); 221 0 stevel } 222 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 223 0 stevel return (NULL); 224 0 stevel } 225 0 stevel 226 0 stevel /* 227 0 stevel * Populate the list with all the SCTP ipifs for a given ipversion. 228 0 stevel * Increments sctp_ipif refcnt. 229 0 stevel * Called with no locks held. 230 0 stevel */ 231 0 stevel static int 232 0 stevel sctp_get_all_ipifs(sctp_t *sctp, int sleep) 233 0 stevel { 234 0 stevel sctp_ipif_t *sctp_ipif; 235 0 stevel int i; 236 0 stevel int j; 237 0 stevel int error = 0; 238 8903 Venu sctp_stack_t *sctps = sctp->sctp_sctps; 239 8903 Venu boolean_t isv6; 240 11042 Erik conn_t *connp = sctp->sctp_connp; 241 0 stevel 242 3448 dh155122 rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER); 243 0 stevel for (i = 0; i < SCTP_IPIF_HASH; i++) { 244 3448 dh155122 if (sctps->sctps_g_ipifs[i].ipif_count == 0) 245 0 stevel continue; 246 3448 dh155122 sctp_ipif = list_head(&sctps->sctps_g_ipifs[i].sctp_ipif_list); 247 3448 dh155122 for (j = 0; j < sctps->sctps_g_ipifs[i].ipif_count; j++) { 248 0 stevel rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER); 249 8903 Venu isv6 = sctp_ipif->sctp_ipif_isv6; 250 432 vi117747 if (SCTP_IPIF_DISCARD(sctp_ipif->sctp_ipif_flags) || 251 0 stevel !SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) || 252 2263 sommerfe !SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) || 253 8903 Venu SCTP_IS_ADDR_UNSPEC(!isv6, 254 8903 Venu sctp_ipif->sctp_ipif_saddr) || 255 11042 Erik (connp->conn_family == AF_INET && isv6) || 256 11042 Erik (connp->conn_ipv6_v6only && !isv6)) { 257 0 stevel rw_exit(&sctp_ipif->sctp_ipif_lock); 258 0 stevel sctp_ipif = list_next( 259 3448 dh155122 &sctps->sctps_g_ipifs[i].sctp_ipif_list, 260 3448 dh155122 sctp_ipif); 261 0 stevel continue; 262 0 stevel } 263 0 stevel rw_exit(&sctp_ipif->sctp_ipif_lock); 264 0 stevel SCTP_IPIF_REFHOLD(sctp_ipif); 265 432 vi117747 error = sctp_ipif_hash_insert(sctp, sctp_ipif, sleep, 266 3510 vi117747 B_FALSE, B_FALSE); 267 3510 vi117747 if (error != 0 && error != EALREADY) 268 0 stevel goto free_stuff; 269 3448 dh155122 sctp_ipif = list_next( 270 3448 dh155122 &sctps->sctps_g_ipifs[i].sctp_ipif_list, 271 0 stevel sctp_ipif); 272 0 stevel } 273 0 stevel } 274 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 275 0 stevel return (0); 276 0 stevel free_stuff: 277 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 278 0 stevel sctp_free_saddrs(sctp); 279 0 stevel return (ENOMEM); 280 0 stevel } 281 0 stevel 282 0 stevel /* 283 0 stevel * Given a list of address, fills in the list of SCTP ipifs if all the addresses 284 0 stevel * are present in the SCTP interface list, return number of addresses filled 285 852 vi117747 * or error. If the caller wants the list of addresses, it sends a pre-allocated 286 852 vi117747 * buffer - list. Currently, this list is only used on a clustered node when 287 852 vi117747 * the SCTP is in the listen state (from sctp_bind_add()). When called on a 288 852 vi117747 * clustered node, the input is always a list of addresses (even if the 289 852 vi117747 * original bind() was to INADDR_ANY). 290 0 stevel * Called with no locks held. 291 0 stevel */ 292 0 stevel int 293 852 vi117747 sctp_valid_addr_list(sctp_t *sctp, const void *addrs, uint32_t addrcnt, 294 852 vi117747 uchar_t *list, size_t lsize) 295 0 stevel { 296 0 stevel struct sockaddr_in *sin4; 297 0 stevel struct sockaddr_in6 *sin6; 298 0 stevel struct in_addr *addr4; 299 0 stevel in6_addr_t addr; 300 0 stevel int cnt; 301 0 stevel int err = 0; 302 0 stevel int saddr_cnt = 0; 303 0 stevel sctp_ipif_t *ipif; 304 0 stevel boolean_t bind_to_all = B_FALSE; 305 0 stevel boolean_t check_addrs = B_FALSE; 306 0 stevel boolean_t check_lport = B_FALSE; 307 852 vi117747 uchar_t *p = list; 308 11042 Erik conn_t *connp = sctp->sctp_connp; 309 0 stevel 310 0 stevel /* 311 0 stevel * Need to check for port and address depending on the state. 312 0 stevel * After a socket is bound, we need to make sure that subsequent 313 0 stevel * bindx() has correct port. After an association is established, 314 0 stevel * we need to check for changing the bound address to invalid 315 0 stevel * addresses. 316 0 stevel */ 317 0 stevel if (sctp->sctp_state >= SCTPS_BOUND) { 318 0 stevel check_lport = B_TRUE; 319 0 stevel if (sctp->sctp_state > SCTPS_LISTEN) 320 0 stevel check_addrs = B_TRUE; 321 0 stevel } 322 852 vi117747 323 0 stevel if (sctp->sctp_conn_tfp != NULL) 324 0 stevel mutex_enter(&sctp->sctp_conn_tfp->tf_lock); 325 0 stevel if (sctp->sctp_listen_tfp != NULL) 326 0 stevel mutex_enter(&sctp->sctp_listen_tfp->tf_lock); 327 0 stevel for (cnt = 0; cnt < addrcnt; cnt++) { 328 0 stevel boolean_t lookup_saddr = B_TRUE; 329 852 vi117747 uint_t ifindex = 0; 330 0 stevel 331 11042 Erik switch (connp->conn_family) { 332 0 stevel case AF_INET: 333 0 stevel sin4 = (struct sockaddr_in *)addrs + cnt; 334 0 stevel if (sin4->sin_family != AF_INET || (check_lport && 335 11042 Erik sin4->sin_port != connp->conn_lport)) { 336 0 stevel err = EINVAL; 337 0 stevel goto free_ret; 338 0 stevel } 339 0 stevel addr4 = &sin4->sin_addr; 340 0 stevel if (check_addrs && 341 0 stevel (addr4->s_addr == INADDR_ANY || 342 0 stevel addr4->s_addr == INADDR_BROADCAST || 343 5215 kcpoon CLASSD(addr4->s_addr))) { 344 0 stevel err = EINVAL; 345 0 stevel goto free_ret; 346 0 stevel } 347 0 stevel IN6_INADDR_TO_V4MAPPED(addr4, &addr); 348 0 stevel if (!check_addrs && addr4->s_addr == INADDR_ANY) { 349 0 stevel lookup_saddr = B_FALSE; 350 0 stevel bind_to_all = B_TRUE; 351 0 stevel } 352 0 stevel 353 0 stevel break; 354 0 stevel case AF_INET6: 355 0 stevel sin6 = (struct sockaddr_in6 *)addrs + cnt; 356 0 stevel if (sin6->sin6_family != AF_INET6 || (check_lport && 357 11042 Erik sin6->sin6_port != connp->conn_lport)) { 358 0 stevel err = EINVAL; 359 0 stevel goto free_ret; 360 0 stevel } 361 0 stevel addr = sin6->sin6_addr; 362 852 vi117747 /* Contains the interface index */ 363 852 vi117747 ifindex = sin6->sin6_scope_id; 364 11042 Erik if (connp->conn_ipv6_v6only && 365 0 stevel IN6_IS_ADDR_V4MAPPED(&addr)) { 366 0 stevel err = EAFNOSUPPORT; 367 0 stevel goto free_ret; 368 0 stevel } 369 0 stevel if (check_addrs && 370 0 stevel (IN6_IS_ADDR_LINKLOCAL(&addr) || 371 0 stevel IN6_IS_ADDR_MULTICAST(&addr) || 372 0 stevel IN6_IS_ADDR_UNSPECIFIED(&addr))) { 373 0 stevel err = EINVAL; 374 0 stevel goto free_ret; 375 0 stevel } 376 0 stevel if (!check_addrs && IN6_IS_ADDR_UNSPECIFIED(&addr)) { 377 0 stevel lookup_saddr = B_FALSE; 378 0 stevel bind_to_all = B_TRUE; 379 0 stevel } 380 0 stevel 381 0 stevel break; 382 0 stevel default: 383 0 stevel err = EAFNOSUPPORT; 384 0 stevel goto free_ret; 385 0 stevel } 386 0 stevel if (lookup_saddr) { 387 3510 vi117747 ipif = sctp_lookup_ipif_addr(&addr, B_TRUE, 388 11042 Erik IPCL_ZONEID(connp), !connp->conn_allzones, 389 3510 vi117747 ifindex, 0, B_TRUE, sctp->sctp_sctps); 390 0 stevel if (ipif == NULL) { 391 0 stevel /* Address not in the list */ 392 0 stevel err = EINVAL; 393 0 stevel goto free_ret; 394 852 vi117747 } else if (check_addrs && SCTP_IS_IPIF_LOOPBACK(ipif) && 395 852 vi117747 cl_sctp_check_addrs == NULL) { 396 0 stevel SCTP_IPIF_REFRELE(ipif); 397 0 stevel err = EINVAL; 398 0 stevel goto free_ret; 399 0 stevel } 400 0 stevel } 401 0 stevel if (!bind_to_all) { 402 432 vi117747 /* 403 432 vi117747 * If an address is added after association setup, 404 432 vi117747 * we need to wait for the peer to send us an ASCONF 405 432 vi117747 * ACK before we can start using it. 406 432 vi117747 * saddr_ipif_dontsrc will be reset (to 0) when we 407 432 vi117747 * get the ASCONF ACK for this address. 408 432 vi117747 */ 409 432 vi117747 err = sctp_ipif_hash_insert(sctp, ipif, KM_SLEEP, 410 3510 vi117747 check_addrs ? B_TRUE : B_FALSE, B_FALSE); 411 0 stevel if (err != 0) { 412 0 stevel SCTP_IPIF_REFRELE(ipif); 413 0 stevel if (check_addrs && err == EALREADY) 414 0 stevel err = EADDRINUSE; 415 0 stevel goto free_ret; 416 0 stevel } 417 0 stevel saddr_cnt++; 418 852 vi117747 if (lsize >= sizeof (addr)) { 419 852 vi117747 bcopy(&addr, p, sizeof (addr)); 420 852 vi117747 p += sizeof (addr); 421 852 vi117747 lsize -= sizeof (addr); 422 852 vi117747 } 423 0 stevel } 424 0 stevel } 425 0 stevel if (bind_to_all) { 426 0 stevel /* 427 0 stevel * Free whatever we might have added before encountering 428 0 stevel * inaddr_any. 429 0 stevel */ 430 0 stevel if (sctp->sctp_nsaddrs > 0) { 431 0 stevel sctp_free_saddrs(sctp); 432 0 stevel ASSERT(sctp->sctp_nsaddrs == 0); 433 0 stevel } 434 0 stevel err = sctp_get_all_ipifs(sctp, KM_SLEEP); 435 0 stevel if (err != 0) 436 0 stevel return (err); 437 0 stevel sctp->sctp_bound_to_all = 1; 438 0 stevel } 439 0 stevel if (sctp->sctp_listen_tfp != NULL) 440 0 stevel mutex_exit(&sctp->sctp_listen_tfp->tf_lock); 441 0 stevel if (sctp->sctp_conn_tfp != NULL) 442 0 stevel mutex_exit(&sctp->sctp_conn_tfp->tf_lock); 443 0 stevel return (0); 444 0 stevel free_ret: 445 0 stevel if (saddr_cnt != 0) 446 0 stevel sctp_del_saddr_list(sctp, addrs, saddr_cnt, B_TRUE); 447 0 stevel if (sctp->sctp_listen_tfp != NULL) 448 0 stevel mutex_exit(&sctp->sctp_listen_tfp->tf_lock); 449 0 stevel if (sctp->sctp_conn_tfp != NULL) 450 0 stevel mutex_exit(&sctp->sctp_conn_tfp->tf_lock); 451 0 stevel return (err); 452 0 stevel } 453 0 stevel 454 0 stevel static int 455 432 vi117747 sctp_ipif_hash_insert(sctp_t *sctp, sctp_ipif_t *ipif, int sleep, 456 3510 vi117747 boolean_t dontsrc, boolean_t allow_dup) 457 0 stevel { 458 0 stevel int cnt; 459 0 stevel sctp_saddr_ipif_t *ipif_obj; 460 3510 vi117747 int hindex; 461 0 stevel 462 3510 vi117747 hindex = SCTP_IPIF_ADDR_HASH(ipif->sctp_ipif_saddr, 463 3510 vi117747 ipif->sctp_ipif_isv6); 464 3510 vi117747 ipif_obj = list_head(&sctp->sctp_saddrs[hindex].sctp_ipif_list); 465 3510 vi117747 for (cnt = 0; cnt < sctp->sctp_saddrs[hindex].ipif_count; cnt++) { 466 3510 vi117747 if (IN6_ARE_ADDR_EQUAL(&ipif_obj->saddr_ipifp->sctp_ipif_saddr, 467 3510 vi117747 &ipif->sctp_ipif_saddr)) { 468 3510 vi117747 if (ipif->sctp_ipif_id != 469 3510 vi117747 ipif_obj->saddr_ipifp->sctp_ipif_id && 470 3510 vi117747 ipif_obj->saddr_ipifp->sctp_ipif_state == 471 3510 vi117747 SCTP_IPIFS_DOWN && ipif->sctp_ipif_state == 472 3510 vi117747 SCTP_IPIFS_UP) { 473 3510 vi117747 SCTP_IPIF_REFRELE(ipif_obj->saddr_ipifp); 474 3510 vi117747 ipif_obj->saddr_ipifp = ipif; 475 3510 vi117747 ipif_obj->saddr_ipif_dontsrc = dontsrc ? 1 : 0; 476 3510 vi117747 return (0); 477 3510 vi117747 } else if (!allow_dup || ipif->sctp_ipif_id == 478 3510 vi117747 ipif_obj->saddr_ipifp->sctp_ipif_id) { 479 3510 vi117747 return (EALREADY); 480 3510 vi117747 } 481 3510 vi117747 } 482 3510 vi117747 ipif_obj = list_next(&sctp->sctp_saddrs[hindex].sctp_ipif_list, 483 0 stevel ipif_obj); 484 0 stevel } 485 0 stevel ipif_obj = kmem_zalloc(sizeof (sctp_saddr_ipif_t), sleep); 486 0 stevel if (ipif_obj == NULL) { 487 0 stevel /* Need to do something */ 488 0 stevel return (ENOMEM); 489 0 stevel } 490 0 stevel ipif_obj->saddr_ipifp = ipif; 491 432 vi117747 ipif_obj->saddr_ipif_dontsrc = dontsrc ? 1 : 0; 492 3510 vi117747 list_insert_tail(&sctp->sctp_saddrs[hindex].sctp_ipif_list, ipif_obj); 493 3510 vi117747 sctp->sctp_saddrs[hindex].ipif_count++; 494 0 stevel sctp->sctp_nsaddrs++; 495 0 stevel return (0); 496 0 stevel } 497 0 stevel 498 4818 kcpoon /* 499 4818 kcpoon * Given a source address, walk through the peer address list to see 500 4818 kcpoon * if the source address is being used. If it is, reset that. 501 11042 Erik * A cleared saddr will then make sctp_make_mp lookup the destination again 502 11042 Erik * and as part of that look for a new source. 503 4818 kcpoon */ 504 4818 kcpoon static void 505 4818 kcpoon sctp_fix_saddr(sctp_t *sctp, in6_addr_t *saddr) 506 4818 kcpoon { 507 4818 kcpoon sctp_faddr_t *fp; 508 4818 kcpoon 509 4818 kcpoon for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { 510 4818 kcpoon if (!IN6_ARE_ADDR_EQUAL(&fp->saddr, saddr)) 511 4818 kcpoon continue; 512 4818 kcpoon V6_SET_ZERO(fp->saddr); 513 4818 kcpoon } 514 4818 kcpoon } 515 4818 kcpoon 516 0 stevel static void 517 0 stevel sctp_ipif_hash_remove(sctp_t *sctp, sctp_ipif_t *ipif) 518 0 stevel { 519 0 stevel int cnt; 520 0 stevel sctp_saddr_ipif_t *ipif_obj; 521 3510 vi117747 int hindex; 522 0 stevel 523 3510 vi117747 hindex = SCTP_IPIF_ADDR_HASH(ipif->sctp_ipif_saddr, 524 3510 vi117747 ipif->sctp_ipif_isv6); 525 3510 vi117747 ipif_obj = list_head(&sctp->sctp_saddrs[hindex].sctp_ipif_list); 526 3510 vi117747 for (cnt = 0; cnt < sctp->sctp_saddrs[hindex].ipif_count; cnt++) { 527 3510 vi117747 if (IN6_ARE_ADDR_EQUAL(&ipif_obj->saddr_ipifp->sctp_ipif_saddr, 528 3510 vi117747 &ipif->sctp_ipif_saddr)) { 529 3510 vi117747 list_remove(&sctp->sctp_saddrs[hindex].sctp_ipif_list, 530 0 stevel ipif_obj); 531 3510 vi117747 sctp->sctp_saddrs[hindex].ipif_count--; 532 0 stevel sctp->sctp_nsaddrs--; 533 4818 kcpoon sctp_fix_saddr(sctp, &ipif->sctp_ipif_saddr); 534 0 stevel SCTP_IPIF_REFRELE(ipif_obj->saddr_ipifp); 535 0 stevel kmem_free(ipif_obj, sizeof (sctp_saddr_ipif_t)); 536 0 stevel break; 537 0 stevel } 538 3510 vi117747 ipif_obj = list_next(&sctp->sctp_saddrs[hindex].sctp_ipif_list, 539 0 stevel ipif_obj); 540 0 stevel } 541 0 stevel } 542 0 stevel 543 0 stevel static int 544 0 stevel sctp_compare_ipif_list(sctp_ipif_hash_t *list1, sctp_ipif_hash_t *list2) 545 0 stevel { 546 0 stevel int i; 547 0 stevel int j; 548 0 stevel sctp_saddr_ipif_t *obj1; 549 0 stevel sctp_saddr_ipif_t *obj2; 550 0 stevel int overlap = 0; 551 0 stevel 552 0 stevel obj1 = list_head(&list1->sctp_ipif_list); 553 0 stevel for (i = 0; i < list1->ipif_count; i++) { 554 0 stevel obj2 = list_head(&list2->sctp_ipif_list); 555 0 stevel for (j = 0; j < list2->ipif_count; j++) { 556 3510 vi117747 if (IN6_ARE_ADDR_EQUAL( 557 3510 vi117747 &obj1->saddr_ipifp->sctp_ipif_saddr, 558 3510 vi117747 &obj2->saddr_ipifp->sctp_ipif_saddr)) { 559 0 stevel overlap++; 560 0 stevel break; 561 0 stevel } 562 0 stevel obj2 = list_next(&list2->sctp_ipif_list, 563 0 stevel obj2); 564 0 stevel } 565 0 stevel obj1 = list_next(&list1->sctp_ipif_list, obj1); 566 0 stevel } 567 0 stevel return (overlap); 568 0 stevel } 569 0 stevel 570 0 stevel int 571 0 stevel sctp_compare_saddrs(sctp_t *sctp1, sctp_t *sctp2) 572 0 stevel { 573 0 stevel int i; 574 0 stevel int overlap = 0; 575 0 stevel 576 0 stevel for (i = 0; i < SCTP_IPIF_HASH; i++) { 577 0 stevel overlap += sctp_compare_ipif_list(&sctp1->sctp_saddrs[i], 578 0 stevel &sctp2->sctp_saddrs[i]); 579 0 stevel } 580 0 stevel 581 0 stevel if (sctp1->sctp_nsaddrs == sctp2->sctp_nsaddrs && 582 0 stevel overlap == sctp1->sctp_nsaddrs) { 583 0 stevel return (SCTP_ADDR_EQUAL); 584 0 stevel } 585 0 stevel 586 0 stevel if (overlap == sctp1->sctp_nsaddrs) 587 0 stevel return (SCTP_ADDR_SUBSET); 588 0 stevel 589 0 stevel if (overlap > 0) 590 0 stevel return (SCTP_ADDR_OVERLAP); 591 0 stevel 592 0 stevel return (SCTP_ADDR_DISJOINT); 593 0 stevel } 594 0 stevel 595 0 stevel static int 596 0 stevel sctp_copy_ipifs(sctp_ipif_hash_t *list1, sctp_t *sctp2, int sleep) 597 0 stevel { 598 0 stevel int i; 599 0 stevel sctp_saddr_ipif_t *obj; 600 0 stevel int error = 0; 601 0 stevel 602 0 stevel obj = list_head(&list1->sctp_ipif_list); 603 0 stevel for (i = 0; i < list1->ipif_count; i++) { 604 0 stevel SCTP_IPIF_REFHOLD(obj->saddr_ipifp); 605 432 vi117747 error = sctp_ipif_hash_insert(sctp2, obj->saddr_ipifp, sleep, 606 3510 vi117747 B_FALSE, B_FALSE); 607 3510 vi117747 ASSERT(error != EALREADY); 608 0 stevel if (error != 0) 609 0 stevel return (error); 610 0 stevel obj = list_next(&list1->sctp_ipif_list, obj); 611 0 stevel } 612 0 stevel return (error); 613 0 stevel } 614 0 stevel 615 0 stevel int 616 0 stevel sctp_dup_saddrs(sctp_t *sctp1, sctp_t *sctp2, int sleep) 617 0 stevel { 618 0 stevel int error = 0; 619 0 stevel int i; 620 0 stevel 621 432 vi117747 if (sctp1 == NULL || sctp1->sctp_bound_to_all == 1) 622 0 stevel return (sctp_get_all_ipifs(sctp2, sleep)); 623 0 stevel 624 0 stevel for (i = 0; i < SCTP_IPIF_HASH; i++) { 625 0 stevel if (sctp1->sctp_saddrs[i].ipif_count == 0) 626 0 stevel continue; 627 0 stevel error = sctp_copy_ipifs(&sctp1->sctp_saddrs[i], sctp2, sleep); 628 0 stevel if (error != 0) { 629 0 stevel sctp_free_saddrs(sctp2); 630 0 stevel return (error); 631 0 stevel } 632 0 stevel } 633 0 stevel return (0); 634 0 stevel } 635 0 stevel 636 0 stevel void 637 0 stevel sctp_free_saddrs(sctp_t *sctp) 638 0 stevel { 639 0 stevel int i; 640 0 stevel int l; 641 0 stevel sctp_saddr_ipif_t *obj; 642 0 stevel 643 0 stevel if (sctp->sctp_nsaddrs == 0) 644 0 stevel return; 645 0 stevel for (i = 0; i < SCTP_IPIF_HASH; i++) { 646 0 stevel if (sctp->sctp_saddrs[i].ipif_count == 0) 647 0 stevel continue; 648 0 stevel obj = list_tail(&sctp->sctp_saddrs[i].sctp_ipif_list); 649 0 stevel for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) { 650 0 stevel list_remove(&sctp->sctp_saddrs[i].sctp_ipif_list, obj); 651 0 stevel SCTP_IPIF_REFRELE(obj->saddr_ipifp); 652 0 stevel sctp->sctp_nsaddrs--; 653 0 stevel kmem_free(obj, sizeof (sctp_saddr_ipif_t)); 654 0 stevel obj = list_tail(&sctp->sctp_saddrs[i].sctp_ipif_list); 655 0 stevel } 656 0 stevel sctp->sctp_saddrs[i].ipif_count = 0; 657 0 stevel } 658 432 vi117747 if (sctp->sctp_bound_to_all == 1) 659 432 vi117747 sctp->sctp_bound_to_all = 0; 660 0 stevel ASSERT(sctp->sctp_nsaddrs == 0); 661 0 stevel } 662 0 stevel 663 0 stevel /* 664 0 stevel * Add/Delete the given ILL from the SCTP ILL list. Called with no locks 665 0 stevel * held. 666 0 stevel */ 667 0 stevel void 668 0 stevel sctp_update_ill(ill_t *ill, int op) 669 0 stevel { 670 0 stevel int i; 671 0 stevel sctp_ill_t *sctp_ill = NULL; 672 0 stevel uint_t index; 673 3448 dh155122 netstack_t *ns = ill->ill_ipst->ips_netstack; 674 3448 dh155122 sctp_stack_t *sctps = ns->netstack_sctp; 675 0 stevel 676 3448 dh155122 rw_enter(&sctps->sctps_g_ills_lock, RW_WRITER); 677 0 stevel 678 0 stevel index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill)); 679 3448 dh155122 sctp_ill = list_head(&sctps->sctps_g_ills[index].sctp_ill_list); 680 3448 dh155122 for (i = 0; i < sctps->sctps_g_ills[index].ill_count; i++) { 681 4311 vi117747 if ((sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill)) && 682 4311 vi117747 (sctp_ill->sctp_ill_isv6 == ill->ill_isv6)) { 683 0 stevel break; 684 4311 vi117747 } 685 3448 dh155122 sctp_ill = list_next(&sctps->sctps_g_ills[index].sctp_ill_list, 686 0 stevel sctp_ill); 687 0 stevel } 688 0 stevel 689 0 stevel switch (op) { 690 0 stevel case SCTP_ILL_INSERT: 691 0 stevel if (sctp_ill != NULL) { 692 0 stevel /* Unmark it if it is condemned */ 693 0 stevel if (sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) 694 0 stevel sctp_ill->sctp_ill_state = 0; 695 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 696 0 stevel return; 697 0 stevel } 698 0 stevel sctp_ill = kmem_zalloc(sizeof (sctp_ill_t), KM_NOSLEEP); 699 0 stevel /* Need to re-try? */ 700 0 stevel if (sctp_ill == NULL) { 701 4311 vi117747 cmn_err(CE_WARN, "sctp_update_ill: error adding " 702 4311 vi117747 "ILL %p to SCTP's ILL list", (void *)ill); 703 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 704 0 stevel return; 705 0 stevel } 706 3510 vi117747 sctp_ill->sctp_ill_name = kmem_zalloc(ill->ill_name_length, 707 3510 vi117747 KM_NOSLEEP); 708 0 stevel if (sctp_ill->sctp_ill_name == NULL) { 709 4311 vi117747 cmn_err(CE_WARN, "sctp_update_ill: error adding " 710 4311 vi117747 "ILL %p to SCTP's ILL list", (void *)ill); 711 0 stevel kmem_free(sctp_ill, sizeof (sctp_ill_t)); 712 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 713 0 stevel return; 714 0 stevel } 715 0 stevel bcopy(ill->ill_name, sctp_ill->sctp_ill_name, 716 0 stevel ill->ill_name_length); 717 0 stevel sctp_ill->sctp_ill_name_length = ill->ill_name_length; 718 0 stevel sctp_ill->sctp_ill_index = SCTP_ILL_TO_PHYINDEX(ill); 719 0 stevel sctp_ill->sctp_ill_flags = ill->ill_phyint->phyint_flags; 720 3448 dh155122 sctp_ill->sctp_ill_netstack = ns; /* No netstack_hold */ 721 4311 vi117747 sctp_ill->sctp_ill_isv6 = ill->ill_isv6; 722 3448 dh155122 list_insert_tail(&sctps->sctps_g_ills[index].sctp_ill_list, 723 0 stevel (void *)sctp_ill); 724 3448 dh155122 sctps->sctps_g_ills[index].ill_count++; 725 3448 dh155122 sctps->sctps_ills_count++; 726 0 stevel 727 0 stevel break; 728 0 stevel 729 0 stevel case SCTP_ILL_REMOVE: 730 0 stevel 731 0 stevel if (sctp_ill == NULL) { 732 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 733 0 stevel return; 734 0 stevel } 735 0 stevel if (sctp_ill->sctp_ill_ipifcnt == 0) { 736 3448 dh155122 list_remove(&sctps->sctps_g_ills[index].sctp_ill_list, 737 0 stevel (void *)sctp_ill); 738 3448 dh155122 sctps->sctps_g_ills[index].ill_count--; 739 3448 dh155122 sctps->sctps_ills_count--; 740 0 stevel kmem_free(sctp_ill->sctp_ill_name, 741 0 stevel ill->ill_name_length); 742 0 stevel kmem_free(sctp_ill, sizeof (sctp_ill_t)); 743 0 stevel } else { 744 0 stevel sctp_ill->sctp_ill_state = SCTP_ILLS_CONDEMNED; 745 0 stevel } 746 0 stevel 747 0 stevel break; 748 0 stevel } 749 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 750 0 stevel } 751 0 stevel 752 4311 vi117747 /* 753 4311 vi117747 * The ILL's index is being changed, just remove it from the old list, 754 4311 vi117747 * change the SCTP ILL's index and re-insert using the new index. 755 4311 vi117747 */ 756 4311 vi117747 void 757 4311 vi117747 sctp_ill_reindex(ill_t *ill, uint_t orig_ill_index) 758 4311 vi117747 { 759 4311 vi117747 sctp_ill_t *sctp_ill = NULL; 760 4311 vi117747 sctp_ill_t *nxt_sill; 761 4311 vi117747 uint_t indx; 762 4311 vi117747 uint_t nindx; 763 4311 vi117747 boolean_t once = B_FALSE; 764 4311 vi117747 netstack_t *ns = ill->ill_ipst->ips_netstack; 765 4311 vi117747 sctp_stack_t *sctps = ns->netstack_sctp; 766 4311 vi117747 767 4311 vi117747 rw_enter(&sctps->sctps_g_ills_lock, RW_WRITER); 768 4311 vi117747 769 4311 vi117747 indx = SCTP_ILL_HASH_FN(orig_ill_index); 770 4311 vi117747 nindx = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill)); 771 4311 vi117747 sctp_ill = list_head(&sctps->sctps_g_ills[indx].sctp_ill_list); 772 4311 vi117747 while (sctp_ill != NULL) { 773 4311 vi117747 nxt_sill = list_next(&sctps->sctps_g_ills[indx].sctp_ill_list, 774 4311 vi117747 sctp_ill); 775 4311 vi117747 if (sctp_ill->sctp_ill_index == orig_ill_index) { 776 4311 vi117747 sctp_ill->sctp_ill_index = SCTP_ILL_TO_PHYINDEX(ill); 777 4311 vi117747 /* 778 4311 vi117747 * if the new index hashes to the same value, all's 779 4311 vi117747 * done. 780 4311 vi117747 */ 781 4311 vi117747 if (nindx != indx) { 782 4311 vi117747 list_remove( 783 4311 vi117747 &sctps->sctps_g_ills[indx].sctp_ill_list, 784 4311 vi117747 (void *)sctp_ill); 785 4311 vi117747 sctps->sctps_g_ills[indx].ill_count--; 786 4311 vi117747 list_insert_tail( 787 4311 vi117747 &sctps->sctps_g_ills[nindx].sctp_ill_list, 788 4311 vi117747 (void *)sctp_ill); 789 4311 vi117747 sctps->sctps_g_ills[nindx].ill_count++; 790 4311 vi117747 } 791 4311 vi117747 if (once) 792 4311 vi117747 break; 793 4311 vi117747 /* We might have one for v4 and for v6 */ 794 4311 vi117747 once = B_TRUE; 795 4311 vi117747 } 796 4311 vi117747 sctp_ill = nxt_sill; 797 4311 vi117747 } 798 4311 vi117747 rw_exit(&sctps->sctps_g_ills_lock); 799 4311 vi117747 } 800 4311 vi117747 801 0 stevel /* move ipif from f_ill to t_ill */ 802 0 stevel void 803 0 stevel sctp_move_ipif(ipif_t *ipif, ill_t *f_ill, ill_t *t_ill) 804 0 stevel { 805 0 stevel sctp_ill_t *fsctp_ill = NULL; 806 0 stevel sctp_ill_t *tsctp_ill = NULL; 807 0 stevel sctp_ipif_t *sctp_ipif; 808 3510 vi117747 uint_t hindex; 809 0 stevel int i; 810 3448 dh155122 netstack_t *ns = ipif->ipif_ill->ill_ipst->ips_netstack; 811 3448 dh155122 sctp_stack_t *sctps = ns->netstack_sctp; 812 0 stevel 813 3448 dh155122 rw_enter(&sctps->sctps_g_ills_lock, RW_READER); 814 3448 dh155122 rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER); 815 0 stevel 816 3510 vi117747 hindex = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(f_ill)); 817 3510 vi117747 fsctp_ill = list_head(&sctps->sctps_g_ills[hindex].sctp_ill_list); 818 3510 vi117747 for (i = 0; i < sctps->sctps_g_ills[hindex].ill_count; i++) { 819 4311 vi117747 if (fsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(f_ill) && 820 4311 vi117747 fsctp_ill->sctp_ill_isv6 == f_ill->ill_isv6) { 821 0 stevel break; 822 4311 vi117747 } 823 3510 vi117747 fsctp_ill = list_next( 824 3510 vi117747 &sctps->sctps_g_ills[hindex].sctp_ill_list, fsctp_ill); 825 0 stevel } 826 0 stevel 827 3510 vi117747 hindex = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(t_ill)); 828 3510 vi117747 tsctp_ill = list_head(&sctps->sctps_g_ills[hindex].sctp_ill_list); 829 3510 vi117747 for (i = 0; i < sctps->sctps_g_ills[hindex].ill_count; i++) { 830 4311 vi117747 if (tsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(t_ill) && 831 4311 vi117747 tsctp_ill->sctp_ill_isv6 == t_ill->ill_isv6) { 832 0 stevel break; 833 4311 vi117747 } 834 3510 vi117747 tsctp_ill = list_next( 835 3510 vi117747 &sctps->sctps_g_ills[hindex].sctp_ill_list, tsctp_ill); 836 0 stevel } 837 0 stevel 838 3510 vi117747 hindex = SCTP_IPIF_ADDR_HASH(ipif->ipif_v6lcl_addr, 839 3510 vi117747 ipif->ipif_ill->ill_isv6); 840 3510 vi117747 sctp_ipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list); 841 3510 vi117747 for (i = 0; i < sctps->sctps_g_ipifs[hindex].ipif_count; i++) { 842 0 stevel if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid) 843 0 stevel break; 844 3448 dh155122 sctp_ipif = list_next( 845 3510 vi117747 &sctps->sctps_g_ipifs[hindex].sctp_ipif_list, sctp_ipif); 846 0 stevel } 847 0 stevel /* Should be an ASSERT? */ 848 0 stevel if (fsctp_ill == NULL || tsctp_ill == NULL || sctp_ipif == NULL) { 849 0 stevel ip1dbg(("sctp_move_ipif: error moving ipif %p from %p to %p\n", 850 0 stevel (void *)ipif, (void *)f_ill, (void *)t_ill)); 851 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 852 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 853 0 stevel return; 854 0 stevel } 855 0 stevel rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER); 856 0 stevel ASSERT(sctp_ipif->sctp_ipif_ill == fsctp_ill); 857 0 stevel sctp_ipif->sctp_ipif_ill = tsctp_ill; 858 0 stevel rw_exit(&sctp_ipif->sctp_ipif_lock); 859 0 stevel (void) atomic_add_32_nv(&fsctp_ill->sctp_ill_ipifcnt, -1); 860 0 stevel atomic_add_32(&tsctp_ill->sctp_ill_ipifcnt, 1); 861 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 862 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 863 0 stevel } 864 0 stevel 865 3510 vi117747 /* 866 3510 vi117747 * Walk the list of SCTPs and find each that has oipif in it's saddr list, and 867 3510 vi117747 * if so replace it with nipif. 868 3510 vi117747 */ 869 3510 vi117747 void 870 3510 vi117747 sctp_update_saddrs(sctp_ipif_t *oipif, sctp_ipif_t *nipif, int idx, 871 3510 vi117747 sctp_stack_t *sctps) 872 3510 vi117747 { 873 3510 vi117747 sctp_t *sctp; 874 3510 vi117747 sctp_t *sctp_prev = NULL; 875 3510 vi117747 sctp_saddr_ipif_t *sobj; 876 3510 vi117747 int count; 877 3510 vi117747 878 3510 vi117747 mutex_enter(&sctps->sctps_g_lock); 879 11042 Erik sctp = list_head(&sctps->sctps_g_list); 880 3510 vi117747 while (sctp != NULL && oipif->sctp_ipif_refcnt > 0) { 881 3510 vi117747 mutex_enter(&sctp->sctp_reflock); 882 3510 vi117747 if (sctp->sctp_condemned || 883 3510 vi117747 sctp->sctp_saddrs[idx].ipif_count <= 0) { 884 3510 vi117747 mutex_exit(&sctp->sctp_reflock); 885 3510 vi117747 sctp = list_next(&sctps->sctps_g_list, sctp); 886 3510 vi117747 continue; 887 3510 vi117747 } 888 3510 vi117747 sctp->sctp_refcnt++; 889 3510 vi117747 mutex_exit(&sctp->sctp_reflock); 890 3510 vi117747 mutex_exit(&sctps->sctps_g_lock); 891 3510 vi117747 if (sctp_prev != NULL) 892 3510 vi117747 SCTP_REFRELE(sctp_prev); 893 3510 vi117747 894 3510 vi117747 RUN_SCTP(sctp); 895 3510 vi117747 sobj = list_head(&sctp->sctp_saddrs[idx].sctp_ipif_list); 896 3510 vi117747 for (count = 0; count < 897 3510 vi117747 sctp->sctp_saddrs[idx].ipif_count; count++) { 898 3510 vi117747 if (sobj->saddr_ipifp == oipif) { 899 3510 vi117747 SCTP_IPIF_REFHOLD(nipif); 900 3510 vi117747 sobj->saddr_ipifp = nipif; 901 3510 vi117747 ASSERT(oipif->sctp_ipif_refcnt > 0); 902 3510 vi117747 /* We have the writer lock */ 903 3510 vi117747 oipif->sctp_ipif_refcnt--; 904 3510 vi117747 /* 905 3510 vi117747 * Can't have more than one referring 906 3510 vi117747 * to the same sctp_ipif. 907 3510 vi117747 */ 908 3510 vi117747 break; 909 3510 vi117747 } 910 3510 vi117747 sobj = list_next(&sctp->sctp_saddrs[idx].sctp_ipif_list, 911 3510 vi117747 sobj); 912 3510 vi117747 } 913 3510 vi117747 WAKE_SCTP(sctp); 914 3510 vi117747 sctp_prev = sctp; 915 3510 vi117747 mutex_enter(&sctps->sctps_g_lock); 916 3510 vi117747 sctp = list_next(&sctps->sctps_g_list, sctp); 917 3510 vi117747 } 918 3510 vi117747 mutex_exit(&sctps->sctps_g_lock); 919 3510 vi117747 if (sctp_prev != NULL) 920 3510 vi117747 SCTP_REFRELE(sctp_prev); 921 3510 vi117747 } 922 3510 vi117747 923 3510 vi117747 /* 924 3510 vi117747 * Given an ipif, walk the hash list in the global ipif table and for 925 3510 vi117747 * any other SCTP ipif with the same address and non-zero reference, walk 926 3510 vi117747 * the SCTP list and update the saddr list, if required, to point to the 927 9705 Venu * new SCTP ipif. If it is a loopback interface, then there could be 928 9705 Venu * multiple interfaces with 127.0.0.1 if there are zones configured, so 929 9705 Venu * check the zoneid in addition to the address. 930 3510 vi117747 */ 931 3510 vi117747 void 932 3510 vi117747 sctp_chk_and_updt_saddr(int hindex, sctp_ipif_t *ipif, sctp_stack_t *sctps) 933 3510 vi117747 { 934 3510 vi117747 int cnt; 935 3510 vi117747 sctp_ipif_t *sipif; 936 3510 vi117747 937 3510 vi117747 ASSERT(sctps->sctps_g_ipifs[hindex].ipif_count > 0); 938 3510 vi117747 ASSERT(ipif->sctp_ipif_state == SCTP_IPIFS_UP); 939 3510 vi117747 940 3510 vi117747 sipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list); 941 3510 vi117747 for (cnt = 0; cnt < sctps->sctps_g_ipifs[hindex].ipif_count; cnt++) { 942 3510 vi117747 rw_enter(&sipif->sctp_ipif_lock, RW_WRITER); 943 3510 vi117747 if (sipif->sctp_ipif_id != ipif->sctp_ipif_id && 944 3510 vi117747 IN6_ARE_ADDR_EQUAL(&sipif->sctp_ipif_saddr, 945 9705 Venu &ipif->sctp_ipif_saddr) && sipif->sctp_ipif_refcnt > 0 && 946 9705 Venu (!SCTP_IS_IPIF_LOOPBACK(ipif) || ipif->sctp_ipif_zoneid == 947 9705 Venu sipif->sctp_ipif_zoneid)) { 948 3510 vi117747 /* 949 3510 vi117747 * There can only be one address up at any time 950 3510 vi117747 * and we are here because ipif has been brought 951 3510 vi117747 * up. 952 3510 vi117747 */ 953 3510 vi117747 ASSERT(sipif->sctp_ipif_state != SCTP_IPIFS_UP); 954 3510 vi117747 /* 955 3510 vi117747 * Someone has a reference to this we need to update to 956 3510 vi117747 * point to the new sipif. 957 3510 vi117747 */ 958 3510 vi117747 sctp_update_saddrs(sipif, ipif, hindex, sctps); 959 3510 vi117747 } 960 3510 vi117747 rw_exit(&sipif->sctp_ipif_lock); 961 3510 vi117747 sipif = list_next(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list, 962 3510 vi117747 sipif); 963 3510 vi117747 } 964 3510 vi117747 } 965 3510 vi117747 966 3510 vi117747 /* 967 3510 vi117747 * Insert a new SCTP ipif using 'ipif'. v6addr is the address that existed 968 3510 vi117747 * prior to the current address in 'ipif'. Only when an existing address 969 3510 vi117747 * is changed on an IPIF, will v6addr be specified. If the IPIF already 970 3510 vi117747 * exists in the global SCTP ipif table, then we either removed it, if 971 3510 vi117747 * it doesn't have any existing reference, or mark it condemned otherwise. 972 3510 vi117747 * If an address is being brought up (IPIF_UP), then we need to scan 973 3510 vi117747 * the SCTP list to check if there is any SCTP that points to the *same* 974 3510 vi117747 * address on a different SCTP ipif and update in that case. 975 3510 vi117747 */ 976 3510 vi117747 void 977 3510 vi117747 sctp_update_ipif_addr(ipif_t *ipif, in6_addr_t v6addr) 978 3510 vi117747 { 979 3510 vi117747 ill_t *ill = ipif->ipif_ill; 980 3510 vi117747 int i; 981 3510 vi117747 sctp_ill_t *sctp_ill; 982 3510 vi117747 sctp_ill_t *osctp_ill; 983 3510 vi117747 sctp_ipif_t *sctp_ipif = NULL; 984 3510 vi117747 sctp_ipif_t *osctp_ipif = NULL; 985 3510 vi117747 uint_t ill_index; 986 3510 vi117747 int hindex; 987 3510 vi117747 sctp_stack_t *sctps; 988 3510 vi117747 989 3510 vi117747 sctps = ipif->ipif_ill->ill_ipst->ips_netstack->netstack_sctp; 990 3510 vi117747 991 3510 vi117747 /* Index for new address */ 992 3510 vi117747 hindex = SCTP_IPIF_ADDR_HASH(ipif->ipif_v6lcl_addr, ill->ill_isv6); 993 3510 vi117747 994 3510 vi117747 /* 995 3510 vi117747 * The address on this IPIF is changing, we need to look for 996 3510 vi117747 * this old address and mark it condemned, before creating 997 3510 vi117747 * one for the new address. 998 3510 vi117747 */ 999 3510 vi117747 osctp_ipif = sctp_lookup_ipif_addr(&v6addr, B_FALSE, 1000 3510 vi117747 ipif->ipif_zoneid, B_TRUE, SCTP_ILL_TO_PHYINDEX(ill), 1001 3510 vi117747 ipif->ipif_seqid, B_FALSE, sctps); 1002 3510 vi117747 1003 3510 vi117747 rw_enter(&sctps->sctps_g_ills_lock, RW_READER); 1004 3510 vi117747 rw_enter(&sctps->sctps_g_ipifs_lock, RW_WRITER); 1005 3510 vi117747 1006 3510 vi117747 ill_index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill)); 1007 3510 vi117747 sctp_ill = list_head(&sctps->sctps_g_ills[ill_index].sctp_ill_list); 1008 3510 vi117747 for (i = 0; i < sctps->sctps_g_ills[ill_index].ill_count; i++) { 1009 4311 vi117747 if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill) && 1010 4311 vi117747 sctp_ill->sctp_ill_isv6 == ill->ill_isv6) { 1011 3510 vi117747 break; 1012 4311 vi117747 } 1013 3510 vi117747 sctp_ill = list_next( 1014 3510 vi117747 &sctps->sctps_g_ills[ill_index].sctp_ill_list, sctp_ill); 1015 3510 vi117747 } 1016 3510 vi117747 1017 3510 vi117747 if (sctp_ill == NULL) { 1018 4311 vi117747 ip1dbg(("sctp_update_ipif_addr: ill not found ..\n")); 1019 3510 vi117747 rw_exit(&sctps->sctps_g_ipifs_lock); 1020 3510 vi117747 rw_exit(&sctps->sctps_g_ills_lock); 1021 4311 vi117747 return; 1022 3510 vi117747 } 1023 3510 vi117747 1024 3510 vi117747 if (osctp_ipif != NULL) { 1025 3510 vi117747 1026 3510 vi117747 /* The address is the same? */ 1027 3510 vi117747 if (IN6_ARE_ADDR_EQUAL(&ipif->ipif_v6lcl_addr, &v6addr)) { 1028 3510 vi117747 boolean_t chk_n_updt = B_FALSE; 1029 3510 vi117747 1030 3510 vi117747 rw_downgrade(&sctps->sctps_g_ipifs_lock); 1031 3510 vi117747 rw_enter(&osctp_ipif->sctp_ipif_lock, RW_WRITER); 1032 3510 vi117747 if (ipif->ipif_flags & IPIF_UP && 1033 3510 vi117747 osctp_ipif->sctp_ipif_state != SCTP_IPIFS_UP) { 1034 3510 vi117747 osctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP; 1035 3510 vi117747 chk_n_updt = B_TRUE; 1036 3510 vi117747 } else { 1037 3510 vi117747 osctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN; 1038 3510 vi117747 } 1039 3510 vi117747 osctp_ipif->sctp_ipif_flags = ipif->ipif_flags; 1040 3510 vi117747 rw_exit(&osctp_ipif->sctp_ipif_lock); 1041 3510 vi117747 if (chk_n_updt) { 1042 3510 vi117747 sctp_chk_and_updt_saddr(hindex, osctp_ipif, 1043 3510 vi117747 sctps); 1044 3510 vi117747 } 1045 3510 vi117747 rw_exit(&sctps->sctps_g_ipifs_lock); 1046 3510 vi117747 rw_exit(&sctps->sctps_g_ills_lock); 1047 3510 vi117747 return; 1048 3510 vi117747 } 1049 3510 vi117747 /* 1050 3510 vi117747 * We are effectively removing this address from the ILL. 1051 3510 vi117747 */ 1052 3510 vi117747 if (osctp_ipif->sctp_ipif_refcnt != 0) { 1053 3510 vi117747 osctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED; 1054 3510 vi117747 } else { 1055 3510 vi117747 list_t *ipif_list; 1056 3510 vi117747 int ohindex; 1057 3510 vi117747 1058 3510 vi117747 osctp_ill = osctp_ipif->sctp_ipif_ill; 1059 3510 vi117747 /* hash index for the old one */ 1060 3510 vi117747 ohindex = SCTP_IPIF_ADDR_HASH( 1061 3510 vi117747 osctp_ipif->sctp_ipif_saddr, 1062 3510 vi117747 osctp_ipif->sctp_ipif_isv6); 1063 3510 vi117747 1064 3510 vi117747 ipif_list = 1065 3510 vi117747 &sctps->sctps_g_ipifs[ohindex].sctp_ipif_list; 1066 3510 vi117747 1067 3510 vi117747 list_remove(ipif_list, (void *)osctp_ipif); 1068 3510 vi117747 sctps->sctps_g_ipifs[ohindex].ipif_count--; 1069 3510 vi117747 sctps->sctps_g_ipifs_count--; 1070 3510 vi117747 rw_destroy(&osctp_ipif->sctp_ipif_lock); 1071 3510 vi117747 kmem_free(osctp_ipif, sizeof (sctp_ipif_t)); 1072 3510 vi117747 (void) atomic_add_32_nv(&osctp_ill->sctp_ill_ipifcnt, 1073 3510 vi117747 -1); 1074 3510 vi117747 } 1075 3510 vi117747 } 1076 3510 vi117747 1077 3510 vi117747 sctp_ipif = kmem_zalloc(sizeof (sctp_ipif_t), KM_NOSLEEP); 1078 3510 vi117747 /* Try again? */ 1079 3510 vi117747 if (sctp_ipif == NULL) { 1080 4311 vi117747 cmn_err(CE_WARN, "sctp_update_ipif_addr: error adding " 1081 4311 vi117747 "IPIF %p to SCTP's IPIF list", (void *)ipif); 1082 3510 vi117747 rw_exit(&sctps->sctps_g_ipifs_lock); 1083 3510 vi117747 rw_exit(&sctps->sctps_g_ills_lock); 1084 3510 vi117747 return; 1085 3510 vi117747 } 1086 3510 vi117747 sctps->sctps_g_ipifs_count++; 1087 3510 vi117747 rw_init(&sctp_ipif->sctp_ipif_lock, NULL, RW_DEFAULT, NULL); 1088 3510 vi117747 sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr; 1089 3510 vi117747 sctp_ipif->sctp_ipif_ill = sctp_ill; 1090 3510 vi117747 sctp_ipif->sctp_ipif_isv6 = ill->ill_isv6; 1091 3510 vi117747 sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid; 1092 3510 vi117747 sctp_ipif->sctp_ipif_id = ipif->ipif_seqid; 1093 3510 vi117747 if (ipif->ipif_flags & IPIF_UP) 1094 3510 vi117747 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP; 1095 3510 vi117747 else 1096 3510 vi117747 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN; 1097 3510 vi117747 sctp_ipif->sctp_ipif_flags = ipif->ipif_flags; 1098 3510 vi117747 /* 1099 3510 vi117747 * We add it to the head so that it is quicker to find good/recent 1100 3510 vi117747 * additions. 1101 3510 vi117747 */ 1102 3510 vi117747 list_insert_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list, 1103 3510 vi117747 (void *)sctp_ipif); 1104 3510 vi117747 sctps->sctps_g_ipifs[hindex].ipif_count++; 1105 3510 vi117747 atomic_add_32(&sctp_ill->sctp_ill_ipifcnt, 1); 1106 3510 vi117747 if (sctp_ipif->sctp_ipif_state == SCTP_IPIFS_UP) 1107 3510 vi117747 sctp_chk_and_updt_saddr(hindex, sctp_ipif, sctps); 1108 3510 vi117747 rw_exit(&sctps->sctps_g_ipifs_lock); 1109 3510 vi117747 rw_exit(&sctps->sctps_g_ills_lock); 1110 3510 vi117747 } 1111 3510 vi117747 1112 0 stevel /* Insert, Remove, Mark up or Mark down the ipif */ 1113 0 stevel void 1114 0 stevel sctp_update_ipif(ipif_t *ipif, int op) 1115 0 stevel { 1116 0 stevel ill_t *ill = ipif->ipif_ill; 1117 0 stevel int i; 1118 0 stevel sctp_ill_t *sctp_ill; 1119 0 stevel sctp_ipif_t *sctp_ipif; 1120 0 stevel uint_t ill_index; 1121 3510 vi117747 uint_t hindex; 1122 3448 dh155122 netstack_t *ns = ipif->ipif_ill->ill_ipst->ips_netstack; 1123 3448 dh155122 sctp_stack_t *sctps = ns->netstack_sctp; 1124 0 stevel 1125 0 stevel ip2dbg(("sctp_update_ipif: %s %d\n", ill->ill_name, ipif->ipif_seqid)); 1126 0 stevel 1127 3448 dh155122 rw_enter(&sctps->sctps_g_ills_lock, RW_READER); 1128 3448 dh155122 rw_enter(&sctps->sctps_g_ipifs_lock, RW_WRITER); 1129 0 stevel 1130 0 stevel ill_index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill)); 1131 3448 dh155122 sctp_ill = list_head(&sctps->sctps_g_ills[ill_index].sctp_ill_list); 1132 3448 dh155122 for (i = 0; i < sctps->sctps_g_ills[ill_index].ill_count; i++) { 1133 4311 vi117747 if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill) && 1134 4311 vi117747 sctp_ill->sctp_ill_isv6 == ill->ill_isv6) { 1135 0 stevel break; 1136 4311 vi117747 } 1137 3448 dh155122 sctp_ill = list_next( 1138 3448 dh155122 &sctps->sctps_g_ills[ill_index].sctp_ill_list, sctp_ill); 1139 0 stevel } 1140 0 stevel if (sctp_ill == NULL) { 1141 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 1142 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 1143 0 stevel return; 1144 0 stevel } 1145 0 stevel 1146 3510 vi117747 hindex = SCTP_IPIF_ADDR_HASH(ipif->ipif_v6lcl_addr, 1147 3510 vi117747 ipif->ipif_ill->ill_isv6); 1148 3510 vi117747 sctp_ipif = list_head(&sctps->sctps_g_ipifs[hindex].sctp_ipif_list); 1149 3510 vi117747 for (i = 0; i < sctps->sctps_g_ipifs[hindex].ipif_count; i++) { 1150 3510 vi117747 if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid) { 1151 3510 vi117747 ASSERT(IN6_ARE_ADDR_EQUAL(&sctp_ipif->sctp_ipif_saddr, 1152 3510 vi117747 &ipif->ipif_v6lcl_addr)); 1153 0 stevel break; 1154 3510 vi117747 } 1155 3448 dh155122 sctp_ipif = list_next( 1156 3510 vi117747 &sctps->sctps_g_ipifs[hindex].sctp_ipif_list, 1157 0 stevel sctp_ipif); 1158 0 stevel } 1159 3510 vi117747 if (sctp_ipif == NULL) { 1160 0 stevel ip1dbg(("sctp_update_ipif: null sctp_ipif for %d\n", op)); 1161 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 1162 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 1163 0 stevel return; 1164 0 stevel } 1165 3510 vi117747 ASSERT(sctp_ill == sctp_ipif->sctp_ipif_ill); 1166 0 stevel switch (op) { 1167 0 stevel case SCTP_IPIF_REMOVE: 1168 0 stevel { 1169 0 stevel list_t *ipif_list; 1170 0 stevel list_t *ill_list; 1171 0 stevel 1172 3448 dh155122 ill_list = &sctps->sctps_g_ills[ill_index].sctp_ill_list; 1173 3510 vi117747 ipif_list = &sctps->sctps_g_ipifs[hindex].sctp_ipif_list; 1174 0 stevel if (sctp_ipif->sctp_ipif_refcnt != 0) { 1175 0 stevel sctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED; 1176 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 1177 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 1178 0 stevel return; 1179 0 stevel } 1180 0 stevel list_remove(ipif_list, (void *)sctp_ipif); 1181 3510 vi117747 sctps->sctps_g_ipifs[hindex].ipif_count--; 1182 3448 dh155122 sctps->sctps_g_ipifs_count--; 1183 0 stevel rw_destroy(&sctp_ipif->sctp_ipif_lock); 1184 0 stevel kmem_free(sctp_ipif, sizeof (sctp_ipif_t)); 1185 0 stevel (void) atomic_add_32_nv(&sctp_ill->sctp_ill_ipifcnt, -1); 1186 3448 dh155122 if (rw_tryupgrade(&sctps->sctps_g_ills_lock) != 0) { 1187 3448 dh155122 rw_downgrade(&sctps->sctps_g_ipifs_lock); 1188 0 stevel if (sctp_ill->sctp_ill_ipifcnt == 0 && 1189 0 stevel sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) { 1190 0 stevel list_remove(ill_list, (void *)sctp_ill); 1191 3448 dh155122 sctps->sctps_ills_count--; 1192 3448 dh155122 sctps->sctps_g_ills[ill_index].ill_count--; 1193 0 stevel kmem_free(sctp_ill->sctp_ill_name, 1194 0 stevel sctp_ill->sctp_ill_name_length); 1195 0 stevel kmem_free(sctp_ill, sizeof (sctp_ill_t)); 1196 0 stevel } 1197 0 stevel } 1198 0 stevel break; 1199 0 stevel } 1200 0 stevel 1201 0 stevel case SCTP_IPIF_UP: 1202 0 stevel 1203 3448 dh155122 rw_downgrade(&sctps->sctps_g_ipifs_lock); 1204 0 stevel rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER); 1205 0 stevel sctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP; 1206 432 vi117747 sctp_ipif->sctp_ipif_flags = ipif->ipif_flags; 1207 0 stevel rw_exit(&sctp_ipif->sctp_ipif_lock); 1208 3510 vi117747 sctp_chk_and_updt_saddr(hindex, sctp_ipif, 1209 3510 vi117747 ipif->ipif_ill->ill_ipst->ips_netstack->netstack_sctp); 1210 0 stevel 1211 0 stevel break; 1212 0 stevel 1213 0 stevel case SCTP_IPIF_UPDATE: 1214 0 stevel 1215 3448 dh155122 rw_downgrade(&sctps->sctps_g_ipifs_lock); 1216 0 stevel rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER); 1217 0 stevel sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid; 1218 432 vi117747 sctp_ipif->sctp_ipif_flags = ipif->ipif_flags; 1219 0 stevel rw_exit(&sctp_ipif->sctp_ipif_lock); 1220 0 stevel 1221 0 stevel break; 1222 0 stevel 1223 0 stevel case SCTP_IPIF_DOWN: 1224 0 stevel 1225 3448 dh155122 rw_downgrade(&sctps->sctps_g_ipifs_lock); 1226 0 stevel rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER); 1227 0 stevel sctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN; 1228 3510 vi117747 sctp_ipif->sctp_ipif_flags = ipif->ipif_flags; 1229 0 stevel rw_exit(&sctp_ipif->sctp_ipif_lock); 1230 0 stevel 1231 0 stevel break; 1232 0 stevel } 1233 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 1234 3448 dh155122 rw_exit(&sctps->sctps_g_ills_lock); 1235 0 stevel } 1236 0 stevel 1237 0 stevel /* 1238 0 stevel * SCTP source address list manipulaton, locking not used (except for 1239 0 stevel * sctp locking by the caller. 1240 0 stevel */ 1241 0 stevel 1242 0 stevel /* Remove a specific saddr from the list */ 1243 0 stevel void 1244 0 stevel sctp_del_saddr(sctp_t *sctp, sctp_saddr_ipif_t *sp) 1245 0 stevel { 1246 0 stevel if (sctp->sctp_conn_tfp != NULL) 1247 0 stevel mutex_enter(&sctp->sctp_conn_tfp->tf_lock); 1248 0 stevel 1249 0 stevel if (sctp->sctp_listen_tfp != NULL) 1250 0 stevel mutex_enter(&sctp->sctp_listen_tfp->tf_lock); 1251 0 stevel 1252 0 stevel sctp_ipif_hash_remove(sctp, sp->saddr_ipifp); 1253 0 stevel 1254 432 vi117747 if (sctp->sctp_bound_to_all == 1) 1255 0 stevel sctp->sctp_bound_to_all = 0; 1256 0 stevel 1257 0 stevel if (sctp->sctp_conn_tfp != NULL) 1258 0 stevel mutex_exit(&sctp->sctp_conn_tfp->tf_lock); 1259 0 stevel 1260 0 stevel if (sctp->sctp_listen_tfp != NULL) 1261 0 stevel mutex_exit(&sctp->sctp_listen_tfp->tf_lock); 1262 0 stevel } 1263 0 stevel 1264 0 stevel /* 1265 0 stevel * Delete source address from the existing list. No error checking done here 1266 0 stevel * Called with no locks held. 1267 0 stevel */ 1268 0 stevel void 1269 0 stevel sctp_del_saddr_list(sctp_t *sctp, const void *addrs, int addcnt, 1270 0 stevel boolean_t fanout_locked) 1271 0 stevel { 1272 0 stevel struct sockaddr_in *sin4; 1273 0 stevel struct sockaddr_in6 *sin6; 1274 0 stevel int cnt; 1275 0 stevel in6_addr_t addr; 1276 0 stevel sctp_ipif_t *sctp_ipif; 1277 852 vi117747 int ifindex = 0; 1278 11042 Erik conn_t *connp = sctp->sctp_connp; 1279 0 stevel 1280 852 vi117747 ASSERT(sctp->sctp_nsaddrs >= addcnt); 1281 0 stevel 1282 0 stevel if (!fanout_locked) { 1283 0 stevel if (sctp->sctp_conn_tfp != NULL) 1284 0 stevel mutex_enter(&sctp->sctp_conn_tfp->tf_lock); 1285 0 stevel if (sctp->sctp_listen_tfp != NULL) 1286 0 stevel mutex_enter(&sctp->sctp_listen_tfp->tf_lock); 1287 0 stevel } 1288 0 stevel 1289 0 stevel for (cnt = 0; cnt < addcnt; cnt++) { 1290 11042 Erik switch (connp->conn_family) { 1291 0 stevel case AF_INET: 1292 0 stevel sin4 = (struct sockaddr_in *)addrs + cnt; 1293 0 stevel IN6_INADDR_TO_V4MAPPED(&sin4->sin_addr, &addr); 1294 0 stevel break; 1295 0 stevel 1296 0 stevel case AF_INET6: 1297 0 stevel sin6 = (struct sockaddr_in6 *)addrs + cnt; 1298 0 stevel addr = sin6->sin6_addr; 1299 852 vi117747 ifindex = sin6->sin6_scope_id; 1300 0 stevel break; 1301 0 stevel } 1302 3510 vi117747 sctp_ipif = sctp_lookup_ipif_addr(&addr, B_FALSE, 1303 11042 Erik IPCL_ZONEID(connp), !connp->conn_allzones, 1304 3510 vi117747 ifindex, 0, B_TRUE, sctp->sctp_sctps); 1305 0 stevel ASSERT(sctp_ipif != NULL); 1306 0 stevel sctp_ipif_hash_remove(sctp, sctp_ipif); 1307 0 stevel } 1308 432 vi117747 if (sctp->sctp_bound_to_all == 1) 1309 0 stevel sctp->sctp_bound_to_all = 0; 1310 0 stevel 1311 0 stevel if (!fanout_locked) { 1312 0 stevel if (sctp->sctp_conn_tfp != NULL) 1313 0 stevel mutex_exit(&sctp->sctp_conn_tfp->tf_lock); 1314 0 stevel if (sctp->sctp_listen_tfp != NULL) 1315 0 stevel mutex_exit(&sctp->sctp_listen_tfp->tf_lock); 1316 0 stevel } 1317 0 stevel } 1318 0 stevel 1319 0 stevel /* 1320 0 stevel * Given an address get the corresponding entry from the list 1321 0 stevel * Called with no locks held. 1322 0 stevel */ 1323 0 stevel sctp_saddr_ipif_t * 1324 852 vi117747 sctp_saddr_lookup(sctp_t *sctp, in6_addr_t *addr, uint_t ifindex) 1325 0 stevel { 1326 3510 vi117747 int cnt; 1327 3510 vi117747 sctp_saddr_ipif_t *ipif_obj; 1328 3510 vi117747 int hindex; 1329 0 stevel sctp_ipif_t *sctp_ipif; 1330 0 stevel 1331 3510 vi117747 hindex = SCTP_IPIF_ADDR_HASH(*addr, !IN6_IS_ADDR_V4MAPPED(addr)); 1332 3510 vi117747 if (sctp->sctp_saddrs[hindex].ipif_count == 0) 1333 0 stevel return (NULL); 1334 0 stevel 1335 3510 vi117747 ipif_obj = list_head(&sctp->sctp_saddrs[hindex].sctp_ipif_list); 1336 3510 vi117747 for (cnt = 0; cnt < sctp->sctp_saddrs[hindex].ipif_count; cnt++) { 1337 3510 vi117747 sctp_ipif = ipif_obj->saddr_ipifp; 1338 3510 vi117747 /* 1339 3510 vi117747 * Zone check shouldn't be needed. 1340 3510 vi117747 */ 1341 3510 vi117747 if (IN6_ARE_ADDR_EQUAL(addr, &sctp_ipif->sctp_ipif_saddr) && 1342 3510 vi117747 (ifindex == 0 || 1343 3510 vi117747 ifindex == sctp_ipif->sctp_ipif_ill->sctp_ill_index) && 1344 3510 vi117747 SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state)) { 1345 3510 vi117747 return (ipif_obj); 1346 3510 vi117747 } 1347 3510 vi117747 ipif_obj = list_next(&sctp->sctp_saddrs[hindex].sctp_ipif_list, 1348 3510 vi117747 ipif_obj); 1349 3510 vi117747 } 1350 3510 vi117747 return (NULL); 1351 0 stevel } 1352 0 stevel 1353 432 vi117747 /* Given an address, add it to the source address list */ 1354 432 vi117747 int 1355 852 vi117747 sctp_saddr_add_addr(sctp_t *sctp, in6_addr_t *addr, uint_t ifindex) 1356 432 vi117747 { 1357 432 vi117747 sctp_ipif_t *sctp_ipif; 1358 11042 Erik conn_t *connp = sctp->sctp_connp; 1359 432 vi117747 1360 11042 Erik sctp_ipif = sctp_lookup_ipif_addr(addr, B_TRUE, IPCL_ZONEID(connp), 1361 11042 Erik !connp->conn_allzones, ifindex, 0, B_TRUE, sctp->sctp_sctps); 1362 432 vi117747 if (sctp_ipif == NULL) 1363 432 vi117747 return (EINVAL); 1364 432 vi117747 1365 3510 vi117747 if (sctp_ipif_hash_insert(sctp, sctp_ipif, KM_NOSLEEP, B_FALSE, 1366 3510 vi117747 B_FALSE) != 0) { 1367 432 vi117747 SCTP_IPIF_REFRELE(sctp_ipif); 1368 432 vi117747 return (EINVAL); 1369 432 vi117747 } 1370 432 vi117747 return (0); 1371 432 vi117747 } 1372 432 vi117747 1373 432 vi117747 /* 1374 432 vi117747 * Remove or mark as dontsrc addresses that are currently not part of the 1375 432 vi117747 * association. One would delete addresses when processing an INIT and 1376 432 vi117747 * mark as dontsrc when processing an INIT-ACK. 1377 432 vi117747 */ 1378 432 vi117747 void 1379 4818 kcpoon sctp_check_saddr(sctp_t *sctp, int supp_af, boolean_t delete, 1380 4818 kcpoon in6_addr_t *no_del_addr) 1381 432 vi117747 { 1382 432 vi117747 int i; 1383 432 vi117747 int l; 1384 432 vi117747 sctp_saddr_ipif_t *obj; 1385 432 vi117747 int scanned = 0; 1386 432 vi117747 int naddr; 1387 432 vi117747 int nsaddr; 1388 11042 Erik conn_t *connp = sctp->sctp_connp; 1389 432 vi117747 1390 432 vi117747 ASSERT(!sctp->sctp_loopback && !sctp->sctp_linklocal && supp_af != 0); 1391 432 vi117747 1392 432 vi117747 /* 1393 432 vi117747 * Irregardless of the supported address in the INIT, v4 1394 432 vi117747 * must be supported. 1395 432 vi117747 */ 1396 11042 Erik if (connp->conn_family == AF_INET) 1397 432 vi117747 supp_af = PARM_SUPP_V4; 1398 432 vi117747 1399 432 vi117747 nsaddr = sctp->sctp_nsaddrs; 1400 432 vi117747 for (i = 0; i < SCTP_IPIF_HASH; i++) { 1401 432 vi117747 if (sctp->sctp_saddrs[i].ipif_count == 0) 1402 432 vi117747 continue; 1403 432 vi117747 obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list); 1404 432 vi117747 naddr = sctp->sctp_saddrs[i].ipif_count; 1405 432 vi117747 for (l = 0; l < naddr; l++) { 1406 432 vi117747 sctp_ipif_t *ipif; 1407 432 vi117747 1408 432 vi117747 ipif = obj->saddr_ipifp; 1409 432 vi117747 scanned++; 1410 4818 kcpoon 1411 4818 kcpoon if (IN6_ARE_ADDR_EQUAL(&ipif->sctp_ipif_saddr, 1412 4818 kcpoon no_del_addr)) { 1413 4818 kcpoon goto next_obj; 1414 4818 kcpoon } 1415 432 vi117747 1416 432 vi117747 /* 1417 432 vi117747 * Delete/mark dontsrc loopback/linklocal addresses and 1418 432 vi117747 * unsupported address. 1419 852 vi117747 * On a clustered node, we trust the clustering module 1420 852 vi117747 * to do the right thing w.r.t loopback addresses, so 1421 852 vi117747 * we ignore loopback addresses in this check. 1422 432 vi117747 */ 1423 852 vi117747 if ((SCTP_IS_IPIF_LOOPBACK(ipif) && 1424 852 vi117747 cl_sctp_check_addrs == NULL) || 1425 852 vi117747 SCTP_IS_IPIF_LINKLOCAL(ipif) || 1426 432 vi117747 SCTP_UNSUPP_AF(ipif, supp_af)) { 1427 432 vi117747 if (!delete) { 1428 432 vi117747 obj->saddr_ipif_unconfirmed = 1; 1429 432 vi117747 goto next_obj; 1430 432 vi117747 } 1431 432 vi117747 if (sctp->sctp_bound_to_all == 1) 1432 432 vi117747 sctp->sctp_bound_to_all = 0; 1433 432 vi117747 if (scanned < nsaddr) { 1434 432 vi117747 obj = list_next(&sctp->sctp_saddrs[i]. 1435 432 vi117747 sctp_ipif_list, obj); 1436 432 vi117747 sctp_ipif_hash_remove(sctp, ipif); 1437 432 vi117747 continue; 1438 432 vi117747 } 1439 432 vi117747 sctp_ipif_hash_remove(sctp, ipif); 1440 432 vi117747 } 1441 432 vi117747 next_obj: 1442 432 vi117747 if (scanned >= nsaddr) 1443 432 vi117747 return; 1444 432 vi117747 obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list, 1445 432 vi117747 obj); 1446 432 vi117747 } 1447 432 vi117747 } 1448 432 vi117747 } 1449 432 vi117747 1450 432 vi117747 1451 0 stevel /* Get the first valid address from the list. Called with no locks held */ 1452 0 stevel in6_addr_t 1453 4818 kcpoon sctp_get_valid_addr(sctp_t *sctp, boolean_t isv6, boolean_t *addr_set) 1454 0 stevel { 1455 0 stevel int i; 1456 0 stevel int l; 1457 0 stevel sctp_saddr_ipif_t *obj; 1458 0 stevel int scanned = 0; 1459 0 stevel in6_addr_t addr; 1460 0 stevel 1461 0 stevel for (i = 0; i < SCTP_IPIF_HASH; i++) { 1462 0 stevel if (sctp->sctp_saddrs[i].ipif_count == 0) 1463 0 stevel continue; 1464 0 stevel obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list); 1465 0 stevel for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) { 1466 0 stevel sctp_ipif_t *ipif; 1467 0 stevel 1468 0 stevel ipif = obj->saddr_ipifp; 1469 432 vi117747 if (!SCTP_DONT_SRC(obj) && 1470 0 stevel ipif->sctp_ipif_isv6 == isv6 && 1471 432 vi117747 ipif->sctp_ipif_state == SCTP_IPIFS_UP) { 1472 4818 kcpoon *addr_set = B_TRUE; 1473 0 stevel return (ipif->sctp_ipif_saddr); 1474 0 stevel } 1475 0 stevel scanned++; 1476 0 stevel if (scanned >= sctp->sctp_nsaddrs) 1477 0 stevel goto got_none; 1478 0 stevel obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list, 1479 0 stevel obj); 1480 0 stevel } 1481 0 stevel } 1482 0 stevel got_none: 1483 0 stevel /* Need to double check this */ 1484 0 stevel if (isv6 == B_TRUE) 1485 0 stevel addr = ipv6_all_zeros; 1486 0 stevel else 1487 0 stevel IN6_IPADDR_TO_V4MAPPED(0, &addr); 1488 4818 kcpoon *addr_set = B_FALSE; 1489 0 stevel return (addr); 1490 0 stevel } 1491 0 stevel 1492 0 stevel /* 1493 0 stevel * Return the list of local addresses of an association. The parameter 1494 0 stevel * myaddrs is supposed to be either (struct sockaddr_in *) or (struct 1495 0 stevel * sockaddr_in6 *) depending on the address family. 1496 0 stevel */ 1497 0 stevel int 1498 0 stevel sctp_getmyaddrs(void *conn, void *myaddrs, int *addrcnt) 1499 0 stevel { 1500 0 stevel int i; 1501 0 stevel int l; 1502 0 stevel sctp_saddr_ipif_t *obj; 1503 0 stevel sctp_t *sctp = (sctp_t *)conn; 1504 11042 Erik conn_t *connp = sctp->sctp_connp; 1505 11042 Erik int family = connp->conn_family; 1506 0 stevel int max = *addrcnt; 1507 0 stevel size_t added = 0; 1508 0 stevel struct sockaddr_in6 *sin6; 1509 0 stevel struct sockaddr_in *sin4; 1510 0 stevel int scanned = 0; 1511 0 stevel boolean_t skip_lback = B_FALSE; 1512 11042 Erik ip_xmit_attr_t *ixa = connp->conn_ixa; 1513 0 stevel 1514 0 stevel if (sctp->sctp_nsaddrs == 0) 1515 0 stevel return (EINVAL); 1516 0 stevel 1517 852 vi117747 /* 1518 852 vi117747 * Skip loopback addresses for non-loopback assoc., ignore 1519 852 vi117747 * this on a clustered node. 1520 852 vi117747 */ 1521 852 vi117747 if (sctp->sctp_state >= SCTPS_ESTABLISHED && !sctp->sctp_loopback && 1522 852 vi117747 (cl_sctp_check_addrs == NULL)) { 1523 0 stevel skip_lback = B_TRUE; 1524 852 vi117747 } 1525 852 vi117747 1526 0 stevel for (i = 0; i < SCTP_IPIF_HASH; i++) { 1527 0 stevel if (sctp->sctp_saddrs[i].ipif_count == 0) 1528 0 stevel continue; 1529 0 stevel obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list); 1530 0 stevel for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) { 1531 0 stevel sctp_ipif_t *ipif = obj->saddr_ipifp; 1532 0 stevel in6_addr_t addr = ipif->sctp_ipif_saddr; 1533 0 stevel 1534 0 stevel scanned++; 1535 0 stevel if ((ipif->sctp_ipif_state == SCTP_IPIFS_CONDEMNED) || 1536 432 vi117747 SCTP_DONT_SRC(obj) || 1537 852 vi117747 (SCTP_IS_IPIF_LOOPBACK(ipif) && skip_lback)) { 1538 0 stevel if (scanned >= sctp->sctp_nsaddrs) 1539 0 stevel goto done; 1540 0 stevel obj = list_next(&sctp->sctp_saddrs[i]. 1541 0 stevel sctp_ipif_list, obj); 1542 0 stevel continue; 1543 0 stevel } 1544 0 stevel switch (family) { 1545 0 stevel case AF_INET: 1546 0 stevel sin4 = (struct sockaddr_in *)myaddrs + added; 1547 0 stevel sin4->sin_family = AF_INET; 1548 11042 Erik sin4->sin_port = connp->conn_lport; 1549 0 stevel IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1550 0 stevel break; 1551 0 stevel 1552 0 stevel case AF_INET6: 1553 0 stevel sin6 = (struct sockaddr_in6 *)myaddrs + added; 1554 0 stevel sin6->sin6_family = AF_INET6; 1555 11042 Erik sin6->sin6_port = connp->conn_lport; 1556 0 stevel sin6->sin6_addr = addr; 1557 11042 Erik /* 1558 11042 Erik * Note that flowinfo is only returned for 1559 11042 Erik * getpeername just like for TCP and UDP. 1560 11042 Erik */ 1561 11042 Erik sin6->sin6_flowinfo = 0; 1562 11042 Erik 1563 11042 Erik if (IN6_IS_ADDR_LINKSCOPE(&sin6->sin6_addr) && 1564 11042 Erik (ixa->ixa_flags & IXAF_SCOPEID_SET)) 1565 11042 Erik sin6->sin6_scope_id = ixa->ixa_scopeid; 1566 11042 Erik else 1567 11042 Erik sin6->sin6_scope_id = 0; 1568 11042 Erik sin6->__sin6_src_id = 0; 1569 0 stevel break; 1570 0 stevel } 1571 0 stevel added++; 1572 0 stevel if (added >= max || scanned >= sctp->sctp_nsaddrs) 1573 0 stevel goto done; 1574 0 stevel obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list, 1575 0 stevel obj); 1576 0 stevel } 1577 0 stevel } 1578 0 stevel done: 1579 0 stevel *addrcnt = added; 1580 0 stevel return (0); 1581 0 stevel } 1582 0 stevel 1583 0 stevel /* 1584 252 vi117747 * Given the supported address family, walk through the source address list 1585 252 vi117747 * and return the total length of the available addresses. If 'p' is not 1586 252 vi117747 * null, construct the parameter list for the addresses in 'p'. 1587 432 vi117747 * 'modify' will only be set when we want the source address list to 1588 432 vi117747 * be modified. The source address list will be modified only when 1589 432 vi117747 * generating an INIT chunk. For generating an INIT-ACK 'modify' will 1590 432 vi117747 * be false since the 'sctp' will be that of the listener. 1591 0 stevel */ 1592 0 stevel size_t 1593 432 vi117747 sctp_saddr_info(sctp_t *sctp, int supp_af, uchar_t *p, boolean_t modify) 1594 0 stevel { 1595 0 stevel int i; 1596 0 stevel int l; 1597 0 stevel sctp_saddr_ipif_t *obj; 1598 252 vi117747 size_t paramlen = 0; 1599 0 stevel sctp_parm_hdr_t *hdr; 1600 0 stevel int scanned = 0; 1601 432 vi117747 int naddr; 1602 432 vi117747 int nsaddr; 1603 852 vi117747 boolean_t del_ll = B_FALSE; 1604 852 vi117747 boolean_t del_lb = B_FALSE; 1605 0 stevel 1606 852 vi117747 1607 852 vi117747 /* 1608 852 vi117747 * On a clustered node don't bother changing anything 1609 852 vi117747 * on the loopback interface. 1610 852 vi117747 */ 1611 852 vi117747 if (modify && !sctp->sctp_loopback && (cl_sctp_check_addrs == NULL)) 1612 852 vi117747 del_lb = B_TRUE; 1613 852 vi117747 1614 852 vi117747 if (modify && !sctp->sctp_linklocal) 1615 852 vi117747 del_ll = B_TRUE; 1616 432 vi117747 1617 432 vi117747 nsaddr = sctp->sctp_nsaddrs; 1618 0 stevel for (i = 0; i < SCTP_IPIF_HASH; i++) { 1619 0 stevel if (sctp->sctp_saddrs[i].ipif_count == 0) 1620 0 stevel continue; 1621 0 stevel obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list); 1622 432 vi117747 naddr = sctp->sctp_saddrs[i].ipif_count; 1623 432 vi117747 for (l = 0; l < naddr; l++) { 1624 0 stevel in6_addr_t addr; 1625 0 stevel sctp_ipif_t *ipif; 1626 852 vi117747 boolean_t ipif_lb; 1627 852 vi117747 boolean_t ipif_ll; 1628 432 vi117747 boolean_t unsupp_af; 1629 0 stevel 1630 0 stevel ipif = obj->saddr_ipifp; 1631 0 stevel scanned++; 1632 432 vi117747 1633 852 vi117747 ipif_lb = SCTP_IS_IPIF_LOOPBACK(ipif); 1634 852 vi117747 ipif_ll = SCTP_IS_IPIF_LINKLOCAL(ipif); 1635 432 vi117747 unsupp_af = SCTP_UNSUPP_AF(ipif, supp_af); 1636 432 vi117747 /* 1637 432 vi117747 * We need to either delete or skip loopback/linklocal 1638 852 vi117747 * or unsupported addresses, if required. 1639 432 vi117747 */ 1640 852 vi117747 if ((ipif_ll && del_ll) || (ipif_lb && del_lb) || 1641 852 vi117747 (unsupp_af && modify)) { 1642 432 vi117747 if (sctp->sctp_bound_to_all == 1) 1643 432 vi117747 sctp->sctp_bound_to_all = 0; 1644 432 vi117747 if (scanned < nsaddr) { 1645 432 vi117747 obj = list_next(&sctp->sctp_saddrs[i]. 1646 432 vi117747 sctp_ipif_list, obj); 1647 432 vi117747 sctp_ipif_hash_remove(sctp, ipif); 1648 432 vi117747 continue; 1649 432 vi117747 } 1650 432 vi117747 sctp_ipif_hash_remove(sctp, ipif); 1651 432 vi117747 goto next_addr; 1652 852 vi117747 } else if (ipif_ll || unsupp_af || 1653 852 vi117747 (ipif_lb && (cl_sctp_check_addrs == NULL))) { 1654 252 vi117747 goto next_addr; 1655 0 stevel } 1656 432 vi117747 1657 432 vi117747 if (!SCTP_IPIF_USABLE(ipif->sctp_ipif_state)) 1658 432 vi117747 goto next_addr; 1659 252 vi117747 if (p != NULL) 1660 252 vi117747 hdr = (sctp_parm_hdr_t *)(p + paramlen); 1661 0 stevel addr = ipif->sctp_ipif_saddr; 1662 432 vi117747 if (!ipif->sctp_ipif_isv6) { 1663 0 stevel struct in_addr *v4; 1664 0 stevel 1665 252 vi117747 if (p != NULL) { 1666 252 vi117747 hdr->sph_type = htons(PARM_ADDR4); 1667 252 vi117747 hdr->sph_len = htons(PARM_ADDR4_LEN); 1668 252 vi117747 v4 = (struct in_addr *)(hdr + 1); 1669 252 vi117747 IN6_V4MAPPED_TO_INADDR(&addr, v4); 1670 252 vi117747 } 1671 252 vi117747 paramlen += PARM_ADDR4_LEN; 1672 432 vi117747 } else { 1673 252 vi117747 if (p != NULL) { 1674 252 vi117747 hdr->sph_type = htons(PARM_ADDR6); 1675 252 vi117747 hdr->sph_len = htons(PARM_ADDR6_LEN); 1676 252 vi117747 bcopy(&addr, hdr + 1, sizeof (addr)); 1677 252 vi117747 } 1678 252 vi117747 paramlen += PARM_ADDR6_LEN; 1679 0 stevel } 1680 252 vi117747 next_addr: 1681 432 vi117747 if (scanned >= nsaddr) 1682 252 vi117747 return (paramlen); 1683 0 stevel obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list, 1684 0 stevel obj); 1685 0 stevel } 1686 0 stevel } 1687 252 vi117747 return (paramlen); 1688 0 stevel } 1689 0 stevel 1690 852 vi117747 /* 1691 852 vi117747 * This is used on a clustered node to obtain a list of addresses, the list 1692 852 vi117747 * consists of sockaddr_in structs for v4 and sockaddr_in6 for v6. The list 1693 852 vi117747 * is then passed onto the clustering module which sends back the correct 1694 852 vi117747 * list based on the port info. Regardless of the input, i.e INADDR_ANY 1695 852 vi117747 * or specific address(es), we create the list since it could be modified by 1696 852 vi117747 * the clustering module. When given a list of addresses, we simply 1697 852 vi117747 * create the list of sockaddr_in or sockaddr_in6 structs using those 1698 852 vi117747 * addresses. If there is an INADDR_ANY in the input list, or if the 1699 852 vi117747 * input is INADDR_ANY, we create a list of sockaddr_in or sockaddr_in6 1700 852 vi117747 * structs consisting all the addresses in the global interface list 1701 852 vi117747 * except those that are hosted on the loopback interface. We create 1702 852 vi117747 * a list of sockaddr_in[6] structs just so that it can be directly input 1703 852 vi117747 * to sctp_valid_addr_list() once the clustering module has processed it. 1704 852 vi117747 */ 1705 852 vi117747 int 1706 852 vi117747 sctp_get_addrlist(sctp_t *sctp, const void *addrs, uint32_t *addrcnt, 1707 852 vi117747 uchar_t **addrlist, int *uspec, size_t *size) 1708 852 vi117747 { 1709 852 vi117747 int cnt; 1710 852 vi117747 int icnt; 1711 852 vi117747 sctp_ipif_t *sctp_ipif; 1712 852 vi117747 struct sockaddr_in *s4; 1713 852 vi117747 struct sockaddr_in6 *s6; 1714 852 vi117747 uchar_t *p; 1715 852 vi117747 int err = 0; 1716 3448 dh155122 sctp_stack_t *sctps = sctp->sctp_sctps; 1717 11042 Erik conn_t *connp = sctp->sctp_connp; 1718 852 vi117747 1719 852 vi117747 *addrlist = NULL; 1720 852 vi117747 *size = 0; 1721 852 vi117747 1722 852 vi117747 /* 1723 852 vi117747 * Create a list of sockaddr_in[6] structs using the input list. 1724 852 vi117747 */ 1725 11042 Erik if (connp->conn_family == AF_INET) { 1726 852 vi117747 *size = sizeof (struct sockaddr_in) * *addrcnt; 1727 852 vi117747 *addrlist = kmem_zalloc(*size, KM_SLEEP); 1728 852 vi117747 p = *addrlist; 1729 852 vi117747 for (cnt = 0; cnt < *addrcnt; cnt++) { 1730 852 vi117747 s4 = (struct sockaddr_in *)addrs + cnt; 1731 852 vi117747 /* 1732 852 vi117747 * We need to create a list of all the available 1733 852 vi117747 * addresses if there is an INADDR_ANY. However, 1734 852 vi117747 * if we are beyond LISTEN, then this is invalid 1735 852 vi117747 * (see sctp_valid_addr_list(). So, we just fail 1736 852 vi117747 * it here rather than wait till it fails in 1737 852 vi117747 * sctp_valid_addr_list(). 1738 852 vi117747 */ 1739 852 vi117747 if (s4->sin_addr.s_addr == INADDR_ANY) { 1740 852 vi117747 kmem_free(*addrlist, *size); 1741 852 vi117747 *addrlist = NULL; 1742 852 vi117747 *size = 0; 1743 852 vi117747 if (sctp->sctp_state > SCTPS_LISTEN) { 1744 852 vi117747 *addrcnt = 0; 1745 852 vi117747 return (EINVAL); 1746 852 vi117747 } 1747 852 vi117747 if (uspec != NULL) 1748 852 vi117747 *uspec = 1; 1749 852 vi117747 goto get_all_addrs; 1750 852 vi117747 } else { 1751 852 vi117747 bcopy(s4, p, sizeof (*s4)); 1752 852 vi117747 p += sizeof (*s4); 1753 852 vi117747 } 1754 852 vi117747 } 1755 852 vi117747 } else { 1756 852 vi117747 *size = sizeof (struct sockaddr_in6) * *addrcnt; 1757 852 vi117747 *addrlist = kmem_zalloc(*size, KM_SLEEP); 1758 852 vi117747 p = *addrlist; 1759 852 vi117747 for (cnt = 0; cnt < *addrcnt; cnt++) { 1760 852 vi117747 s6 = (struct sockaddr_in6 *)addrs + cnt; 1761 852 vi117747 /* 1762 852 vi117747 * Comments for INADDR_ANY, above, apply here too. 1763 852 vi117747 */ 1764 852 vi117747 if (IN6_IS_ADDR_UNSPECIFIED(&s6->sin6_addr)) { 1765 852 vi117747 kmem_free(*addrlist, *size); 1766 852 vi117747 *size = 0; 1767 852 vi117747 *addrlist = NULL; 1768 852 vi117747 if (sctp->sctp_state > SCTPS_LISTEN) { 1769 852 vi117747 *addrcnt = 0; 1770 852 vi117747 return (EINVAL); 1771 852 vi117747 } 1772 852 vi117747 if (uspec != NULL) 1773 852 vi117747 *uspec = 1; 1774 852 vi117747 goto get_all_addrs; 1775 852 vi117747 } else { 1776 852 vi117747 bcopy(addrs, p, sizeof (*s6)); 1777 852 vi117747 p += sizeof (*s6); 1778 852 vi117747 } 1779 852 vi117747 } 1780 852 vi117747 } 1781 852 vi117747 return (err); 1782 852 vi117747 get_all_addrs: 1783 852 vi117747 1784 852 vi117747 /* 1785 852 vi117747 * Allocate max possible size. We allocate the max. size here because 1786 852 vi117747 * the clustering module could end up adding addresses to the list. 1787 852 vi117747 * We allocate upfront so that the clustering module need to bother 1788 852 vi117747 * re-sizing the list. 1789 852 vi117747 */ 1790 11042 Erik if (connp->conn_family == AF_INET) { 1791 3448 dh155122 *size = sizeof (struct sockaddr_in) * 1792 3448 dh155122 sctps->sctps_g_ipifs_count; 1793 3448 dh155122 } else { 1794 3448 dh155122 *size = sizeof (struct sockaddr_in6) * 1795 3448 dh155122 sctps->sctps_g_ipifs_count; 1796 3448 dh155122 } 1797 852 vi117747 *addrlist = kmem_zalloc(*size, KM_SLEEP); 1798 852 vi117747 *addrcnt = 0; 1799 852 vi117747 p = *addrlist; 1800 3448 dh155122 rw_enter(&sctps->sctps_g_ipifs_lock, RW_READER); 1801 852 vi117747 1802 852 vi117747 /* 1803 852 vi117747 * Walk through the global interface list and add all addresses, 1804 852 vi117747 * except those that are hosted on loopback interfaces. 1805 852 vi117747 */ 1806 852 vi117747 for (cnt = 0; cnt < SCTP_IPIF_HASH; cnt++) { 1807 3448 dh155122 if (sctps->sctps_g_ipifs[cnt].ipif_count == 0) 1808 852 vi117747 continue; 1809 3448 dh155122 sctp_ipif = list_head( 1810 3448 dh155122 &sctps->sctps_g_ipifs[cnt].sctp_ipif_list); 1811 3448 dh155122 for (icnt = 0; 1812 3448 dh155122 icnt < sctps->sctps_g_ipifs[cnt].ipif_count; 1813 3448 dh155122 icnt++) { 1814 852 vi117747 in6_addr_t addr; 1815 852 vi117747 1816 852 vi117747 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER); 1817 852 vi117747 addr = sctp_ipif->sctp_ipif_saddr; 1818 852 vi117747 if (SCTP_IPIF_DISCARD(sctp_ipif->sctp_ipif_flags) || 1819 852 vi117747 !SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) || 1820 852 vi117747 SCTP_IS_IPIF_LOOPBACK(sctp_ipif) || 1821 852 vi117747 SCTP_IS_IPIF_LINKLOCAL(sctp_ipif) || 1822 2263 sommerfe !SCTP_IPIF_ZONE_MATCH(sctp, sctp_ipif) || 1823 11042 Erik (connp->conn_family == AF_INET && 1824 852 vi117747 sctp_ipif->sctp_ipif_isv6) || 1825 852 vi117747 (sctp->sctp_connp->conn_ipv6_v6only && 1826 852 vi117747 !sctp_ipif->sctp_ipif_isv6)) { 1827 852 vi117747 rw_exit(&sctp_ipif->sctp_ipif_lock); 1828 852 vi117747 sctp_ipif = list_next( 1829 3448 dh155122 &sctps->sctps_g_ipifs[cnt].sctp_ipif_list, 1830 852 vi117747 sctp_ipif); 1831 852 vi117747 continue; 1832 852 vi117747 } 1833 852 vi117747 rw_exit(&sctp_ipif->sctp_ipif_lock); 1834 11042 Erik if (connp->conn_family == AF_INET) { 1835 852 vi117747 s4 = (struct sockaddr_in *)p; 1836 852 vi117747 IN6_V4MAPPED_TO_INADDR(&addr, &s4->sin_addr); 1837 852 vi117747 s4->sin_family = AF_INET; 1838 852 vi117747 p += sizeof (*s4); 1839 852 vi117747 } else { 1840 852 vi117747 s6 = (struct sockaddr_in6 *)p; 1841 852 vi117747 s6->sin6_addr = addr; 1842 852 vi117747 s6->sin6_family = AF_INET6; 1843 852 vi117747 s6->sin6_scope_id = 1844 852 vi117747 sctp_ipif->sctp_ipif_ill->sctp_ill_index; 1845 852 vi117747 p += sizeof (*s6); 1846 852 vi117747 } 1847 852 vi117747 (*addrcnt)++; 1848 3448 dh155122 sctp_ipif = list_next( 1849 3448 dh155122 &sctps->sctps_g_ipifs[cnt].sctp_ipif_list, 1850 852 vi117747 sctp_ipif); 1851 852 vi117747 } 1852 852 vi117747 } 1853 3448 dh155122 rw_exit(&sctps->sctps_g_ipifs_lock); 1854 852 vi117747 return (err); 1855 852 vi117747 } 1856 852 vi117747 1857 852 vi117747 /* 1858 852 vi117747 * Get a list of addresses from the source address list. The caller is 1859 852 vi117747 * responsible for allocating sufficient buffer for this. 1860 852 vi117747 */ 1861 852 vi117747 void 1862 852 vi117747 sctp_get_saddr_list(sctp_t *sctp, uchar_t *p, size_t psize) 1863 852 vi117747 { 1864 852 vi117747 int cnt; 1865 852 vi117747 int icnt; 1866 852 vi117747 sctp_saddr_ipif_t *obj; 1867 852 vi117747 int naddr; 1868 852 vi117747 int scanned = 0; 1869 852 vi117747 1870 852 vi117747 for (cnt = 0; cnt < SCTP_IPIF_HASH; cnt++) { 1871 852 vi117747 if (sctp->sctp_saddrs[cnt].ipif_count == 0) 1872 852 vi117747 continue; 1873 852 vi117747 obj = list_head(&sctp->sctp_saddrs[cnt].sctp_ipif_list); 1874 852 vi117747 naddr = sctp->sctp_saddrs[cnt].ipif_count; 1875 852 vi117747 for (icnt = 0; icnt < naddr; icnt++) { 1876 852 vi117747 sctp_ipif_t *ipif; 1877 852 vi117747 1878 852 vi117747 if (psize < sizeof (ipif->sctp_ipif_saddr)) 1879 852 vi117747 return; 1880 852 vi117747 1881 852 vi117747 scanned++; 1882 852 vi117747 ipif = obj->saddr_ipifp; 1883 852 vi117747 bcopy(&ipif->sctp_ipif_saddr, p, 1884 852 vi117747 sizeof (ipif->sctp_ipif_saddr)); 1885 852 vi117747 p += sizeof (ipif->sctp_ipif_saddr); 1886 852 vi117747 psize -= sizeof (ipif->sctp_ipif_saddr); 1887 852 vi117747 if (scanned >= sctp->sctp_nsaddrs) 1888 852 vi117747 return; 1889 3448 dh155122 obj = list_next( 1890 3448 dh155122 &sctp->sctp_saddrs[icnt].sctp_ipif_list, 1891 852 vi117747 obj); 1892 852 vi117747 } 1893 852 vi117747 } 1894 852 vi117747 } 1895 852 vi117747 1896 852 vi117747 /* 1897 852 vi117747 * Get a list of addresses from the remote address list. The caller is 1898 852 vi117747 * responsible for allocating sufficient buffer for this. 1899 852 vi117747 */ 1900 852 vi117747 void 1901 852 vi117747 sctp_get_faddr_list(sctp_t *sctp, uchar_t *p, size_t psize) 1902 852 vi117747 { 1903 852 vi117747 sctp_faddr_t *fp; 1904 852 vi117747 1905 852 vi117747 for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { 1906 852 vi117747 if (psize < sizeof (fp->faddr)) 1907 852 vi117747 return; 1908 852 vi117747 bcopy(&fp->faddr, p, sizeof (fp->faddr)); 1909 852 vi117747 p += sizeof (fp->faddr); 1910 852 vi117747 psize -= sizeof (fp->faddr); 1911 852 vi117747 } 1912 852 vi117747 } 1913 0 stevel 1914 3448 dh155122 static void 1915 3448 dh155122 sctp_free_ills(sctp_stack_t *sctps) 1916 3448 dh155122 { 1917 3448 dh155122 int i; 1918 3448 dh155122 int l; 1919 3448 dh155122 sctp_ill_t *sctp_ill; 1920 3448 dh155122 1921 3448 dh155122 if (sctps->sctps_ills_count == 0) 1922 3448 dh155122 return; 1923 3448 dh155122 1924 3448 dh155122 for (i = 0; i < SCTP_ILL_HASH; i++) { 1925 3448 dh155122 sctp_ill = list_tail(&sctps->sctps_g_ills[i].sctp_ill_list); 1926 3448 dh155122 for (l = 0; l < sctps->sctps_g_ills[i].ill_count; l++) { 1927 3448 dh155122 ASSERT(sctp_ill->sctp_ill_ipifcnt == 0); 1928 3448 dh155122 list_remove(&sctps->sctps_g_ills[i].sctp_ill_list, 1929 3448 dh155122 sctp_ill); 1930 3448 dh155122 sctps->sctps_ills_count--; 1931 3448 dh155122 kmem_free(sctp_ill->sctp_ill_name, 1932 3448 dh155122 sctp_ill->sctp_ill_name_length); 1933 3448 dh155122 kmem_free(sctp_ill, sizeof (sctp_ill_t)); 1934 3448 dh155122 sctp_ill = 1935 3448 dh155122 list_tail(&sctps->sctps_g_ills[i].sctp_ill_list); 1936 3448 dh155122 } 1937 3448 dh155122 sctps->sctps_g_ills[i].ill_count = 0; 1938 3448 dh155122 } 1939 3448 dh155122 ASSERT(sctps->sctps_ills_count == 0); 1940 3448 dh155122 } 1941 3448 dh155122 1942 3448 dh155122 static void 1943 3448 dh155122 sctp_free_ipifs(sctp_stack_t *sctps) 1944 3448 dh155122 { 1945 3448 dh155122 int i; 1946 3448 dh155122 int l; 1947 3448 dh155122 sctp_ipif_t *sctp_ipif; 1948 3448 dh155122 sctp_ill_t *sctp_ill; 1949 3448 dh155122 1950 3448 dh155122 if (sctps->sctps_g_ipifs_count == 0) 1951 3448 dh155122 return; 1952 3448 dh155122 1953 3448 dh155122 for (i = 0; i < SCTP_IPIF_HASH; i++) { 1954 3448 dh155122 sctp_ipif = list_tail(&sctps->sctps_g_ipifs[i].sctp_ipif_list); 1955 3448 dh155122 for (l = 0; l < sctps->sctps_g_ipifs[i].ipif_count; l++) { 1956 3448 dh155122 sctp_ill = sctp_ipif->sctp_ipif_ill; 1957 3448 dh155122 1958 3448 dh155122 list_remove(&sctps->sctps_g_ipifs[i].sctp_ipif_list, 1959 3448 dh155122 sctp_ipif); 1960 3448 dh155122 sctps->sctps_g_ipifs_count--; 1961 3448 dh155122 (void) atomic_add_32_nv(&sctp_ill->sctp_ill_ipifcnt, 1962 3448 dh155122 -1); 1963 3448 dh155122 kmem_free(sctp_ipif, sizeof (sctp_ipif_t)); 1964 3448 dh155122 sctp_ipif = 1965 3448 dh155122 list_tail(&sctps->sctps_g_ipifs[i].sctp_ipif_list); 1966 3448 dh155122 } 1967 3448 dh155122 sctps->sctps_g_ipifs[i].ipif_count = 0; 1968 3448 dh155122 } 1969 3448 dh155122 ASSERT(sctps->sctps_g_ipifs_count == 0); 1970 3448 dh155122 } 1971 3448 dh155122 1972 3448 dh155122 1973 0 stevel /* Initialize the SCTP ILL list and lock */ 1974 0 stevel void 1975 3448 dh155122 sctp_saddr_init(sctp_stack_t *sctps) 1976 0 stevel { 1977 0 stevel int i; 1978 0 stevel 1979 3448 dh155122 sctps->sctps_g_ills = kmem_zalloc(sizeof (sctp_ill_hash_t) * 1980 3448 dh155122 SCTP_ILL_HASH, KM_SLEEP); 1981 3448 dh155122 sctps->sctps_g_ipifs = kmem_zalloc(sizeof (sctp_ipif_hash_t) * 1982 3448 dh155122 SCTP_IPIF_HASH, KM_SLEEP); 1983 3448 dh155122 1984 3448 dh155122 rw_init(&sctps->sctps_g_ills_lock, NULL, RW_DEFAULT, NULL); 1985 3448 dh155122 rw_init(&sctps->sctps_g_ipifs_lock, NULL, RW_DEFAULT, NULL); 1986 0 stevel 1987 0 stevel for (i = 0; i < SCTP_ILL_HASH; i++) { 1988 3448 dh155122 sctps->sctps_g_ills[i].ill_count = 0; 1989 3448 dh155122 list_create(&sctps->sctps_g_ills[i].sctp_ill_list, 1990 3448 dh155122 sizeof (sctp_ill_t), 1991 0 stevel offsetof(sctp_ill_t, sctp_ills)); 1992 0 stevel } 1993 0 stevel for (i = 0; i < SCTP_IPIF_HASH; i++) { 1994 3448 dh155122 sctps->sctps_g_ipifs[i].ipif_count = 0; 1995 3448 dh155122 list_create(&sctps->sctps_g_ipifs[i].sctp_ipif_list, 1996 0 stevel sizeof (sctp_ipif_t), offsetof(sctp_ipif_t, sctp_ipifs)); 1997 0 stevel } 1998 0 stevel } 1999 0 stevel 2000 0 stevel void 2001 3448 dh155122 sctp_saddr_fini(sctp_stack_t *sctps) 2002 0 stevel { 2003 0 stevel int i; 2004 0 stevel 2005 3448 dh155122 sctp_free_ipifs(sctps); 2006 3448 dh155122 sctp_free_ills(sctps); 2007 3448 dh155122 2008 0 stevel for (i = 0; i < SCTP_ILL_HASH; i++) 2009 3448 dh155122 list_destroy(&sctps->sctps_g_ills[i].sctp_ill_list); 2010 0 stevel for (i = 0; i < SCTP_IPIF_HASH; i++) 2011 3448 dh155122 list_destroy(&sctps->sctps_g_ipifs[i].sctp_ipif_list); 2012 3448 dh155122 2013 3448 dh155122 ASSERT(sctps->sctps_ills_count == 0 && sctps->sctps_g_ipifs_count == 0); 2014 3448 dh155122 kmem_free(sctps->sctps_g_ills, sizeof (sctp_ill_hash_t) * 2015 3448 dh155122 SCTP_ILL_HASH); 2016 3448 dh155122 sctps->sctps_g_ills = NULL; 2017 3448 dh155122 kmem_free(sctps->sctps_g_ipifs, sizeof (sctp_ipif_hash_t) * 2018 3448 dh155122 SCTP_IPIF_HASH); 2019 3448 dh155122 sctps->sctps_g_ipifs = NULL; 2020 3448 dh155122 rw_destroy(&sctps->sctps_g_ills_lock); 2021 3448 dh155122 rw_destroy(&sctps->sctps_g_ipifs_lock); 2022 0 stevel } 2023