summaryrefslogtreecommitdiffstats
path: root/sys/net/if_ethersubr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/if_ethersubr.c')
-rw-r--r--sys/net/if_ethersubr.c69
1 files changed, 61 insertions, 8 deletions
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index f7a5158..1a5b0c9 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -56,6 +56,7 @@
#include <net/if_llc.h>
#include <net/if_dl.h>
#include <net/if_types.h>
+#include <net/bpf.h>
#if defined(INET) || defined(INET6)
#include <netinet/in.h>
@@ -365,19 +366,22 @@ ether_output(ifp, m, dst, rt0)
return (0); /* XXX */
}
}
+
#ifdef BRIDGE
if (do_bridge) {
- struct mbuf *m0 = m ;
-
- if (m->m_pkthdr.rcvif)
- m->m_pkthdr.rcvif = NULL ;
- ifp = bridge_dst_lookup(m);
- bdg_forward(&m0, ifp);
- if (m0)
- m_freem(m0);
+ struct ether_header hdr;
+
+ m->m_pkthdr.rcvif = NULL;
+ bcopy(mtod(m, struct ether_header *), &hdr, ETHER_HDR_LEN);
+ m_adj(m, ETHER_HDR_LEN);
+ ifp = bridge_dst_lookup(&hdr);
+ bdg_forward(&m, &hdr, ifp);
+ if (m != NULL)
+ m_freem(m);
return (0);
}
#endif
+
s = splimp();
/*
* Queue message on interface, and start output if interface
@@ -421,6 +425,55 @@ ether_input(ifp, eh, m)
register struct llc *l;
#endif
+ /* Check for a BPF tap */
+ if (ifp->if_bpf != NULL) {
+ struct m_hdr mh;
+
+ /* This kludge is OK; BPF treats the "mbuf" as read-only */
+ mh.mh_next = m;
+ mh.mh_data = (char *)eh;
+ mh.mh_len = ETHER_HDR_LEN;
+ bpf_mtap(ifp, (struct mbuf *)&mh);
+ }
+
+#ifdef BRIDGE
+ /* Check for bridging mode */
+ if (do_bridge) {
+ struct ifnet *bif;
+
+ /* Check with bridging code */
+ if ((bif = bridge_in(ifp, eh)) == BDG_DROP) {
+ m_freem(m);
+ return;
+ }
+ if (bif != BDG_LOCAL)
+ bdg_forward(&m, eh, bif); /* needs forwarding */
+ if (bif == BDG_LOCAL
+ || bif == BDG_BCAST
+ || bif == BDG_MCAST)
+ goto recvLocal; /* receive locally */
+
+ /* If not local and not multicast, just drop it */
+ if (m != NULL)
+ m_freem(m);
+ return;
+ }
+#endif
+
+ /* Discard packet if upper layers shouldn't see it. This should
+ only happen when the interface is in promiscuous mode. */
+ if ((ifp->if_flags & IFF_PROMISC) != 0
+ && (eh->ether_dhost[0] & 1) == 0
+ && bcmp(eh->ether_dhost,
+ IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN) != 0) {
+ m_freem(m);
+ return;
+ }
+
+#ifdef BRIDGE
+recvLocal:
+#endif
+ /* Discard packet if interface is not up */
if ((ifp->if_flags & IFF_UP) == 0) {
m_freem(m);
return;
OpenPOWER on IntegriCloud