ether_demux_oncpu(struct ifnet *ifp, struct mbuf *m)
{
struct ether_header *eh;
- int isr, redispatch;
+ int isr, redispatch, discard = 0;
u_short ether_type;
struct ip_fw *rule = NULL;
#ifdef NETATALK
#endif
/*
- * Discard packet if upper layers shouldn't see it because
- * it was unicast to a different Ethernet address. If the
- * driver is working properly, then this situation can only
- * happen when the interface is in promiscuous mode.
+ * We got a packet which was unicast to a different Ethernet
+ * address. If the driver is working properly, then this
+ * situation can only happen when the interface is in
+ * promiscuous mode. We defer the packet discarding until the
+ * vlan processing is done, so that vlan/bridge or vlan/netgraph
+ * could work.
*/
if (((ifp->if_flags & (IFF_PROMISC | IFF_PPROMISC)) == IFF_PROMISC) &&
!ETHER_IS_MULTICAST(eh->ether_dhost) &&
- bcmp(eh->ether_dhost, IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN)) {
- m_freem(m);
- return;
- }
+ bcmp(eh->ether_dhost, IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN))
+ discard = 1;
post_stats:
- if (IPFW_LOADED && ether_ipfw != 0) {
+ if (IPFW_LOADED && ether_ipfw != 0 && !discard) {
struct ether_header save_eh = *eh;
/* XXX old crufty stuff, needs to be removed */
}
/*
+ * If we have been asked to discard this packet
+ * (e.g. not for us), drop it before entering
+ * the upper layer.
+ */
+ if (discard) {
+ m_freem(m);
+ return;
+ }
+
+ /*
* Clear protocol specific flags,
* before entering the upper layer.
*/