diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/netfilter/nf_tables_bridge.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c index d468c19faecd..19473a9371b8 100644 --- a/net/bridge/netfilter/nf_tables_bridge.c +++ b/net/bridge/netfilter/nf_tables_bridge.c @@ -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; - nft_set_pktinfo(&pkt, ops, skb, in, out); + 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); } |