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?

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);
 }
 
 /*

Reply via email to