diff options
-rw-r--r-- | sys/netinet/if_ether.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 4544fbe..a1fb3ca 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -211,29 +211,41 @@ arprequest(struct ifnet *ifp, struct in_addr *sip, struct in_addr *tip, struct mbuf *m; struct arphdr *ah; struct sockaddr sa; + u_char *carpaddr = NULL; if (sip == NULL) { - /* XXX don't believe this can happen (or explain why) */ /* * The caller did not supply a source address, try to find * a compatible one among those assigned to this interface. */ struct ifaddr *ifa; + IF_ADDR_RLOCK(ifp); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { - if (!ifa->ifa_addr || - ifa->ifa_addr->sa_family != AF_INET) + if (ifa->ifa_addr->sa_family != AF_INET) continue; - sip = &SIN(ifa->ifa_addr)->sin_addr; + + if (ifa->ifa_carp) { + if ((*carp_iamatch_p)(ifa, &carpaddr) == 0) + continue; + sip = &IA_SIN(ifa)->sin_addr; + } else { + carpaddr = NULL; + sip = &IA_SIN(ifa)->sin_addr; + } + if (0 == ((sip->s_addr ^ tip->s_addr) & - SIN(ifa->ifa_netmask)->sin_addr.s_addr) ) + IA_MASKSIN(ifa)->sin_addr.s_addr)) break; /* found it. */ } + IF_ADDR_RUNLOCK(ifp); if (sip == NULL) { printf("%s: cannot find matching address\n", __func__); return; } } + if (enaddr == NULL) + enaddr = carpaddr ? carpaddr : (u_char *)IF_LLADDR(ifp); if ((m = m_gethdr(M_DONTWAIT, MT_DATA)) == NULL) return; @@ -328,9 +340,7 @@ retry: */ if (!(la->la_flags & LLE_STATIC) && time_uptime + la->la_preempt > la->la_expire) { - arprequest(ifp, NULL, - &SIN(dst)->sin_addr, IF_LLADDR(ifp)); - + arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL); la->la_preempt--; } @@ -406,8 +416,7 @@ retry: LLE_REMREF(la); la->la_asked++; LLE_WUNLOCK(la); - arprequest(ifp, NULL, &SIN(dst)->sin_addr, - IF_LLADDR(ifp)); + arprequest(ifp, NULL, &SIN(dst)->sin_addr, NULL); return (error); } done: |