summaryrefslogtreecommitdiffstats
path: root/sys/net/if_bridge.c
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2006-01-31 21:21:28 +0000
committerthompsa <thompsa@FreeBSD.org>2006-01-31 21:21:28 +0000
commitd32360b9225bbcf4985813a366ad0048f7f3f396 (patch)
tree9fbfe44cefd6a70252bb0b69215b6780edc23391 /sys/net/if_bridge.c
parent7fe6d13c28a5d890bba5f41ec1bc98f1ce65d41f (diff)
downloadFreeBSD-src-d32360b9225bbcf4985813a366ad0048f7f3f396.zip
FreeBSD-src-d32360b9225bbcf4985813a366ad0048f7f3f396.tar.gz
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
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r--sys/net/if_bridge.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 69dc466..1ec9e62 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -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) {
OpenPOWER on IntegriCloud