Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b63d4b9 authored by Alvaro Neira's avatar Alvaro Neira Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_tables_bridge: set the pktinfo for IPv4/IPv6 traffic



This patch adds the missing bits to allow to match per meta l4proto from
the bridge. Example:

  nft add rule bridge filter input ether type {ip, ip6} meta l4proto udp counter

Signed-off-by: default avatarAlvaro Neira Ayuso <alvaroneay@gmail.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 68b0faa8
Loading
Loading
Loading
Loading
+39 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
#include <net/netfilter/nf_tables_bridge.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <net/netfilter/nf_tables_ipv4.h>
#include <net/netfilter/nf_tables_ipv6.h>

int nft_bridge_iphdr_validate(struct sk_buff *skb)
{
@@ -62,6 +64,32 @@ int nft_bridge_ip6hdr_validate(struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(nft_bridge_ip6hdr_validate);

static inline void nft_bridge_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
					       const struct nf_hook_ops *ops,
					       struct sk_buff *skb,
					       const struct net_device *in,
					       const struct net_device *out)
{
	if (nft_bridge_iphdr_validate(skb))
		nft_set_pktinfo_ipv4(pkt, ops, skb, in, out);
	else
		nft_set_pktinfo(pkt, ops, skb, in, out);
}

static inline void nft_bridge_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
					      const struct nf_hook_ops *ops,
					      struct sk_buff *skb,
					      const struct net_device *in,
					      const struct net_device *out)
{
#if IS_ENABLED(CONFIG_IPV6)
	if (nft_bridge_ip6hdr_validate(skb) &&
	    nft_set_pktinfo_ipv6(pkt, ops, skb, in, out) == 0)
		return;
#endif
	nft_set_pktinfo(pkt, ops, skb, in, out);
}

static unsigned int
nft_do_chain_bridge(const struct nf_hook_ops *ops,
		    struct sk_buff *skb,
@@ -71,7 +99,17 @@ nft_do_chain_bridge(const struct nf_hook_ops *ops,
{
	struct nft_pktinfo pkt;

	switch (eth_hdr(skb)->h_proto) {
	case htons(ETH_P_IP):
		nft_bridge_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
		break;
	case htons(ETH_P_IPV6):
		nft_bridge_set_pktinfo_ipv6(&pkt, ops, skb, in, out);
		break;
	default:
		nft_set_pktinfo(&pkt, ops, skb, in, out);
		break;
	}

	return nft_do_chain(&pkt, ops);
}