| 2185 | } |
| 2186 | |
| 2187 | static int |
| 2188 | in6_lltable_rtcheck(struct ifnet *ifp, |
| 2189 | u_int flags, |
| 2190 | const struct sockaddr *l3addr) |
| 2191 | { |
| 2192 | const struct sockaddr_in6 *sin6; |
| 2193 | struct nhop_object *nh; |
| 2194 | struct in6_addr dst; |
| 2195 | uint32_t scopeid; |
| 2196 | char ip6buf[INET6_ADDRSTRLEN]; |
| 2197 | int fibnum; |
| 2198 | |
| 2199 | NET_EPOCH_ASSERT(); |
| 2200 | KASSERT(l3addr->sa_family == AF_INET6, |
| 2201 | ("sin_family %d", l3addr->sa_family)); |
| 2202 | |
| 2203 | sin6 = (const struct sockaddr_in6 *)l3addr; |
| 2204 | in6_splitscope(&sin6->sin6_addr, &dst, &scopeid); |
| 2205 | fibnum = V_rt_add_addr_allfibs ? RT_DEFAULT_FIB : ifp->if_fib; |
| 2206 | nh = fib6_lookup(fibnum, &dst, scopeid, NHR_NONE, 0); |
| 2207 | if (nh && ((nh->nh_flags & NHF_GATEWAY) || nh->nh_ifp != ifp)) { |
| 2208 | struct ifaddr *ifa; |
| 2209 | /* |
| 2210 | * Create an ND6 cache for an IPv6 neighbor |
| 2211 | * that is not covered by our own prefix. |
| 2212 | */ |
| 2213 | ifa = ifaof_ifpforaddr(l3addr, ifp); |
| 2214 | if (ifa != NULL) { |
| 2215 | return 0; |
| 2216 | } |
| 2217 | log(LOG_INFO, "IPv6 address: \"%s\" is not on the network\n", |
| 2218 | ip6_sprintf(ip6buf, &sin6->sin6_addr)); |
| 2219 | return EINVAL; |
| 2220 | } |
| 2221 | return 0; |
| 2222 | } |
| 2223 | |
| 2224 | /* |
| 2225 | * Called by the datapath to indicate that the entry was used. |
no test coverage detected