Let me explain my intend from a higher level and forget about the code details for a moment.
If a packet ingresses an interface where ( dst MAC != interface MAC ) && ( dst MAC != multicast joined groups ) && ( dst MAC != broadcast ) I'd expect - the packet to be directly discarded if !( IFF_PROMISC || IFF_PPROMISC ) - the packet to be accepted but not passed to upper layers if ( IFF_PROMISC || IFF_PPROMISC ) A special case is CARP where IFF_PROMISC is set and should be passed to upper layers if ( dst MAC == CARP instance MAC && CARP enabled ) I think we have a consensus until here. This is the current (normal) behavior. This behavior changes as soon as netgraph is involved. If ng_ether hooks are connected, the host skips these checks and passes the packet to the upper layers. The practical issue to my question is: https://github.com/opnsense/src/issues/279 I want to understand the root cause of this behavior and want to identify if this is intentionally or if it's a bug. As per my understanding, this happens in if_ethersubr.c because the hook for the packet to be claimed by netgraph is BEFORE the destination addresses are checked. [...] /* Allow ng_ether(4) to claim this frame. */ if (ifp->if_l2com != NULL) { KASSERT(ng_ether_input_p != NULL, ("%s: ng_ether_input_p is NULL", __func__)); m->m_flags &= ~M_PROMISC; (*ng_ether_input_p)(ifp, &m); if (m == NULL) { CURVNET_RESTORE(); return; } eh = mtod(m, struct ether_header *); } [...] if (ifp->if_carp && (*carp_forus_p)(ifp, eh->ether_dhost)) { m->m_flags &= ~M_PROMISC; } else { /* * If the frame received was not for our MAC address, set the * M_PROMISC flag on the mbuf chain. The frame may need to * be seen by the rest of the Ethernet input path in case of * re-entry (e.g. bridge, vlan, netgraph) but should not be * seen by upper protocol layers. */ if (!ETHER_IS_MULTICAST(eh->ether_dhost) && memcmp(IF_LLADDR(ifp), eh->ether_dhost, ETHER_ADDR_LEN) != 0) m->m_flags |= M_PROMISC; } ether_demux(ifp, m); [...] ether_demux() (which is the re-entry point from ng_ether) won't be able to correctly evaluate (m->m_flags & M_PROMISC). Thanks, Martin
