Fix two bugs with the bridge

- code expects memcmp() to return a signed value, our memcmp() returns 0 if
   args are equal and > 0 if not.

 - It's possible to hijack interface for static entry. If bridge recieves
   packet from interface marked as learning it will replace the bridge_rtnode
   entry for the source address even if such entry marked as static.

Submitted by:	Gleb Kurtsov <k-gleb yandex.ru>
MFC after:	3 days
This commit is contained in:
Andrew Thompson 2006-01-31 21:21:28 +00:00
parent 2f4f3e134b
commit 6637e0f390
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=155143

View File

@ -215,6 +215,7 @@ static int bridge_rtdaddr(struct bridge_softc *, const uint8_t *);
static int bridge_rtable_init(struct bridge_softc *);
static void bridge_rtable_fini(struct bridge_softc *);
static int bridge_rtnode_addr_cmp(const uint8_t *, const uint8_t *);
static struct bridge_rtnode *bridge_rtnode_lookup(struct bridge_softc *,
const uint8_t *);
static int bridge_rtnode_insert(struct bridge_softc *,
@ -2193,7 +2194,8 @@ bridge_rtupdate(struct bridge_softc *sc, const uint8_t *dst,
}
}
brt->brt_ifp = dst_if;
if ((brt->brt_flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
brt->brt_ifp = dst_if;
if ((flags & IFBAF_TYPEMASK) == IFBAF_DYNAMIC)
brt->brt_expire = time_uptime + sc->sc_brttimeout;
if (setflags)
@ -2424,6 +2426,18 @@ bridge_rthash(struct bridge_softc *sc, const uint8_t *addr)
#undef mix
static int
bridge_rtnode_addr_cmp(const uint8_t *a, const uint8_t *b)
{
int i, d;
for (i = 0, d = 0; i < ETHER_ADDR_LEN && d == 0; i++) {
d = ((int)a[i]) - ((int)b[i]);
}
return (d);
}
/*
* bridge_rtnode_lookup:
*
@ -2440,7 +2454,7 @@ bridge_rtnode_lookup(struct bridge_softc *sc, const uint8_t *addr)
hash = bridge_rthash(sc, addr);
LIST_FOREACH(brt, &sc->sc_rthash[hash], brt_hash) {
dir = memcmp(addr, brt->brt_addr, ETHER_ADDR_LEN);
dir = bridge_rtnode_addr_cmp(addr, brt->brt_addr);
if (dir == 0)
return (brt);
if (dir > 0)
@ -2474,7 +2488,7 @@ bridge_rtnode_insert(struct bridge_softc *sc, struct bridge_rtnode *brt)
}
do {
dir = memcmp(brt->brt_addr, lbrt->brt_addr, ETHER_ADDR_LEN);
dir = bridge_rtnode_addr_cmp(brt->brt_addr, lbrt->brt_addr);
if (dir == 0)
return (EEXIST);
if (dir > 0) {