Date: Mon, 2 Feb 2026 12:58:05 +0800 From: Zhenlei Huang <zlei@FreeBSD.org> To: Martin Mayer <martin.mayer@m2-it-solutions.de> Cc: Vadim Goncharov <vadimnuclight@gmail.com>, "freebsd-net@freebsd.org" <freebsd-net@freebsd.org>, Gleb Smirnoff <glebius@FreeBSD.org> Subject: Re: promisc/netgraph question Message-ID: <BFA9B02C-7B09-42D5-8DD4-381BA276B68A@FreeBSD.org> In-Reply-To: <FR2PPF447E0FD2FF81BF6D4A7538B0D0894BC9CA@FR2PPF447E0FD2F.DEUP281.PROD.OUTLOOK.COM> References: <FR2PPF447E0FD2F4AB3B97FDEBCB7FC5404BC9FA@FR2PPF447E0FD2F.DEUP281.PROD.OUTLOOK.COM> <FR2PPF447E0FD2FA1F4CFD7A4DF76B5DDD1BC9FA@FR2PPF447E0FD2F.DEUP281.PROD.OUTLOOK.COM> <20260130234931.073ec5df@nuclight.lan> <FR2PPF447E0FD2FF81BF6D4A7538B0D0894BC9CA@FR2PPF447E0FD2F.DEUP281.PROD.OUTLOOK.COM>
index | next in thread | previous in thread | raw e-mail
> On Jan 31, 2026, at 3:44 PM, Martin Mayer <martin.mayer@m2-it-solutions.de> wrote: > > 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 > > The logic from ng_ether(4), ``` /* * Handle an mbuf received on the "upper" hook. */ static int ng_ether_rcv_upper(hook_p hook, item_p item) { .... m->m_pkthdr.rcvif = ifp; /* Pass the packet to the bridge, it may come back to us */ if (ifp->if_bridge) { BRIDGE_INPUT(ifp, m); if (m == NULL) return (0); } /* Route packet back in */ ether_demux(ifp, m); return (0); } ``` it lacks checking of the dest MAC of the inbound packets, and unconditionally inject packets ( no matter whether they're for us or not ) via ether_demux() to the net stack. Probably we should 1. check the dest MAC address prior to passing the packets to ng_ether(4), or 2. teach ng_ether(4) to check the dest MAC address, or 3. Move the checking to ether_demux(). The 3rd one has the minimal impact. I'm CCing Gleb who is more familiar with netgraph. Best regards, Zhenleihome | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?BFA9B02C-7B09-42D5-8DD4-381BA276B68A>
