* Lookup link headerfor @sa_dst address. Stores found * data in @desten buffer. Copy of lle ln_flags can be also * saved in @pflags if @pflags is non-NULL. * * If destination LLE does not exists or lle state modification * is required, call "slow" version. * * Return values: * - 0 on success (address copied to buffer). * - EWOULDBLOCK (no local error, but address is still unresolved) * -
| 2211 | * - other errors (alloc failure, etc) |
| 2212 | */ |
| 2213 | int |
| 2214 | nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m, |
| 2215 | const struct sockaddr *sa_dst, u_char *desten, uint32_t *pflags, |
| 2216 | struct llentry **plle) |
| 2217 | { |
| 2218 | struct llentry *ln = NULL; |
| 2219 | const struct sockaddr_in6 *dst6; |
| 2220 | |
| 2221 | NET_EPOCH_ASSERT(); |
| 2222 | |
| 2223 | if (pflags != NULL) |
| 2224 | *pflags = 0; |
| 2225 | |
| 2226 | dst6 = (const struct sockaddr_in6 *)sa_dst; |
| 2227 | |
| 2228 | /* discard the packet if IPv6 operation is disabled on the interface */ |
| 2229 | if ((ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED)) { |
| 2230 | m_freem(m); |
| 2231 | return (ENETDOWN); /* better error? */ |
| 2232 | } |
| 2233 | |
| 2234 | if (m != NULL && m->m_flags & M_MCAST) { |
| 2235 | switch (ifp->if_type) { |
| 2236 | case IFT_ETHER: |
| 2237 | case IFT_L2VLAN: |
| 2238 | case IFT_BRIDGE: |
| 2239 | ETHER_MAP_IPV6_MULTICAST(&dst6->sin6_addr, |
| 2240 | desten); |
| 2241 | return (0); |
| 2242 | default: |
| 2243 | m_freem(m); |
| 2244 | return (EAFNOSUPPORT); |
| 2245 | } |
| 2246 | } |
| 2247 | |
| 2248 | ln = nd6_lookup(&dst6->sin6_addr, plle ? LLE_EXCLUSIVE : LLE_UNLOCKED, |
| 2249 | ifp); |
| 2250 | if (ln != NULL && (ln->r_flags & RLLE_VALID) != 0) { |
| 2251 | /* Entry found, let's copy lle info */ |
| 2252 | bcopy(ln->r_linkdata, desten, ln->r_hdrlen); |
| 2253 | if (pflags != NULL) |
| 2254 | *pflags = LLE_VALID | (ln->r_flags & RLLE_IFADDR); |
| 2255 | /* Check if we have feedback request from nd6 timer */ |
| 2256 | if (ln->r_skip_req != 0) { |
| 2257 | LLE_REQ_LOCK(ln); |
| 2258 | ln->r_skip_req = 0; /* Notify that entry was used */ |
| 2259 | ln->lle_hittime = time_uptime; |
| 2260 | LLE_REQ_UNLOCK(ln); |
| 2261 | } |
| 2262 | if (plle) { |
| 2263 | LLE_ADDREF(ln); |
| 2264 | *plle = ln; |
| 2265 | LLE_WUNLOCK(ln); |
| 2266 | } |
| 2267 | return (0); |
| 2268 | } else if (plle && ln) |
| 2269 | LLE_WUNLOCK(ln); |
| 2270 |
no test coverage detected