On Mon, Oct 26, 2015 at 07:08:19PM +0100, Martin Pieuchot wrote:
> This rewrites the code to send an ARP reply to no use ``myaddr''. The
> goal is to get rid of the per-ifp address list iterations.
>
> Instead do two route lookups.
>
> ok?
Should the "reply:" label stay before the "if (op != ARPOP_REQUEST)"?
Otherwise you could send a reply in response to a reply.
bluhm
>
> Index: netinet/if_ether.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/if_ether.c,v
> retrieving revision 1.177
> diff -u -p -r1.177 if_ether.c
> --- netinet/if_ether.c 25 Oct 2015 11:58:11 -0000 1.177
> +++ netinet/if_ether.c 26 Oct 2015 18:01:12 -0000
> @@ -519,8 +519,9 @@ in_arpinput(struct mbuf *m)
> #endif
> char addr[INET_ADDRSTRLEN];
> int op, changed = 0;
> - unsigned int len;
> + unsigned int len, rdomain;
>
> + rdomain = rtable_l2(m->m_pkthdr.ph_rtableid);
> ifp = if_get(m->m_pkthdr.ph_ifidx);
> if (ifp == NULL) {
> m_freem(m);
> @@ -606,7 +607,7 @@ in_arpinput(struct mbuf *m)
> goto reply;
> }
> rt = arplookup(isaddr.s_addr, itaddr.s_addr == myaddr.s_addr, 0,
> - rtable_l2(m->m_pkthdr.ph_rtableid));
> + rdomain);
> if (rt != NULL && (sdl = satosdl(rt->rt_gateway)) != NULL) {
> la = (struct llinfo_arp *)rt->rt_llinfo;
> if (sdl->sdl_alen) {
> @@ -693,32 +694,29 @@ in_arpinput(struct mbuf *m)
> }
> }
> }
> -reply:
> - if (op != ARPOP_REQUEST) {
> -out:
> - rtfree(rt);
> - if_put(ifp);
> - m_freem(m);
> - return;
> - }
>
> + if (op != ARPOP_REQUEST)
> + goto out;
> rtfree(rt);
> - if (itaddr.s_addr == myaddr.s_addr) {
> - /* I am the target */
> - memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
> - memcpy(ea->arp_sha, enaddr, sizeof(ea->arp_sha));
> - } else {
> - rt = arplookup(itaddr.s_addr, 0, SIN_PROXY,
> - rtable_l2(m->m_pkthdr.ph_rtableid));
> - if (rt == NULL)
> - goto out;
> - if (rt->rt_ifp->if_type == IFT_CARP && ifp->if_type != IFT_CARP)
> +
> +
> +reply:
> + /*
> + * Reply if we have a local or proxy entry.
> + */
> + rt = arplookup(itaddr.s_addr, 0, SIN_PROXY, rdomain);
> + if (!rtisvalid(rt)) {
> + rt = arplookup(itaddr.s_addr, 0, 0, rdomain);
> + if (!rtisvalid(rt) || !ISSET(rt->rt_flags, RTF_LOCAL))
> goto out;
> - memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
> - sdl = satosdl(rt->rt_gateway);
> - memcpy(ea->arp_sha, LLADDR(sdl), sizeof(ea->arp_sha));
> - rtfree(rt);
> }
> + if (rt->rt_ifp->if_type == IFT_CARP && ifp->if_type != IFT_CARP)
> + goto out;
> + memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
> + sdl = satosdl(rt->rt_gateway);
> + memcpy(ea->arp_sha, LLADDR(sdl), sizeof(ea->arp_sha));
> + rtfree(rt);
> +
>
> memcpy(ea->arp_tpa, ea->arp_spa, sizeof(ea->arp_spa));
> memcpy(ea->arp_spa, &itaddr, sizeof(ea->arp_spa));
> @@ -738,6 +736,11 @@ out:
> ifp->if_output(ifp, m, &sa, NULL);
> if_put(ifp);
> return;
> +
> +out:
> + rtfree(rt);
> + if_put(ifp);
> + m_freem(m);
> }
>
> /*