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