From: Eric Woudstra <ericwouds@gmail.com>
To: Pablo Neira Ayuso <pablo@netfilter.org>,
Jozsef Kadlecsik <kadlec@netfilter.org>,
Nikolay Aleksandrov <razor@blackwall.org>,
Ido Schimmel <idosch@nvidia.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Simon Horman <horms@kernel.org>
Cc: netfilter-devel@vger.kernel.org, bridge@lists.linux.dev,
netdev@vger.kernel.org, Eric Woudstra <ericwouds@gmail.com>
Subject: [PATCH v13 nf-next 2/3] netfilter: bridge: Add conntrack double vlan and pppoe
Date: Fri, 4 Jul 2025 21:11:34 +0200 [thread overview]
Message-ID: <20250704191135.1815969-3-ericwouds@gmail.com> (raw)
In-Reply-To: <20250704191135.1815969-1-ericwouds@gmail.com>
This adds the capability to conntrack 802.1ad, QinQ, PPPoE and PPPoE-in-Q
packets that are passing a bridge, only when a conntrack zone is set.
Signed-off-by: Eric Woudstra <ericwouds@gmail.com>
---
net/bridge/netfilter/nf_conntrack_bridge.c | 88 ++++++++++++++++++----
1 file changed, 72 insertions(+), 16 deletions(-)
diff --git a/net/bridge/netfilter/nf_conntrack_bridge.c b/net/bridge/netfilter/nf_conntrack_bridge.c
index 6482de4d8750..5fcb1bdf2e31 100644
--- a/net/bridge/netfilter/nf_conntrack_bridge.c
+++ b/net/bridge/netfilter/nf_conntrack_bridge.c
@@ -242,53 +242,109 @@ static unsigned int nf_ct_bridge_pre(void *priv, struct sk_buff *skb,
{
struct nf_hook_state bridge_state = *state;
enum ip_conntrack_info ctinfo;
+ u32 len, data_len = U32_MAX;
+ int ret, offset = 0;
struct nf_conn *ct;
- u32 len;
- int ret;
+ __be16 outer_proto;
ct = nf_ct_get(skb, &ctinfo);
if ((ct && !nf_ct_is_template(ct)) ||
ctinfo == IP_CT_UNTRACKED)
return NF_ACCEPT;
+ if (ct && nf_ct_zone_id(nf_ct_zone(ct), CTINFO2DIR(ctinfo)) !=
+ NF_CT_DEFAULT_ZONE_ID) {
+ switch (skb->protocol) {
+ case htons(ETH_P_PPP_SES): {
+ struct ppp_hdr {
+ struct pppoe_hdr hdr;
+ __be16 proto;
+ } *ph;
+
+ offset = PPPOE_SES_HLEN;
+ if (!pskb_may_pull(skb, offset))
+ return NF_ACCEPT;
+ outer_proto = skb->protocol;
+ ph = (struct ppp_hdr *)(skb->data);
+ switch (ph->proto) {
+ case htons(PPP_IP):
+ skb->protocol = htons(ETH_P_IP);
+ break;
+ case htons(PPP_IPV6):
+ skb->protocol = htons(ETH_P_IPV6);
+ break;
+ default:
+ nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
+ return NF_ACCEPT;
+ }
+ data_len = ntohs(ph->hdr.length) - 2;
+ skb_set_network_header(skb, offset);
+ break;
+ }
+ case htons(ETH_P_8021Q): {
+ struct vlan_hdr *vhdr;
+
+ offset = VLAN_HLEN;
+ if (!pskb_may_pull(skb, offset))
+ return NF_ACCEPT;
+ outer_proto = skb->protocol;
+ vhdr = (struct vlan_hdr *)(skb->data);
+ skb->protocol = vhdr->h_vlan_encapsulated_proto;
+ data_len = U32_MAX;
+ skb_set_network_header(skb, offset);
+ break;
+ }
+ }
+ }
+
+ ret = NF_ACCEPT;
switch (skb->protocol) {
case htons(ETH_P_IP):
- if (!pskb_may_pull(skb, sizeof(struct iphdr)))
- return NF_ACCEPT;
+ if (!pskb_may_pull(skb, offset + sizeof(struct iphdr)))
+ goto do_not_track;
len = skb_ip_totlen(skb);
- if (pskb_trim_rcsum(skb, len))
- return NF_ACCEPT;
+ if (data_len < len)
+ len = data_len;
+ if (pskb_trim_rcsum(skb, len + offset))
+ goto do_not_track;
if (nf_ct_br_ip_check(skb))
- return NF_ACCEPT;
+ goto do_not_track;
bridge_state.pf = NFPROTO_IPV4;
ret = nf_ct_br_defrag4(skb, &bridge_state);
break;
case htons(ETH_P_IPV6):
- if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
- return NF_ACCEPT;
+ if (!pskb_may_pull(skb, offset + sizeof(struct ipv6hdr)))
+ goto do_not_track;
len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len);
- if (pskb_trim_rcsum(skb, len))
- return NF_ACCEPT;
+ if (data_len < len)
+ len = data_len;
+ if (pskb_trim_rcsum(skb, len + offset))
+ goto do_not_track;
if (nf_ct_br_ipv6_check(skb))
- return NF_ACCEPT;
+ goto do_not_track;
bridge_state.pf = NFPROTO_IPV6;
ret = nf_ct_br_defrag6(skb, &bridge_state);
break;
default:
nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
- return NF_ACCEPT;
+ goto do_not_track;
}
- if (ret != NF_ACCEPT)
- return ret;
+ if (ret == NF_ACCEPT)
+ ret = nf_conntrack_in(skb, &bridge_state);
- return nf_conntrack_in(skb, &bridge_state);
+do_not_track:
+ if (offset) {
+ skb_reset_network_header(skb);
+ skb->protocol = outer_proto;
+ }
+ return ret;
}
static unsigned int nf_ct_bridge_in(void *priv, struct sk_buff *skb,
--
2.47.1
next prev parent reply other threads:[~2025-07-04 19:12 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-04 19:11 [PATCH v13 nf-next 0/3] conntrack: bridge: add double vlan, pppoe and pppoe-in-q Eric Woudstra
2025-07-04 19:11 ` [PATCH v13 nf-next 1/3] netfilter: utils: nf_checksum(_partial) correct data!=networkheader Eric Woudstra
2025-07-04 19:39 ` Florian Westphal
2025-07-05 17:33 ` kernel test robot
2025-07-14 19:06 ` Dan Carpenter
2025-07-04 19:11 ` Eric Woudstra [this message]
2025-07-04 19:11 ` [PATCH v13 nf-next 3/3] netfilter: nft_chain_filter: Add bridge double vlan and pppoe Eric Woudstra
2025-07-04 20:02 ` Florian Westphal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250704191135.1815969-3-ericwouds@gmail.com \
--to=ericwouds@gmail.com \
--cc=bridge@lists.linux.dev \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=kadlec@netfilter.org \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pablo@netfilter.org \
--cc=razor@blackwall.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.