diff options
Diffstat (limited to 'sys/netinet/if_ether.c')
-rw-r--r-- | sys/netinet/if_ether.c | 139 |
1 files changed, 19 insertions, 120 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index f6c5c12..b1133c9 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -344,14 +344,15 @@ arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip, * Resolve an IP address into an ethernet address. * On input: * ifp is the interface we use - * dst is the next hop, * rt0 is the route to the final destination (possibly useless) - * m is the mbuf + * m is the mbuf. May be NULL if we don't have a packet. + * dst is the next hop, * desten is where we want the address. * * On success, desten is filled in and the function returns 0; * If the packet must be held pending resolution, we return EWOULDBLOCK * On other errors, we return the corresponding error code. + * Note that m_freem() handles NULL. */ int arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, @@ -362,13 +363,18 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, struct sockaddr_dl *sdl; int error; - if (m->m_flags & M_BCAST) { /* broadcast */ - (void)memcpy(desten, ifp->if_broadcastaddr, ifp->if_addrlen); - return (0); - } - if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) {/* multicast */ - ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); - return (0); + if (m) { + if (m->m_flags & M_BCAST) { + /* broadcast */ + (void)memcpy(desten, + ifp->if_broadcastaddr, ifp->if_addrlen); + return (0); + } + if (m->m_flags & M_MCAST && ifp->if_type != IFT_ARCNET) { + /* multicast */ + ETHER_MAP_IP_MULTICAST(&SIN(dst)->sin_addr, desten); + return (0); + } } if (rt0 != NULL) { @@ -449,117 +455,10 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, * response yet. Replace the held mbuf with this * latest one. */ - if (la->la_hold) - m_freem(la->la_hold); - la->la_hold = m; - KASSERT(rt->rt_expire > 0, ("sending ARP request for static entry")); - - /* - * Return EWOULDBLOCK if we have tried less than arp_maxtries. It - * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH - * if we have already sent arp_maxtries ARP requests. Retransmit the - * ARP request, but not faster than one request per second. - */ - if (la->la_asked < arp_maxtries) - error = EWOULDBLOCK; /* First request. */ - else - error = (rt == rt0) ? EHOSTDOWN : EHOSTUNREACH; - - if (la->la_asked == 0 || rt->rt_expire != time_uptime) { - struct in_addr sin = - SIN(rt->rt_ifa->ifa_addr)->sin_addr; - - rt->rt_expire = time_uptime; - callout_reset(&la->la_timer, hz, arptimer, rt); - la->la_asked++; - RT_UNLOCK(rt); - - arprequest(ifp, &sin, &SIN(dst)->sin_addr, - IF_LLADDR(ifp)); - } else - RT_UNLOCK(rt); - - return (error); -} - - -int -arpresolve2(struct ifnet *ifp, struct rtentry *rt0, struct sockaddr *dst, - u_char *desten) -{ - struct llinfo_arp *la = NULL; - struct rtentry *rt = NULL; - struct sockaddr_dl *sdl; - int error; - - if (rt0 != NULL) { - error = rt_check(&rt, &rt0, dst); - if (error) - return (error); - - la = (struct llinfo_arp *)rt->rt_llinfo; - if (la == NULL) - RT_UNLOCK(rt); - } - if (la == NULL) { - /* - * We enter this block in case if rt0 was NULL, - * or if rt found by rt_check() didn't have llinfo. - */ - rt = arplookup(SIN(dst)->sin_addr.s_addr, 1, 0); - if (rt == NULL) { - log(LOG_DEBUG, - "arpresolve: can't allocate route for %s\n", - inet_ntoa(SIN(dst)->sin_addr)); - return (EINVAL); /* XXX */ - } - la = (struct llinfo_arp *)rt->rt_llinfo; - if (la == NULL) { - RT_UNLOCK(rt); - log(LOG_DEBUG, - "arpresolve: can't allocate llinfo for %s\n", - inet_ntoa(SIN(dst)->sin_addr)); - return (EINVAL); /* XXX */ - } - } - sdl = SDL(rt->rt_gateway); - /* - * Check the address family and length is valid, the address - * is resolved; otherwise, try to resolve. - */ - if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) && - sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { - - bcopy(LLADDR(sdl), desten, sdl->sdl_alen); - - /* - * If entry has an expiry time and it is approaching, - * send an ARP request. - */ - if ((rt->rt_expire != 0) && - (time_uptime + la->la_preempt > rt->rt_expire)) { - struct in_addr sin = - SIN(rt->rt_ifa->ifa_addr)->sin_addr; - - la->la_preempt--; - RT_UNLOCK(rt); - arprequest(ifp, &sin, &SIN(dst)->sin_addr, - IF_LLADDR(ifp)); - return (0); - } - - RT_UNLOCK(rt); - return (0); - } - /* - * If ARP is disabled or static on this interface, stop. - * XXX - * Probably should not allocate empty llinfo struct if we are - * not going to be sending out an arp request. - */ - if (ifp->if_flags & (IFF_NOARP | IFF_STATICARP)) { - RT_UNLOCK(rt); - return (EINVAL); + if (m) { + if (la->la_hold) + m_freem(la->la_hold); + la->la_hold = m; } KASSERT(rt->rt_expire > 0, ("sending ARP request for static entry")); |