| 2421 | } |
| 2422 | |
| 2423 | static struct sockaddr * |
| 2424 | sctp_find_valid_localaddr(struct sctp_tcb *stcb, int addr_locked) |
| 2425 | { |
| 2426 | struct sctp_vrf *vrf = NULL; |
| 2427 | struct sctp_ifn *sctp_ifn; |
| 2428 | struct sctp_ifa *sctp_ifa; |
| 2429 | |
| 2430 | if (addr_locked == SCTP_ADDR_NOT_LOCKED) |
| 2431 | SCTP_IPI_ADDR_RLOCK(); |
| 2432 | vrf = sctp_find_vrf(stcb->asoc.vrf_id); |
| 2433 | if (vrf == NULL) { |
| 2434 | if (addr_locked == SCTP_ADDR_NOT_LOCKED) |
| 2435 | SCTP_IPI_ADDR_RUNLOCK(); |
| 2436 | return (NULL); |
| 2437 | } |
| 2438 | LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) { |
| 2439 | if (stcb->asoc.scope.loopback_scope == 0 && |
| 2440 | SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) { |
| 2441 | /* Skip if loopback_scope not set */ |
| 2442 | continue; |
| 2443 | } |
| 2444 | LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) { |
| 2445 | switch (sctp_ifa->address.sa.sa_family) { |
| 2446 | #ifdef INET |
| 2447 | case AF_INET: |
| 2448 | if (stcb->asoc.scope.ipv4_addr_legal) { |
| 2449 | struct sockaddr_in *sin; |
| 2450 | |
| 2451 | sin = &sctp_ifa->address.sin; |
| 2452 | if (sin->sin_addr.s_addr == 0) { |
| 2453 | /* skip unspecifed addresses */ |
| 2454 | continue; |
| 2455 | } |
| 2456 | if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred, |
| 2457 | &sin->sin_addr) != 0) { |
| 2458 | continue; |
| 2459 | } |
| 2460 | if (stcb->asoc.scope.ipv4_local_scope == 0 && |
| 2461 | IN4_ISPRIVATE_ADDRESS(&sin->sin_addr)) |
| 2462 | continue; |
| 2463 | |
| 2464 | if (sctp_is_addr_restricted(stcb, sctp_ifa) && |
| 2465 | (!sctp_is_addr_pending(stcb, sctp_ifa))) |
| 2466 | continue; |
| 2467 | /* |
| 2468 | * found a valid local v4 address to |
| 2469 | * use |
| 2470 | */ |
| 2471 | if (addr_locked == SCTP_ADDR_NOT_LOCKED) |
| 2472 | SCTP_IPI_ADDR_RUNLOCK(); |
| 2473 | return (&sctp_ifa->address.sa); |
| 2474 | } |
| 2475 | break; |
| 2476 | #endif |
| 2477 | #ifdef INET6 |
| 2478 | case AF_INET6: |
| 2479 | if (stcb->asoc.scope.ipv6_addr_legal) { |
| 2480 | struct sockaddr_in6 *sin6; |
no test coverage detected