* Find an interface address specific to an interface best matching * a given address. */
| 2096 | * a given address. |
| 2097 | */ |
| 2098 | struct ifaddr * |
| 2099 | ifaof_ifpforaddr(const struct sockaddr *addr, struct ifnet *ifp) |
| 2100 | { |
| 2101 | struct ifaddr *ifa; |
| 2102 | const char *cp, *cp2, *cp3; |
| 2103 | char *cplim; |
| 2104 | struct ifaddr *ifa_maybe = NULL; |
| 2105 | u_int af = addr->sa_family; |
| 2106 | |
| 2107 | if (af >= AF_MAX) |
| 2108 | return (NULL); |
| 2109 | |
| 2110 | NET_EPOCH_ASSERT(); |
| 2111 | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { |
| 2112 | if (ifa->ifa_addr->sa_family != af) |
| 2113 | continue; |
| 2114 | if (ifa_maybe == NULL) |
| 2115 | ifa_maybe = ifa; |
| 2116 | if (ifa->ifa_netmask == 0) { |
| 2117 | if (sa_equal(addr, ifa->ifa_addr) || |
| 2118 | (ifa->ifa_dstaddr && |
| 2119 | sa_equal(addr, ifa->ifa_dstaddr))) |
| 2120 | goto done; |
| 2121 | continue; |
| 2122 | } |
| 2123 | if (ifp->if_flags & IFF_POINTOPOINT) { |
| 2124 | if (sa_equal(addr, ifa->ifa_dstaddr)) |
| 2125 | goto done; |
| 2126 | } else { |
| 2127 | cp = addr->sa_data; |
| 2128 | cp2 = ifa->ifa_addr->sa_data; |
| 2129 | cp3 = ifa->ifa_netmask->sa_data; |
| 2130 | cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; |
| 2131 | for (; cp3 < cplim; cp3++) |
| 2132 | if ((*cp++ ^ *cp2++) & *cp3) |
| 2133 | break; |
| 2134 | if (cp3 == cplim) |
| 2135 | goto done; |
| 2136 | } |
| 2137 | } |
| 2138 | ifa = ifa_maybe; |
| 2139 | done: |
| 2140 | return (ifa); |
| 2141 | } |
| 2142 | |
| 2143 | /* |
| 2144 | * See whether new ifa is better than current one: |
no outgoing calls
no test coverage detected