1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/systm.h> 31 #include <sys/stream.h> 32 #include <sys/ddi.h> 33 #include <sys/sunddi.h> 34 #include <sys/kmem.h> 35 #include <sys/socket.h> 36 #include <sys/sysmacros.h> 37 #include <sys/list.h> 38 39 #include <netinet/in.h> 40 #include <netinet/ip6.h> 41 #include <netinet/sctp.h> 42 43 #include <inet/common.h> 44 #include <inet/ip.h> 45 #include <inet/ip6.h> 46 #include <inet/ip_if.h> 47 #include <inet/ipclassifier.h> 48 #include <inet/sctp_ip.h> 49 #include "sctp_impl.h" 50 #include "sctp_addr.h" 51 52 static void sctp_ipif_inactive(sctp_ipif_t *); 53 static sctp_ipif_t *sctp_lookup_ipif_addr(in6_addr_t *, boolean_t, 54 zoneid_t zoneid); 55 static int sctp_get_all_ipifs(sctp_t *, int); 56 int sctp_valid_addr_list(sctp_t *, const void *, uint32_t); 57 sctp_saddr_ipif_t *sctp_ipif_lookup(sctp_t *, uint_t); 58 static int sctp_ipif_hash_insert(sctp_t *, sctp_ipif_t *, int); 59 static void sctp_ipif_hash_remove(sctp_t *, sctp_ipif_t *); 60 static int sctp_compare_ipif_list(sctp_ipif_hash_t *, 61 sctp_ipif_hash_t *); 62 int sctp_compare_saddrs(sctp_t *, sctp_t *); 63 static int sctp_copy_ipifs(sctp_ipif_hash_t *, sctp_t *, int); 64 int sctp_dup_saddrs(sctp_t *, sctp_t *, int); 65 void sctp_free_saddrs(sctp_t *); 66 void sctp_update_ill(ill_t *, int); 67 void sctp_update_ipif(ipif_t *, int); 68 void sctp_move_ipif(ipif_t *, ill_t *, ill_t *); 69 void sctp_del_saddr(sctp_t *, sctp_saddr_ipif_t *); 70 void sctp_del_saddr_list(sctp_t *, const void *, int, 71 boolean_t); 72 sctp_saddr_ipif_t *sctp_saddr_lookup(sctp_t *, in6_addr_t *); 73 in6_addr_t sctp_get_valid_addr(sctp_t *, boolean_t); 74 int sctp_getmyaddrs(void *, void *, int *); 75 void sctp_saddr_init(); 76 void sctp_saddr_fini(); 77 #define SCTP_IPIF_USABLE(sctp_ipif_state) \ 78 ((sctp_ipif_state) == SCTP_IPIFS_UP || \ 79 ((sctp_ipif_state) == SCTP_IPIFS_DOWN)) 80 81 #define SCTP_ILL_HASH_FN(index) ((index) % SCTP_ILL_HASH) 82 #define SCTP_IPIF_HASH_FN(seqid) ((seqid) % SCTP_IPIF_HASH) 83 #define SCTP_ILL_TO_PHYINDEX(ill) ((ill)->ill_phyint->phyint_ifindex) 84 85 /* Global list of SCTP ILLs */ 86 sctp_ill_hash_t sctp_g_ills[SCTP_ILL_HASH]; 87 uint32_t sctp_ills_count = 0; 88 89 /* Global list of SCTP IPIFs */ 90 sctp_ipif_hash_t sctp_g_ipifs[SCTP_IPIF_HASH]; 91 uint32_t sctp_g_ipifs_count; 92 93 /* 94 * 95 * 96 * SCTP Interface list manipulation functions, locking used. 97 * 98 * 99 */ 100 101 /* 102 * Delete an SCTP IPIF from the list if the refcount goes to 0 and it is 103 * marked as condemned. Also, check if the ILL needs to go away. 104 * Called with no locks held. 105 */ 106 static void 107 sctp_ipif_inactive(sctp_ipif_t *sctp_ipif) 108 { 109 sctp_ill_t *sctp_ill; 110 uint_t ipif_index; 111 uint_t ill_index; 112 113 rw_enter(&sctp_g_ills_lock, RW_READER); 114 rw_enter(&sctp_g_ipifs_lock, RW_WRITER); 115 116 ipif_index = SCTP_IPIF_HASH_FN(sctp_ipif->sctp_ipif_id); 117 sctp_ill = sctp_ipif->sctp_ipif_ill; 118 ASSERT(sctp_ill != NULL); 119 ill_index = SCTP_ILL_HASH_FN(sctp_ill->sctp_ill_index); 120 if (sctp_ipif->sctp_ipif_state != SCTP_IPIFS_CONDEMNED || 121 sctp_ipif->sctp_ipif_refcnt != 0) { 122 rw_exit(&sctp_g_ipifs_lock); 123 rw_exit(&sctp_g_ills_lock); 124 return; 125 } 126 list_remove(&sctp_g_ipifs[ipif_index].sctp_ipif_list, sctp_ipif); 127 sctp_g_ipifs[ipif_index].ipif_count--; 128 sctp_g_ipifs_count--; 129 rw_destroy(&sctp_ipif->sctp_ipif_lock); 130 kmem_free(sctp_ipif, sizeof (sctp_ipif_t)); 131 132 (void) atomic_add_32_nv(&sctp_ill->sctp_ill_ipifcnt, -1); 133 if (rw_tryupgrade(&sctp_g_ills_lock) != 0) { 134 rw_downgrade(&sctp_g_ipifs_lock); 135 if (sctp_ill->sctp_ill_ipifcnt == 0 && 136 sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) { 137 list_remove(&sctp_g_ills[ill_index].sctp_ill_list, 138 (void *)sctp_ill); 139 sctp_g_ills[ill_index].ill_count--; 140 sctp_ills_count--; 141 kmem_free(sctp_ill->sctp_ill_name, 142 sctp_ill->sctp_ill_name_length); 143 kmem_free(sctp_ill, sizeof (sctp_ill_t)); 144 } 145 } 146 rw_exit(&sctp_g_ipifs_lock); 147 rw_exit(&sctp_g_ills_lock); 148 } 149 150 /* 151 * Lookup an SCTP IPIF given an IP address. Increments sctp_ipif refcnt. 152 * Called with no locks held. 153 */ 154 static sctp_ipif_t * 155 sctp_lookup_ipif_addr(in6_addr_t *addr, boolean_t refhold, zoneid_t zoneid) 156 { 157 int i; 158 int j; 159 sctp_ipif_t *sctp_ipif; 160 161 rw_enter(&sctp_g_ipifs_lock, RW_READER); 162 for (i = 0; i < SCTP_IPIF_HASH; i++) { 163 if (sctp_g_ipifs[i].ipif_count == 0) 164 continue; 165 sctp_ipif = list_head(&sctp_g_ipifs[i].sctp_ipif_list); 166 for (j = 0; j < sctp_g_ipifs[i].ipif_count; j++) { 167 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER); 168 if (zoneid == sctp_ipif->sctp_ipif_zoneid && 169 SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) && 170 IN6_ARE_ADDR_EQUAL(&sctp_ipif->sctp_ipif_saddr, 171 addr)) { 172 rw_exit(&sctp_ipif->sctp_ipif_lock); 173 if (refhold) 174 SCTP_IPIF_REFHOLD(sctp_ipif); 175 rw_exit(&sctp_g_ipifs_lock); 176 return (sctp_ipif); 177 } 178 rw_exit(&sctp_ipif->sctp_ipif_lock); 179 sctp_ipif = list_next(&sctp_g_ipifs[i].sctp_ipif_list, 180 sctp_ipif); 181 } 182 } 183 rw_exit(&sctp_g_ipifs_lock); 184 return (NULL); 185 } 186 187 /* 188 * Populate the list with all the SCTP ipifs for a given ipversion. 189 * Increments sctp_ipif refcnt. 190 * Called with no locks held. 191 */ 192 static int 193 sctp_get_all_ipifs(sctp_t *sctp, int sleep) 194 { 195 sctp_ipif_t *sctp_ipif; 196 int i; 197 int j; 198 int error = 0; 199 200 rw_enter(&sctp_g_ipifs_lock, RW_READER); 201 for (i = 0; i < SCTP_IPIF_HASH; i++) { 202 if (sctp_g_ipifs[i].ipif_count == 0) 203 continue; 204 sctp_ipif = list_head(&sctp_g_ipifs[i].sctp_ipif_list); 205 for (j = 0; j < sctp_g_ipifs[i].ipif_count; j++) { 206 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_READER); 207 if (sctp_ipif->sctp_ipif_zoneid != sctp->sctp_zoneid || 208 !SCTP_IPIF_USABLE(sctp_ipif->sctp_ipif_state) || 209 (sctp->sctp_ipversion == IPV4_VERSION && 210 !IN6_IS_ADDR_V4MAPPED( 211 &sctp_ipif->sctp_ipif_saddr)) || 212 (sctp->sctp_connp->conn_ipv6_v6only && 213 IN6_IS_ADDR_V4MAPPED( 214 &sctp_ipif->sctp_ipif_saddr))) { 215 rw_exit(&sctp_ipif->sctp_ipif_lock); 216 sctp_ipif = list_next( 217 &sctp_g_ipifs[i].sctp_ipif_list, sctp_ipif); 218 continue; 219 } 220 rw_exit(&sctp_ipif->sctp_ipif_lock); 221 SCTP_IPIF_REFHOLD(sctp_ipif); 222 error = sctp_ipif_hash_insert(sctp, sctp_ipif, sleep); 223 if (error != 0) 224 goto free_stuff; 225 sctp_ipif = list_next(&sctp_g_ipifs[i].sctp_ipif_list, 226 sctp_ipif); 227 } 228 } 229 rw_exit(&sctp_g_ipifs_lock); 230 return (0); 231 free_stuff: 232 rw_exit(&sctp_g_ipifs_lock); 233 sctp_free_saddrs(sctp); 234 return (ENOMEM); 235 } 236 237 /* 238 * Given a list of address, fills in the list of SCTP ipifs if all the addresses 239 * are present in the SCTP interface list, return number of addresses filled 240 * or error. 241 * Called with no locks held. 242 */ 243 int 244 sctp_valid_addr_list(sctp_t *sctp, const void *addrs, uint32_t addrcnt) 245 { 246 struct sockaddr_in *sin4; 247 struct sockaddr_in6 *sin6; 248 struct in_addr *addr4; 249 in6_addr_t addr; 250 int cnt; 251 int err = 0; 252 int saddr_cnt = 0; 253 sctp_ipif_t *ipif; 254 boolean_t bind_to_all = B_FALSE; 255 boolean_t check_addrs = B_FALSE; 256 boolean_t check_lport = B_FALSE; 257 258 /* 259 * Need to check for port and address depending on the state. 260 * After a socket is bound, we need to make sure that subsequent 261 * bindx() has correct port. After an association is established, 262 * we need to check for changing the bound address to invalid 263 * addresses. 264 */ 265 if (sctp->sctp_state >= SCTPS_BOUND) { 266 check_lport = B_TRUE; 267 if (sctp->sctp_state > SCTPS_LISTEN) 268 check_addrs = B_TRUE; 269 } 270 if (sctp->sctp_conn_tfp != NULL) 271 mutex_enter(&sctp->sctp_conn_tfp->tf_lock); 272 if (sctp->sctp_listen_tfp != NULL) 273 mutex_enter(&sctp->sctp_listen_tfp->tf_lock); 274 for (cnt = 0; cnt < addrcnt; cnt++) { 275 boolean_t lookup_saddr = B_TRUE; 276 277 switch (sctp->sctp_family) { 278 case AF_INET: 279 sin4 = (struct sockaddr_in *)addrs + cnt; 280 if (sin4->sin_family != AF_INET || (check_lport && 281 sin4->sin_port != sctp->sctp_lport)) { 282 err = EINVAL; 283 goto free_ret; 284 } 285 addr4 = &sin4->sin_addr; 286 if (check_addrs && 287 (addr4->s_addr == INADDR_ANY || 288 addr4->s_addr == INADDR_BROADCAST || 289 IN_MULTICAST(addr4->s_addr))) { 290 err = EINVAL; 291 goto free_ret; 292 } 293 IN6_INADDR_TO_V4MAPPED(addr4, &addr); 294 if (!check_addrs && addr4->s_addr == INADDR_ANY) { 295 lookup_saddr = B_FALSE; 296 bind_to_all = B_TRUE; 297 } 298 299 break; 300 case AF_INET6: 301 sin6 = (struct sockaddr_in6 *)addrs + cnt; 302 if (sin6->sin6_family != AF_INET6 || (check_lport && 303 sin6->sin6_port != sctp->sctp_lport)) { 304 err = EINVAL; 305 goto free_ret; 306 } 307 addr = sin6->sin6_addr; 308 if (sctp->sctp_connp->conn_ipv6_v6only && 309 IN6_IS_ADDR_V4MAPPED(&addr)) { 310 err = EAFNOSUPPORT; 311 goto free_ret; 312 } 313 if (check_addrs && 314 (IN6_IS_ADDR_LINKLOCAL(&addr) || 315 IN6_IS_ADDR_MULTICAST(&addr) || 316 IN6_IS_ADDR_UNSPECIFIED(&addr))) { 317 err = EINVAL; 318 goto free_ret; 319 } 320 if (!check_addrs && IN6_IS_ADDR_UNSPECIFIED(&addr)) { 321 lookup_saddr = B_FALSE; 322 bind_to_all = B_TRUE; 323 } 324 325 break; 326 default: 327 err = EAFNOSUPPORT; 328 goto free_ret; 329 } 330 if (lookup_saddr) { 331 ipif = sctp_lookup_ipif_addr(&addr, B_TRUE, 332 sctp->sctp_zoneid); 333 if (ipif == NULL) { 334 /* Address not in the list */ 335 err = EINVAL; 336 goto free_ret; 337 } else if (check_addrs && 338 (ipif->sctp_ipif_ill->sctp_ill_flags & 339 PHYI_LOOPBACK)) { 340 SCTP_IPIF_REFRELE(ipif); 341 err = EINVAL; 342 goto free_ret; 343 } 344 } 345 if (!bind_to_all) { 346 err = sctp_ipif_hash_insert(sctp, ipif, KM_SLEEP); 347 if (err != 0) { 348 SCTP_IPIF_REFRELE(ipif); 349 if (check_addrs && err == EALREADY) 350 err = EADDRINUSE; 351 goto free_ret; 352 } 353 saddr_cnt++; 354 } 355 } 356 if (bind_to_all) { 357 /* 358 * Free whatever we might have added before encountering 359 * inaddr_any. 360 */ 361 if (sctp->sctp_nsaddrs > 0) { 362 sctp_free_saddrs(sctp); 363 ASSERT(sctp->sctp_nsaddrs == 0); 364 } 365 err = sctp_get_all_ipifs(sctp, KM_SLEEP); 366 if (err != 0) 367 return (err); 368 sctp->sctp_bound_to_all = 1; 369 } 370 if (sctp->sctp_listen_tfp != NULL) 371 mutex_exit(&sctp->sctp_listen_tfp->tf_lock); 372 if (sctp->sctp_conn_tfp != NULL) 373 mutex_exit(&sctp->sctp_conn_tfp->tf_lock); 374 return (0); 375 free_ret: 376 if (saddr_cnt != 0) 377 sctp_del_saddr_list(sctp, addrs, saddr_cnt, B_TRUE); 378 if (sctp->sctp_listen_tfp != NULL) 379 mutex_exit(&sctp->sctp_listen_tfp->tf_lock); 380 if (sctp->sctp_conn_tfp != NULL) 381 mutex_exit(&sctp->sctp_conn_tfp->tf_lock); 382 return (err); 383 } 384 385 sctp_saddr_ipif_t * 386 sctp_ipif_lookup(sctp_t *sctp, uint_t ipif_index) 387 { 388 int cnt; 389 int seqid = SCTP_IPIF_HASH_FN(ipif_index); 390 sctp_saddr_ipif_t *ipif_obj; 391 392 if (sctp->sctp_saddrs[seqid].ipif_count == 0) 393 return (NULL); 394 395 ipif_obj = list_head(&sctp->sctp_saddrs[seqid].sctp_ipif_list); 396 for (cnt = 0; cnt < sctp->sctp_saddrs[seqid].ipif_count; cnt++) { 397 if (ipif_obj->saddr_ipifp->sctp_ipif_id == ipif_index) 398 return (ipif_obj); 399 ipif_obj = list_next(&sctp->sctp_saddrs[seqid].sctp_ipif_list, 400 ipif_obj); 401 } 402 return (NULL); 403 } 404 405 static int 406 sctp_ipif_hash_insert(sctp_t *sctp, sctp_ipif_t *ipif, int sleep) 407 { 408 int cnt; 409 sctp_saddr_ipif_t *ipif_obj; 410 int seqid = SCTP_IPIF_HASH_FN(ipif->sctp_ipif_id); 411 412 ipif_obj = list_head(&sctp->sctp_saddrs[seqid].sctp_ipif_list); 413 for (cnt = 0; cnt < sctp->sctp_saddrs[seqid].ipif_count; cnt++) { 414 if (ipif_obj->saddr_ipifp->sctp_ipif_id == ipif->sctp_ipif_id) 415 return (EALREADY); 416 ipif_obj = list_next(&sctp->sctp_saddrs[seqid].sctp_ipif_list, 417 ipif_obj); 418 } 419 ipif_obj = kmem_zalloc(sizeof (sctp_saddr_ipif_t), sleep); 420 if (ipif_obj == NULL) { 421 /* Need to do something */ 422 return (ENOMEM); 423 } 424 ipif_obj->saddr_ipifp = ipif; 425 list_insert_tail(&sctp->sctp_saddrs[seqid].sctp_ipif_list, ipif_obj); 426 sctp->sctp_saddrs[seqid].ipif_count++; 427 sctp->sctp_nsaddrs++; 428 return (0); 429 } 430 431 static void 432 sctp_ipif_hash_remove(sctp_t *sctp, sctp_ipif_t *ipif) 433 { 434 int cnt; 435 sctp_saddr_ipif_t *ipif_obj; 436 int seqid = SCTP_IPIF_HASH_FN(ipif->sctp_ipif_id); 437 438 ipif_obj = list_head(&sctp->sctp_saddrs[seqid].sctp_ipif_list); 439 for (cnt = 0; cnt < sctp->sctp_saddrs[seqid].ipif_count; cnt++) { 440 if (ipif_obj->saddr_ipifp->sctp_ipif_id == ipif->sctp_ipif_id) { 441 list_remove(&sctp->sctp_saddrs[seqid].sctp_ipif_list, 442 ipif_obj); 443 sctp->sctp_nsaddrs--; 444 sctp->sctp_saddrs[seqid].ipif_count--; 445 SCTP_IPIF_REFRELE(ipif_obj->saddr_ipifp); 446 kmem_free(ipif_obj, sizeof (sctp_saddr_ipif_t)); 447 break; 448 } 449 ipif_obj = list_next(&sctp->sctp_saddrs[seqid].sctp_ipif_list, 450 ipif_obj); 451 } 452 } 453 454 static int 455 sctp_compare_ipif_list(sctp_ipif_hash_t *list1, sctp_ipif_hash_t *list2) 456 { 457 int i; 458 int j; 459 sctp_saddr_ipif_t *obj1; 460 sctp_saddr_ipif_t *obj2; 461 int overlap = 0; 462 463 obj1 = list_head(&list1->sctp_ipif_list); 464 for (i = 0; i < list1->ipif_count; i++) { 465 obj2 = list_head(&list2->sctp_ipif_list); 466 for (j = 0; j < list2->ipif_count; j++) { 467 if (obj1->saddr_ipifp->sctp_ipif_id == 468 obj2->saddr_ipifp->sctp_ipif_id) { 469 overlap++; 470 break; 471 } 472 obj2 = list_next(&list2->sctp_ipif_list, 473 obj2); 474 } 475 obj1 = list_next(&list1->sctp_ipif_list, obj1); 476 } 477 return (overlap); 478 } 479 480 int 481 sctp_compare_saddrs(sctp_t *sctp1, sctp_t *sctp2) 482 { 483 int i; 484 int overlap = 0; 485 486 for (i = 0; i < SCTP_IPIF_HASH; i++) { 487 overlap += sctp_compare_ipif_list(&sctp1->sctp_saddrs[i], 488 &sctp2->sctp_saddrs[i]); 489 } 490 491 if (sctp1->sctp_nsaddrs == sctp2->sctp_nsaddrs && 492 overlap == sctp1->sctp_nsaddrs) { 493 return (SCTP_ADDR_EQUAL); 494 } 495 496 if (overlap == sctp1->sctp_nsaddrs) 497 return (SCTP_ADDR_SUBSET); 498 499 if (overlap > 0) 500 return (SCTP_ADDR_OVERLAP); 501 502 return (SCTP_ADDR_DISJOINT); 503 } 504 505 static int 506 sctp_copy_ipifs(sctp_ipif_hash_t *list1, sctp_t *sctp2, int sleep) 507 { 508 int i; 509 sctp_saddr_ipif_t *obj; 510 int error = 0; 511 512 obj = list_head(&list1->sctp_ipif_list); 513 for (i = 0; i < list1->ipif_count; i++) { 514 SCTP_IPIF_REFHOLD(obj->saddr_ipifp); 515 error = sctp_ipif_hash_insert(sctp2, obj->saddr_ipifp, sleep); 516 if (error != 0) 517 return (error); 518 obj = list_next(&list1->sctp_ipif_list, obj); 519 } 520 return (error); 521 } 522 523 int 524 sctp_dup_saddrs(sctp_t *sctp1, sctp_t *sctp2, int sleep) 525 { 526 int error = 0; 527 int i; 528 529 if (sctp1 == NULL || sctp1->sctp_bound_to_all) 530 return (sctp_get_all_ipifs(sctp2, sleep)); 531 532 for (i = 0; i < SCTP_IPIF_HASH; i++) { 533 if (sctp1->sctp_saddrs[i].ipif_count == 0) 534 continue; 535 error = sctp_copy_ipifs(&sctp1->sctp_saddrs[i], sctp2, sleep); 536 if (error != 0) { 537 sctp_free_saddrs(sctp2); 538 return (error); 539 } 540 } 541 return (0); 542 } 543 544 void 545 sctp_free_saddrs(sctp_t *sctp) 546 { 547 int i; 548 int l; 549 sctp_saddr_ipif_t *obj; 550 551 if (sctp->sctp_nsaddrs == 0) 552 return; 553 for (i = 0; i < SCTP_IPIF_HASH; i++) { 554 if (sctp->sctp_saddrs[i].ipif_count == 0) 555 continue; 556 obj = list_tail(&sctp->sctp_saddrs[i].sctp_ipif_list); 557 for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) { 558 list_remove(&sctp->sctp_saddrs[i].sctp_ipif_list, obj); 559 SCTP_IPIF_REFRELE(obj->saddr_ipifp); 560 sctp->sctp_nsaddrs--; 561 kmem_free(obj, sizeof (sctp_saddr_ipif_t)); 562 obj = list_tail(&sctp->sctp_saddrs[i].sctp_ipif_list); 563 } 564 sctp->sctp_saddrs[i].ipif_count = 0; 565 } 566 ASSERT(sctp->sctp_nsaddrs == 0); 567 } 568 569 /* 570 * Add/Delete the given ILL from the SCTP ILL list. Called with no locks 571 * held. 572 */ 573 void 574 sctp_update_ill(ill_t *ill, int op) 575 { 576 int i; 577 sctp_ill_t *sctp_ill = NULL; 578 uint_t index; 579 580 ip2dbg(("sctp_update_ill: %s\n", ill->ill_name)); 581 582 rw_enter(&sctp_g_ills_lock, RW_WRITER); 583 584 index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill)); 585 sctp_ill = list_head(&sctp_g_ills[index].sctp_ill_list); 586 for (i = 0; i < sctp_g_ills[index].ill_count; i++) { 587 if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill)) 588 break; 589 sctp_ill = list_next(&sctp_g_ills[index].sctp_ill_list, 590 sctp_ill); 591 } 592 593 switch (op) { 594 case SCTP_ILL_INSERT: 595 if (sctp_ill != NULL) { 596 /* Unmark it if it is condemned */ 597 if (sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) 598 sctp_ill->sctp_ill_state = 0; 599 rw_exit(&sctp_g_ills_lock); 600 return; 601 } 602 sctp_ill = kmem_zalloc(sizeof (sctp_ill_t), KM_NOSLEEP); 603 /* Need to re-try? */ 604 if (sctp_ill == NULL) { 605 ip1dbg(("sctp_ill_insert: mem error..\n")); 606 rw_exit(&sctp_g_ills_lock); 607 return; 608 } 609 sctp_ill->sctp_ill_name = 610 kmem_zalloc(ill->ill_name_length, KM_NOSLEEP); 611 if (sctp_ill->sctp_ill_name == NULL) { 612 ip1dbg(("sctp_ill_insert: mem error..\n")); 613 kmem_free(sctp_ill, sizeof (sctp_ill_t)); 614 rw_exit(&sctp_g_ills_lock); 615 return; 616 } 617 bcopy(ill->ill_name, sctp_ill->sctp_ill_name, 618 ill->ill_name_length); 619 sctp_ill->sctp_ill_name_length = ill->ill_name_length; 620 sctp_ill->sctp_ill_index = SCTP_ILL_TO_PHYINDEX(ill); 621 sctp_ill->sctp_ill_flags = ill->ill_phyint->phyint_flags; 622 list_insert_tail(&sctp_g_ills[index].sctp_ill_list, 623 (void *)sctp_ill); 624 sctp_g_ills[index].ill_count++; 625 sctp_ills_count++; 626 627 break; 628 629 case SCTP_ILL_REMOVE: 630 631 if (sctp_ill == NULL) { 632 rw_exit(&sctp_g_ills_lock); 633 return; 634 } 635 if (sctp_ill->sctp_ill_ipifcnt == 0) { 636 list_remove(&sctp_g_ills[index].sctp_ill_list, 637 (void *)sctp_ill); 638 sctp_g_ills[index].ill_count--; 639 sctp_ills_count--; 640 kmem_free(sctp_ill->sctp_ill_name, 641 ill->ill_name_length); 642 kmem_free(sctp_ill, sizeof (sctp_ill_t)); 643 } else { 644 sctp_ill->sctp_ill_state = SCTP_ILLS_CONDEMNED; 645 } 646 647 break; 648 } 649 rw_exit(&sctp_g_ills_lock); 650 } 651 652 /* move ipif from f_ill to t_ill */ 653 void 654 sctp_move_ipif(ipif_t *ipif, ill_t *f_ill, ill_t *t_ill) 655 { 656 sctp_ill_t *fsctp_ill = NULL; 657 sctp_ill_t *tsctp_ill = NULL; 658 sctp_ipif_t *sctp_ipif; 659 uint_t index; 660 int i; 661 662 rw_enter(&sctp_g_ills_lock, RW_READER); 663 rw_enter(&sctp_g_ipifs_lock, RW_READER); 664 665 index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(f_ill)); 666 fsctp_ill = list_head(&sctp_g_ills[index].sctp_ill_list); 667 for (i = 0; i < sctp_g_ills[index].ill_count; i++) { 668 if (fsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(f_ill)) 669 break; 670 fsctp_ill = list_next(&sctp_g_ills[index].sctp_ill_list, 671 fsctp_ill); 672 } 673 674 index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(t_ill)); 675 tsctp_ill = list_head(&sctp_g_ills[index].sctp_ill_list); 676 for (i = 0; i < sctp_g_ills[index].ill_count; i++) { 677 if (tsctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(t_ill)) 678 break; 679 tsctp_ill = list_next(&sctp_g_ills[index].sctp_ill_list, 680 tsctp_ill); 681 } 682 683 index = SCTP_IPIF_HASH_FN(ipif->ipif_seqid); 684 sctp_ipif = list_head(&sctp_g_ipifs[index].sctp_ipif_list); 685 for (i = 0; i < sctp_g_ipifs[index].ipif_count; i++) { 686 if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid) 687 break; 688 sctp_ipif = list_next(&sctp_g_ipifs[index].sctp_ipif_list, 689 sctp_ipif); 690 } 691 /* Should be an ASSERT? */ 692 if (fsctp_ill == NULL || tsctp_ill == NULL || sctp_ipif == NULL) { 693 ip1dbg(("sctp_move_ipif: error moving ipif %p from %p to %p\n", 694 (void *)ipif, (void *)f_ill, (void *)t_ill)); 695 rw_exit(&sctp_g_ipifs_lock); 696 rw_exit(&sctp_g_ills_lock); 697 return; 698 } 699 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER); 700 ASSERT(sctp_ipif->sctp_ipif_ill == fsctp_ill); 701 sctp_ipif->sctp_ipif_ill = tsctp_ill; 702 rw_exit(&sctp_ipif->sctp_ipif_lock); 703 (void) atomic_add_32_nv(&fsctp_ill->sctp_ill_ipifcnt, -1); 704 atomic_add_32(&tsctp_ill->sctp_ill_ipifcnt, 1); 705 rw_exit(&sctp_g_ipifs_lock); 706 rw_exit(&sctp_g_ills_lock); 707 } 708 709 /* Insert, Remove, Mark up or Mark down the ipif */ 710 void 711 sctp_update_ipif(ipif_t *ipif, int op) 712 { 713 ill_t *ill = ipif->ipif_ill; 714 int i; 715 sctp_ill_t *sctp_ill; 716 sctp_ipif_t *sctp_ipif; 717 uint_t ill_index; 718 uint_t ipif_index; 719 720 ip2dbg(("sctp_update_ipif: %s %d\n", ill->ill_name, ipif->ipif_seqid)); 721 722 rw_enter(&sctp_g_ills_lock, RW_READER); 723 rw_enter(&sctp_g_ipifs_lock, RW_WRITER); 724 725 ill_index = SCTP_ILL_HASH_FN(SCTP_ILL_TO_PHYINDEX(ill)); 726 sctp_ill = list_head(&sctp_g_ills[ill_index].sctp_ill_list); 727 for (i = 0; i < sctp_g_ills[ill_index].ill_count; i++) { 728 if (sctp_ill->sctp_ill_index == SCTP_ILL_TO_PHYINDEX(ill)) 729 break; 730 sctp_ill = list_next(&sctp_g_ills[ill_index].sctp_ill_list, 731 sctp_ill); 732 } 733 if (sctp_ill == NULL) { 734 rw_exit(&sctp_g_ipifs_lock); 735 rw_exit(&sctp_g_ills_lock); 736 return; 737 } 738 739 ipif_index = SCTP_IPIF_HASH_FN(ipif->ipif_seqid); 740 sctp_ipif = list_head(&sctp_g_ipifs[ipif_index].sctp_ipif_list); 741 for (i = 0; i < sctp_g_ipifs[ipif_index].ipif_count; i++) { 742 if (sctp_ipif->sctp_ipif_id == ipif->ipif_seqid) 743 break; 744 sctp_ipif = list_next(&sctp_g_ipifs[ipif_index].sctp_ipif_list, 745 sctp_ipif); 746 } 747 if (op != SCTP_IPIF_INSERT && sctp_ipif == NULL) { 748 ip1dbg(("sctp_update_ipif: null sctp_ipif for %d\n", op)); 749 rw_exit(&sctp_g_ipifs_lock); 750 rw_exit(&sctp_g_ills_lock); 751 return; 752 } 753 #ifdef DEBUG 754 if (sctp_ipif != NULL) 755 ASSERT(sctp_ill == sctp_ipif->sctp_ipif_ill); 756 #endif 757 switch (op) { 758 case SCTP_IPIF_INSERT: 759 if (sctp_ipif != NULL) { 760 if (sctp_ipif->sctp_ipif_state == SCTP_IPIFS_CONDEMNED) 761 sctp_ipif->sctp_ipif_state = 0; 762 rw_exit(&sctp_g_ipifs_lock); 763 rw_exit(&sctp_g_ills_lock); 764 return; 765 } 766 sctp_ipif = kmem_zalloc(sizeof (sctp_ipif_t), KM_NOSLEEP); 767 /* Try again? */ 768 if (sctp_ipif == NULL) { 769 ip1dbg(("sctp_ipif_insert: mem failure..\n")); 770 rw_exit(&sctp_g_ipifs_lock); 771 rw_exit(&sctp_g_ills_lock); 772 return; 773 } 774 sctp_ipif->sctp_ipif_id = ipif->ipif_seqid; 775 sctp_ipif->sctp_ipif_ill = sctp_ill; 776 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN; 777 sctp_ipif->sctp_ipif_mtu = ipif->ipif_mtu; 778 sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr; 779 sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid; 780 sctp_ipif->sctp_ipif_isv6 = ill->ill_isv6; 781 rw_init(&sctp_ipif->sctp_ipif_lock, NULL, RW_DEFAULT, NULL); 782 list_insert_tail(&sctp_g_ipifs[ipif_index].sctp_ipif_list, 783 (void *)sctp_ipif); 784 sctp_g_ipifs[ipif_index].ipif_count++; 785 sctp_g_ipifs_count++; 786 atomic_add_32(&sctp_ill->sctp_ill_ipifcnt, 1); 787 788 break; 789 790 case SCTP_IPIF_REMOVE: 791 { 792 list_t *ipif_list; 793 list_t *ill_list; 794 795 ill_list = &sctp_g_ills[ill_index].sctp_ill_list; 796 ipif_list = &sctp_g_ipifs[ipif_index].sctp_ipif_list; 797 if (sctp_ipif->sctp_ipif_refcnt != 0) { 798 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_CONDEMNED; 799 rw_exit(&sctp_g_ipifs_lock); 800 rw_exit(&sctp_g_ills_lock); 801 return; 802 } 803 list_remove(ipif_list, (void *)sctp_ipif); 804 sctp_g_ipifs[ipif_index].ipif_count--; 805 sctp_g_ipifs_count--; 806 rw_destroy(&sctp_ipif->sctp_ipif_lock); 807 kmem_free(sctp_ipif, sizeof (sctp_ipif_t)); 808 (void) atomic_add_32_nv(&sctp_ill->sctp_ill_ipifcnt, -1); 809 if (rw_tryupgrade(&sctp_g_ills_lock) != 0) { 810 rw_downgrade(&sctp_g_ipifs_lock); 811 if (sctp_ill->sctp_ill_ipifcnt == 0 && 812 sctp_ill->sctp_ill_state == SCTP_ILLS_CONDEMNED) { 813 list_remove(ill_list, (void *)sctp_ill); 814 sctp_ills_count--; 815 sctp_g_ills[ill_index].ill_count--; 816 kmem_free(sctp_ill->sctp_ill_name, 817 sctp_ill->sctp_ill_name_length); 818 kmem_free(sctp_ill, sizeof (sctp_ill_t)); 819 } 820 } 821 break; 822 } 823 824 case SCTP_IPIF_UP: 825 826 rw_downgrade(&sctp_g_ipifs_lock); 827 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER); 828 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_UP; 829 sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr; 830 rw_exit(&sctp_ipif->sctp_ipif_lock); 831 832 break; 833 834 case SCTP_IPIF_UPDATE: 835 836 rw_downgrade(&sctp_g_ipifs_lock); 837 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER); 838 sctp_ipif->sctp_ipif_mtu = ipif->ipif_mtu; 839 sctp_ipif->sctp_ipif_saddr = ipif->ipif_v6lcl_addr; 840 sctp_ipif->sctp_ipif_zoneid = ipif->ipif_zoneid; 841 rw_exit(&sctp_ipif->sctp_ipif_lock); 842 843 break; 844 845 case SCTP_IPIF_DOWN: 846 847 rw_downgrade(&sctp_g_ipifs_lock); 848 rw_enter(&sctp_ipif->sctp_ipif_lock, RW_WRITER); 849 sctp_ipif->sctp_ipif_state = SCTP_IPIFS_DOWN; 850 rw_exit(&sctp_ipif->sctp_ipif_lock); 851 852 break; 853 } 854 rw_exit(&sctp_g_ipifs_lock); 855 rw_exit(&sctp_g_ills_lock); 856 } 857 858 /* 859 * 860 * 861 * SCTP source address list manipulaton, locking not used (except for 862 * sctp locking by the caller. 863 * 864 * 865 */ 866 867 /* Remove a specific saddr from the list */ 868 void 869 sctp_del_saddr(sctp_t *sctp, sctp_saddr_ipif_t *sp) 870 { 871 if (sctp->sctp_conn_tfp != NULL) 872 mutex_enter(&sctp->sctp_conn_tfp->tf_lock); 873 874 if (sctp->sctp_listen_tfp != NULL) 875 mutex_enter(&sctp->sctp_listen_tfp->tf_lock); 876 877 sctp_ipif_hash_remove(sctp, sp->saddr_ipifp); 878 879 if (sctp->sctp_bound_to_all) 880 sctp->sctp_bound_to_all = 0; 881 882 if (sctp->sctp_conn_tfp != NULL) 883 mutex_exit(&sctp->sctp_conn_tfp->tf_lock); 884 885 if (sctp->sctp_listen_tfp != NULL) 886 mutex_exit(&sctp->sctp_listen_tfp->tf_lock); 887 } 888 889 /* 890 * Delete source address from the existing list. No error checking done here 891 * Called with no locks held. 892 */ 893 void 894 sctp_del_saddr_list(sctp_t *sctp, const void *addrs, int addcnt, 895 boolean_t fanout_locked) 896 { 897 struct sockaddr_in *sin4; 898 struct sockaddr_in6 *sin6; 899 int cnt; 900 in6_addr_t addr; 901 sctp_ipif_t *sctp_ipif; 902 903 ASSERT(sctp->sctp_nsaddrs > addcnt); 904 905 if (!fanout_locked) { 906 if (sctp->sctp_conn_tfp != NULL) 907 mutex_enter(&sctp->sctp_conn_tfp->tf_lock); 908 if (sctp->sctp_listen_tfp != NULL) 909 mutex_enter(&sctp->sctp_listen_tfp->tf_lock); 910 } 911 912 for (cnt = 0; cnt < addcnt; cnt++) { 913 switch (sctp->sctp_family) { 914 case AF_INET: 915 sin4 = (struct sockaddr_in *)addrs + cnt; 916 IN6_INADDR_TO_V4MAPPED(&sin4->sin_addr, &addr); 917 break; 918 919 case AF_INET6: 920 sin6 = (struct sockaddr_in6 *)addrs + cnt; 921 addr = sin6->sin6_addr; 922 break; 923 } 924 sctp_ipif = sctp_lookup_ipif_addr(&addr, B_FALSE, 925 sctp->sctp_zoneid); 926 ASSERT(sctp_ipif != NULL); 927 sctp_ipif_hash_remove(sctp, sctp_ipif); 928 } 929 if (sctp->sctp_bound_to_all) 930 sctp->sctp_bound_to_all = 0; 931 932 if (!fanout_locked) { 933 if (sctp->sctp_conn_tfp != NULL) 934 mutex_exit(&sctp->sctp_conn_tfp->tf_lock); 935 if (sctp->sctp_listen_tfp != NULL) 936 mutex_exit(&sctp->sctp_listen_tfp->tf_lock); 937 } 938 } 939 940 /* 941 * Given an address get the corresponding entry from the list 942 * Called with no locks held. 943 */ 944 sctp_saddr_ipif_t * 945 sctp_saddr_lookup(sctp_t *sctp, in6_addr_t *addr) 946 { 947 sctp_saddr_ipif_t *saddr_ipifs; 948 sctp_ipif_t *sctp_ipif; 949 950 sctp_ipif = sctp_lookup_ipif_addr(addr, B_FALSE, sctp->sctp_zoneid); 951 if (sctp_ipif == NULL) 952 return (NULL); 953 954 saddr_ipifs = sctp_ipif_lookup(sctp, sctp_ipif->sctp_ipif_id); 955 return (saddr_ipifs); 956 } 957 958 /* Get the first valid address from the list. Called with no locks held */ 959 in6_addr_t 960 sctp_get_valid_addr(sctp_t *sctp, boolean_t isv6) 961 { 962 int i; 963 int l; 964 sctp_saddr_ipif_t *obj; 965 int scanned = 0; 966 in6_addr_t addr; 967 968 for (i = 0; i < SCTP_IPIF_HASH; i++) { 969 if (sctp->sctp_saddrs[i].ipif_count == 0) 970 continue; 971 obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list); 972 for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) { 973 sctp_ipif_t *ipif; 974 sctp_ill_t *ill; 975 976 ipif = obj->saddr_ipifp; 977 ill = ipif->sctp_ipif_ill; 978 if (!obj->saddr_ipif_dontsrc && 979 ipif->sctp_ipif_isv6 == isv6 && 980 ipif->sctp_ipif_state == SCTP_IPIFS_UP && 981 !(ill->sctp_ill_flags & PHYI_LOOPBACK)) { 982 return (ipif->sctp_ipif_saddr); 983 } 984 scanned++; 985 if (scanned >= sctp->sctp_nsaddrs) 986 goto got_none; 987 obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list, 988 obj); 989 } 990 } 991 got_none: 992 /* Need to double check this */ 993 if (isv6 == B_TRUE) 994 addr = ipv6_all_zeros; 995 else 996 IN6_IPADDR_TO_V4MAPPED(0, &addr); 997 998 return (addr); 999 } 1000 1001 /* Given a list, get the combined lengths. Called with no locks held. */ 1002 size_t 1003 sctp_addr_len(sctp_t *sctp, int af) 1004 { 1005 int i; 1006 int l; 1007 sctp_saddr_ipif_t *obj; 1008 size_t paramlen = 0; 1009 int scanned = 0; 1010 1011 for (i = 0; i < SCTP_IPIF_HASH; i++) { 1012 if (sctp->sctp_saddrs[i].ipif_count == 0) 1013 continue; 1014 obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list); 1015 for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) { 1016 in6_addr_t addr; 1017 sctp_ipif_t *ipif; 1018 sctp_ill_t *ill; 1019 1020 ipif = obj->saddr_ipifp; 1021 ill = ipif->sctp_ipif_ill; 1022 scanned++; 1023 if ((ipif->sctp_ipif_state != SCTP_IPIFS_UP) || 1024 (ill->sctp_ill_flags & PHYI_LOOPBACK)) { 1025 if (scanned >= sctp->sctp_nsaddrs) 1026 return (paramlen); 1027 1028 obj = list_next(&sctp->sctp_saddrs[i]. 1029 sctp_ipif_list, obj); 1030 continue; 1031 } 1032 addr = ipif->sctp_ipif_saddr; 1033 if (IN6_IS_ADDR_V4MAPPED(&addr)) { 1034 /* 1035 * Only send v4 address if the other side 1036 * supports it. 1037 */ 1038 if (af & PARM_SUPP_V4) 1039 paramlen += PARM_ADDR4_LEN; 1040 } else if (!IN6_IS_ADDR_LINKLOCAL(&addr) && 1041 (af & PARM_SUPP_V6)) { 1042 paramlen += PARM_ADDR6_LEN; 1043 } 1044 if (scanned >= sctp->sctp_nsaddrs) 1045 return (paramlen); 1046 obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list, 1047 obj); 1048 } 1049 } 1050 return (paramlen); 1051 } 1052 1053 /* 1054 * Return the list of local addresses of an association. The parameter 1055 * myaddrs is supposed to be either (struct sockaddr_in *) or (struct 1056 * sockaddr_in6 *) depending on the address family. 1057 */ 1058 int 1059 sctp_getmyaddrs(void *conn, void *myaddrs, int *addrcnt) 1060 { 1061 int i; 1062 int l; 1063 sctp_saddr_ipif_t *obj; 1064 sctp_t *sctp = (sctp_t *)conn; 1065 int family = sctp->sctp_family; 1066 int max = *addrcnt; 1067 size_t added = 0; 1068 struct sockaddr_in6 *sin6; 1069 struct sockaddr_in *sin4; 1070 int scanned = 0; 1071 boolean_t skip_lback = B_FALSE; 1072 1073 if (sctp->sctp_nsaddrs == 0) 1074 return (EINVAL); 1075 1076 /* Skip loopback addresses for non-loopback assoc. */ 1077 if (sctp->sctp_state >= SCTPS_ESTABLISHED && !sctp->sctp_loopback) 1078 skip_lback = B_TRUE; 1079 for (i = 0; i < SCTP_IPIF_HASH; i++) { 1080 if (sctp->sctp_saddrs[i].ipif_count == 0) 1081 continue; 1082 obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list); 1083 for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) { 1084 sctp_ipif_t *ipif = obj->saddr_ipifp; 1085 sctp_ill_t *ill = ipif->sctp_ipif_ill; 1086 in6_addr_t addr = ipif->sctp_ipif_saddr; 1087 1088 scanned++; 1089 if ((ipif->sctp_ipif_state == SCTP_IPIFS_CONDEMNED) || 1090 obj->saddr_ipif_dontsrc || 1091 ((ill->sctp_ill_flags & PHYI_LOOPBACK) && 1092 skip_lback)) { 1093 if (scanned >= sctp->sctp_nsaddrs) 1094 goto done; 1095 obj = list_next(&sctp->sctp_saddrs[i]. 1096 sctp_ipif_list, obj); 1097 continue; 1098 } 1099 switch (family) { 1100 case AF_INET: 1101 sin4 = (struct sockaddr_in *)myaddrs + added; 1102 sin4->sin_family = AF_INET; 1103 sin4->sin_port = sctp->sctp_lport; 1104 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr); 1105 break; 1106 1107 case AF_INET6: 1108 sin6 = (struct sockaddr_in6 *)myaddrs + added; 1109 sin6->sin6_family = AF_INET6; 1110 sin6->sin6_port = sctp->sctp_lport; 1111 sin6->sin6_addr = addr; 1112 break; 1113 } 1114 added++; 1115 if (added >= max || scanned >= sctp->sctp_nsaddrs) 1116 goto done; 1117 obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list, 1118 obj); 1119 } 1120 } 1121 done: 1122 *addrcnt = added; 1123 return (0); 1124 } 1125 1126 /* 1127 * Given a list construct the list of addresses in p. Called with no locks 1128 * held 1129 */ 1130 size_t 1131 sctp_addr_val(sctp_t *sctp, int supp_af, uchar_t *p) 1132 { 1133 int i; 1134 int l; 1135 sctp_saddr_ipif_t *obj; 1136 size_t added = 0; 1137 sctp_parm_hdr_t *hdr; 1138 int scanned = 0; 1139 1140 for (i = 0; i < SCTP_IPIF_HASH; i++) { 1141 if (sctp->sctp_saddrs[i].ipif_count == 0) 1142 continue; 1143 obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list); 1144 for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) { 1145 in6_addr_t addr; 1146 sctp_ipif_t *ipif; 1147 sctp_ill_t *ill; 1148 1149 ipif = obj->saddr_ipifp; 1150 ill = ipif->sctp_ipif_ill; 1151 scanned++; 1152 if ((ipif->sctp_ipif_state != SCTP_IPIFS_UP) || 1153 (ill->sctp_ill_flags & PHYI_LOOPBACK)) { 1154 if (scanned >= sctp->sctp_nsaddrs) 1155 return (added); 1156 obj = list_next(&sctp->sctp_saddrs[i]. 1157 sctp_ipif_list, obj); 1158 continue; 1159 } 1160 hdr = (sctp_parm_hdr_t *)(p + added); 1161 addr = ipif->sctp_ipif_saddr; 1162 if (IN6_IS_ADDR_V4MAPPED(&addr)) { 1163 struct in_addr *v4; 1164 1165 /* The other side does not support v4 */ 1166 if (!(supp_af & PARM_SUPP_V4)) 1167 continue; 1168 1169 hdr->sph_type = htons(PARM_ADDR4); 1170 hdr->sph_len = htons(PARM_ADDR4_LEN); 1171 v4 = (struct in_addr *)(hdr + 1); 1172 IN6_V4MAPPED_TO_INADDR(&addr, v4); 1173 added += PARM_ADDR4_LEN; 1174 } else if (!IN6_IS_ADDR_LINKLOCAL(&addr) && 1175 (supp_af & PARM_SUPP_V6)) { 1176 hdr->sph_type = htons(PARM_ADDR6); 1177 hdr->sph_len = htons(PARM_ADDR6_LEN); 1178 bcopy(&addr, hdr + 1, sizeof (addr)); 1179 added += PARM_ADDR6_LEN; 1180 } 1181 if (scanned >= sctp->sctp_nsaddrs) 1182 return (added); 1183 obj = list_next(&sctp->sctp_saddrs[i].sctp_ipif_list, 1184 obj); 1185 } 1186 } 1187 return (added); 1188 } 1189 1190 1191 /* Initialize the SCTP ILL list and lock */ 1192 void 1193 sctp_saddr_init() 1194 { 1195 int i; 1196 1197 rw_init(&sctp_g_ills_lock, NULL, RW_DEFAULT, NULL); 1198 rw_init(&sctp_g_ipifs_lock, NULL, RW_DEFAULT, NULL); 1199 1200 for (i = 0; i < SCTP_ILL_HASH; i++) { 1201 sctp_g_ills[i].ill_count = 0; 1202 list_create(&sctp_g_ills[i].sctp_ill_list, sizeof (sctp_ill_t), 1203 offsetof(sctp_ill_t, sctp_ills)); 1204 } 1205 for (i = 0; i < SCTP_IPIF_HASH; i++) { 1206 sctp_g_ipifs[i].ipif_count = 0; 1207 list_create(&sctp_g_ipifs[i].sctp_ipif_list, 1208 sizeof (sctp_ipif_t), offsetof(sctp_ipif_t, sctp_ipifs)); 1209 } 1210 } 1211 1212 void 1213 sctp_saddr_fini() 1214 { 1215 int i; 1216 1217 rw_destroy(&sctp_g_ills_lock); 1218 rw_destroy(&sctp_g_ipifs_lock); 1219 ASSERT(sctp_ills_count == 0 && sctp_g_ipifs_count == 0); 1220 for (i = 0; i < SCTP_ILL_HASH; i++) 1221 list_destroy(&sctp_g_ills[i].sctp_ill_list); 1222 for (i = 0; i < SCTP_IPIF_HASH; i++) 1223 list_destroy(&sctp_g_ipifs[i].sctp_ipif_list); 1224 } 1225