1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-18 15:30:21 +00:00

In ARP input, more consistently acquire and release ifaddr references.

MFC after:	6 weeks
This commit is contained in:
Robert Watson 2009-06-24 10:33:35 +00:00
parent 6c7ffe9340
commit 09d547787f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=194820

View File

@ -512,13 +512,16 @@ in_arpinput(struct mbuf *m)
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) {
if (((bridged && ia->ia_ifp->if_bridge != NULL) || if (((bridged && ia->ia_ifp->if_bridge != NULL) ||
ia->ia_ifp == ifp) && ia->ia_ifp == ifp) &&
itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
ifa_ref(&ia->ia_ifa);
goto match; goto match;
}
#ifdef DEV_CARP #ifdef DEV_CARP
if (ifp->if_carp != NULL && if (ifp->if_carp != NULL &&
carp_iamatch(ifp->if_carp, ia, &isaddr, &enaddr) && carp_iamatch(ifp->if_carp, ia, &isaddr, &enaddr) &&
itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) { itaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
carp_match = 1; carp_match = 1;
ifa_ref(&ia->ia_ifa);
goto match; goto match;
} }
#endif #endif
@ -526,8 +529,10 @@ in_arpinput(struct mbuf *m)
LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash) LIST_FOREACH(ia, INADDR_HASH(isaddr.s_addr), ia_hash)
if (((bridged && ia->ia_ifp->if_bridge != NULL) || if (((bridged && ia->ia_ifp->if_bridge != NULL) ||
ia->ia_ifp == ifp) && ia->ia_ifp == ifp) &&
isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) isaddr.s_addr == ia->ia_addr.sin_addr.s_addr) {
ifa_ref(&ia->ia_ifa);
goto match; goto match;
}
#define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \ #define BDG_MEMBER_MATCHES_ARP(addr, ifp, ia) \
(ia->ia_ifp->if_bridge == ifp->if_softc && \ (ia->ia_ifp->if_bridge == ifp->if_softc && \
@ -542,6 +547,7 @@ in_arpinput(struct mbuf *m)
if (is_bridge) { if (is_bridge) {
LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) { LIST_FOREACH(ia, INADDR_HASH(itaddr.s_addr), ia_hash) {
if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) { if (BDG_MEMBER_MATCHES_ARP(itaddr.s_addr, ifp, ia)) {
ifa_ref(&ia->ia_ifa);
ifp = ia->ia_ifp; ifp = ia->ia_ifp;
goto match; goto match;
} }
@ -553,20 +559,26 @@ in_arpinput(struct mbuf *m)
* No match, use the first inet address on the receive interface * No match, use the first inet address on the receive interface
* as a dummy address for the rest of the function. * as a dummy address for the rest of the function.
*/ */
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
if (ifa->ifa_addr->sa_family == AF_INET) { if (ifa->ifa_addr->sa_family == AF_INET) {
ia = ifatoia(ifa); ia = ifatoia(ifa);
ifa_ref(ifa);
goto match; goto match;
} }
IF_ADDR_UNLOCK(ifp);
/* /*
* If bridging, fall back to using any inet address. * If bridging, fall back to using any inet address.
*/ */
if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL) if (!bridged || (ia = TAILQ_FIRST(&V_in_ifaddrhead)) == NULL)
goto drop; goto drop;
ifa_ref(&ia->ia_ifa);
match: match:
if (!enaddr) if (!enaddr)
enaddr = (u_int8_t *)IF_LLADDR(ifp); enaddr = (u_int8_t *)IF_LLADDR(ifp);
myaddr = ia->ia_addr.sin_addr; myaddr = ia->ia_addr.sin_addr;
ifa_free(&ia->ia_ifa);
if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen)) if (!bcmp(ar_sha(ah), enaddr, ifp->if_addrlen))
goto drop; /* it's from me, ignore it. */ goto drop; /* it's from me, ignore it. */
if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) { if (!bcmp(ar_sha(ah), ifp->if_broadcastaddr, ifp->if_addrlen)) {