diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2014-09-30 08:27:58 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2014-09-30 08:27:58 +0000 |
commit | 6147bafceacc66b432a63c0a5a405bfaef4fa7d8 (patch) | |
tree | 05a5cba2d0f3ac017264d2ce801e4223741de1c7 | |
parent | c85e35b29d77a3789af622d51c51ffa014c152fa (diff) |
Stop using the RB-tree in ifa_ifwithaddr() and make it lookup over
all the per-interface lists of addresses.
Teaks and ok bluhm@, ok kspillner@, claudio@
-rw-r--r-- | sys/net/if.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 3b54d7abaee..96b24d57bc8 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.300 2014/08/25 14:00:34 florian Exp $ */ +/* $OpenBSD: if.c,v 1.301 2014/09/30 08:27:57 mpi Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -837,29 +837,43 @@ if_congestion_clear(void *arg) free(to, M_TEMP, 0); } +#define equal(a1, a2) \ + (bcmp((caddr_t)(a1), (caddr_t)(a2), \ + ((struct sockaddr *)(a1))->sa_len) == 0) + /* * Locate an interface based on a complete address. */ -/*ARGSUSED*/ struct ifaddr * ifa_ifwithaddr(struct sockaddr *addr, u_int rtableid) { - struct ifaddr_item *ifai, key; + struct ifnet *ifp; + struct ifaddr *ifa; + u_int rdomain; - bzero(&key, sizeof(key)); - key.ifai_addr = addr; - key.ifai_rdomain = rtable_l2(rtableid); + rdomain = rtable_l2(rtableid); + TAILQ_FOREACH(ifp, &ifnet, if_list) { + if (ifp->if_rdomain != rdomain) + continue; - ifai = RB_FIND(ifaddr_items, &ifaddr_items, &key); - if (ifai) - return (ifai->ifai_ifa); + TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + if (ifa->ifa_addr->sa_family != addr->sa_family) + continue; + + if (equal(addr, ifa->ifa_addr)) + return (ifa); + + /* IPv6 doesn't have broadcast */ + if ((ifp->if_flags & IFF_BROADCAST) && + ifa->ifa_broadaddr && + ifa->ifa_broadaddr->sa_len != 0 && + equal(ifa->ifa_broadaddr, addr)) + return (ifa); + } + } return (NULL); } -#define equal(a1, a2) \ - (bcmp((caddr_t)(a1), (caddr_t)(a2), \ - ((struct sockaddr *)(a1))->sa_len) == 0) - /* * Locate the point to point interface with a given destination address. */ |