summaryrefslogtreecommitdiff
path: root/sys/net/if_bridge.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/if_bridge.c')
-rw-r--r--sys/net/if_bridge.c82
1 files changed, 61 insertions, 21 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index a58d3ac0fc3..656b462faa1 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.22 2000/01/10 22:18:29 angelos Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.23 2000/01/15 05:02:46 jason Exp $ */
/*
* Copyright (c) 1999 Jason L. Wright (jason@thought.net)
@@ -131,6 +131,14 @@ struct bridge_softc {
LIST_HEAD(bridge_rthead, bridge_rtnode) *sc_rts;/* hash table */
};
+/*
+ * Ethernet header and SNAP header
+ */
+struct ehllc {
+ struct ether_header eh;
+ struct llc llc;
+};
+
struct bridge_softc bridgectl[NBRIDGE];
void bridgeattach __P((int));
@@ -153,6 +161,7 @@ struct ifnet * bridge_rtupdate __P((struct bridge_softc *,
struct ifnet * bridge_rtlookup __P((struct bridge_softc *,
struct ether_addr *));
u_int32_t bridge_hash __P((struct ether_addr *));
+struct mbuf *bridge_blocknonip __P((struct mbuf *));
#define ETHERADDR_IS_IP_MCAST(a) \
/* struct etheraddr *a; */ \
@@ -762,13 +771,13 @@ bridgeintr(void)
}
}
- if ((ifl->bif_flags & IFBIF_BLOCKNONIP) &&
- (eh->ether_type != htons(ETHERTYPE_IP)) &&
- (eh->ether_type != htons(ETHERTYPE_IPV6)) &&
- (eh->ether_type != htons(ETHERTYPE_ARP)) &&
- (eh->ether_type != htons(ETHERTYPE_REVARP))) {
- m_freem(m);
- continue;
+ if (ifl->bif_flags & IFBIF_BLOCKNONIP) {
+ m = bridge_blocknonip(m);
+ if (m == NULL)
+ continue;
+ eh = mtod(m, struct ether_header *);
+ dst = (struct ether_addr *)&eh->ether_dhost[0];
+ src = (struct ether_addr *)&eh->ether_shost[0];
}
#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM))
@@ -937,13 +946,6 @@ bridge_broadcast(sc, ifp, eh, m)
(m->m_flags & (M_BCAST | M_MCAST)) == 0)
continue;
- if ((p->bif_flags & IFBIF_BLOCKNONIP) &&
- (eh->ether_type != htons(ETHERTYPE_IP)) &&
- (eh->ether_type != htons(ETHERTYPE_IPV6)) &&
- (eh->ether_type != htons(ETHERTYPE_ARP)) &&
- (eh->ether_type != htons(ETHERTYPE_REVARP)))
- continue;
-
if ((p->ifp->if_flags & IFF_RUNNING) == 0)
continue;
@@ -965,8 +967,14 @@ bridge_broadcast(sc, ifp, eh, m)
}
}
+ if (p->bif_flags & IFBIF_BLOCKNONIP) {
+ mc = bridge_blocknonip(mc);
+ if (mc == NULL)
+ continue;
+ }
+
sc->sc_if.if_opackets++;
- sc->sc_if.if_obytes += m->m_pkthdr.len;
+ sc->sc_if.if_obytes += mc->m_pkthdr.len;
if ((eh->ether_shost[0] & 1) == 0)
ifp->if_omcasts++;
@@ -1435,12 +1443,44 @@ done:
return (error);
}
-#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM))
+struct mbuf *
+bridge_blocknonip(m)
+ struct mbuf *m;
+{
+ struct ehllc *ehllc;
+ u_int16_t etype;
-struct ehllc {
- struct ether_header eh;
- struct llc llc;
-};
+ if (m->m_len < sizeof(struct ehllc)) {
+ m = m_pullup(m, sizeof(struct ehllc));
+ if (m == NULL)
+ return (m);
+ }
+
+ ehllc = mtod(m, struct ehllc *);
+ etype = ntohs(ehllc->eh.ether_type);
+
+ if (etype == ETHERTYPE_ARP || etype == ETHERTYPE_REVARP ||
+ etype == ETHERTYPE_IP || etype == ETHERTYPE_IPV6)
+ return (m);
+
+ if (etype > ETHERMTU)
+ goto notip;
+
+ if (ehllc->llc.llc_control == LLC_UI &&
+ ehllc->llc.llc_dsap == LLC_SNAP_LSAP &&
+ ehllc->llc.llc_ssap == LLC_SNAP_LSAP) {
+ etype = ntohs(ehllc->llc.llc_snap.ether_type);
+ if (etype == ETHERTYPE_ARP || etype == ETHERTYPE_REVARP ||
+ etype == ETHERTYPE_IP || etype == ETHERTYPE_IPV6)
+ return (m);
+ }
+
+notip:
+ m_freem(m);
+ return (NULL);
+}
+
+#if defined(INET) && (defined(IPFILTER) || defined(IPFILTER_LKM))
/*
* Filter IP packets by peeking into the ethernet frame. This violates