* Do L2 address resolution for @sa_dst address. Stores found * address in @desten buffer. Copy of lle ln_flags can be also * saved in @pflags if @pflags is non-NULL. * * Heavy version. * Function assume that destination LLE does not exist, * is invalid or stale, so LLE_EXCLUSIVE lock needs to be acquired. * * Set noinline to be dtrace-friendly */
| 2283 | * Set noinline to be dtrace-friendly |
| 2284 | */ |
| 2285 | static __noinline int |
| 2286 | nd6_resolve_slow(struct ifnet *ifp, int flags, struct mbuf *m, |
| 2287 | const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags, |
| 2288 | struct llentry **plle) |
| 2289 | { |
| 2290 | struct llentry *lle = NULL, *lle_tmp; |
| 2291 | struct in6_addr *psrc, src; |
| 2292 | int send_ns, ll_len; |
| 2293 | char *lladdr; |
| 2294 | |
| 2295 | NET_EPOCH_ASSERT(); |
| 2296 | |
| 2297 | /* |
| 2298 | * Address resolution or Neighbor Unreachability Detection |
| 2299 | * for the next hop. |
| 2300 | * At this point, the destination of the packet must be a unicast |
| 2301 | * or an anycast address(i.e. not a multicast). |
| 2302 | */ |
| 2303 | if (lle == NULL) { |
| 2304 | lle = nd6_lookup(&dst->sin6_addr, LLE_EXCLUSIVE, ifp); |
| 2305 | if ((lle == NULL) && nd6_is_addr_neighbor(dst, ifp)) { |
| 2306 | /* |
| 2307 | * Since nd6_is_addr_neighbor() internally calls nd6_lookup(), |
| 2308 | * the condition below is not very efficient. But we believe |
| 2309 | * it is tolerable, because this should be a rare case. |
| 2310 | */ |
| 2311 | lle = nd6_alloc(&dst->sin6_addr, 0, ifp); |
| 2312 | if (lle == NULL) { |
| 2313 | char ip6buf[INET6_ADDRSTRLEN]; |
| 2314 | log(LOG_DEBUG, |
| 2315 | "nd6_output: can't allocate llinfo for %s " |
| 2316 | "(ln=%p)\n", |
| 2317 | ip6_sprintf(ip6buf, &dst->sin6_addr), lle); |
| 2318 | m_freem(m); |
| 2319 | return (ENOBUFS); |
| 2320 | } |
| 2321 | |
| 2322 | IF_AFDATA_WLOCK(ifp); |
| 2323 | LLE_WLOCK(lle); |
| 2324 | /* Prefer any existing entry over newly-created one */ |
| 2325 | lle_tmp = nd6_lookup(&dst->sin6_addr, LLE_EXCLUSIVE, ifp); |
| 2326 | if (lle_tmp == NULL) |
| 2327 | lltable_link_entry(LLTABLE6(ifp), lle); |
| 2328 | IF_AFDATA_WUNLOCK(ifp); |
| 2329 | if (lle_tmp != NULL) { |
| 2330 | lltable_free_entry(LLTABLE6(ifp), lle); |
| 2331 | lle = lle_tmp; |
| 2332 | lle_tmp = NULL; |
| 2333 | } |
| 2334 | } |
| 2335 | } |
| 2336 | if (lle == NULL) { |
| 2337 | m_freem(m); |
| 2338 | return (ENOBUFS); |
| 2339 | } |
| 2340 | |
| 2341 | LLE_WLOCK_ASSERT(lle); |
| 2342 |
no test coverage detected