at v6.15-rc2 4.1 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef _NETFILTER_NETDEV_H_ 3#define _NETFILTER_NETDEV_H_ 4 5#include <linux/netfilter.h> 6#include <linux/netdevice.h> 7 8#ifdef CONFIG_NETFILTER_INGRESS 9static inline bool nf_hook_ingress_active(const struct sk_buff *skb) 10{ 11#ifdef CONFIG_JUMP_LABEL 12 if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][NF_NETDEV_INGRESS])) 13 return false; 14#endif 15 return rcu_access_pointer(skb->dev->nf_hooks_ingress); 16} 17 18/* caller must hold rcu_read_lock */ 19static inline int nf_hook_ingress(struct sk_buff *skb) 20{ 21 struct nf_hook_entries *e = rcu_dereference(skb->dev->nf_hooks_ingress); 22 struct nf_hook_state state; 23 int ret; 24 25 /* Must recheck the ingress hook head, in the event it became NULL 26 * after the check in nf_hook_ingress_active evaluated to true. 27 */ 28 if (unlikely(!e)) 29 return 0; 30 31 nf_hook_state_init(&state, NF_NETDEV_INGRESS, 32 NFPROTO_NETDEV, skb->dev, NULL, NULL, 33 dev_net(skb->dev), NULL); 34 ret = nf_hook_slow(skb, &state, e, 0); 35 if (ret == 0) 36 return -1; 37 38 return ret; 39} 40 41#else /* CONFIG_NETFILTER_INGRESS */ 42static inline int nf_hook_ingress_active(struct sk_buff *skb) 43{ 44 return 0; 45} 46 47static inline int nf_hook_ingress(struct sk_buff *skb) 48{ 49 return 0; 50} 51#endif /* CONFIG_NETFILTER_INGRESS */ 52 53#ifdef CONFIG_NETFILTER_EGRESS 54static inline bool nf_hook_egress_active(void) 55{ 56#ifdef CONFIG_JUMP_LABEL 57 if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][NF_NETDEV_EGRESS])) 58 return false; 59#endif 60 return true; 61} 62 63/** 64 * nf_hook_egress - classify packets before transmission 65 * @skb: packet to be classified 66 * @rc: result code which shall be returned by __dev_queue_xmit() on failure 67 * @dev: netdev whose egress hooks shall be applied to @skb 68 * 69 * Caller must hold rcu_read_lock. 70 * 71 * On ingress, packets are classified first by tc, then by netfilter. 72 * On egress, the order is reversed for symmetry. Conceptually, tc and 73 * netfilter can be thought of as layers, with netfilter layered above tc: 74 * When tc redirects a packet to another interface, netfilter is not applied 75 * because the packet is on the tc layer. 76 * 77 * The nf_skip_egress flag controls whether netfilter is applied on egress. 78 * It is updated by __netif_receive_skb_core() and __dev_queue_xmit() when the 79 * packet passes through tc and netfilter. Because __dev_queue_xmit() may be 80 * called recursively by tunnel drivers such as vxlan, the flag is reverted to 81 * false after sch_handle_egress(). This ensures that netfilter is applied 82 * both on the overlay and underlying network. 83 * 84 * Returns: @skb on success or %NULL if the packet was consumed or filtered. 85 */ 86static inline struct sk_buff *nf_hook_egress(struct sk_buff *skb, int *rc, 87 struct net_device *dev) 88{ 89 struct nf_hook_entries *e; 90 struct nf_hook_state state; 91 int ret; 92 93#ifdef CONFIG_NETFILTER_SKIP_EGRESS 94 if (skb->nf_skip_egress) 95 return skb; 96#endif 97 98 e = rcu_dereference_check(dev->nf_hooks_egress, rcu_read_lock_bh_held()); 99 if (!e) 100 return skb; 101 102 nf_hook_state_init(&state, NF_NETDEV_EGRESS, 103 NFPROTO_NETDEV, NULL, dev, NULL, 104 dev_net(dev), NULL); 105 106 /* nf assumes rcu_read_lock, not just read_lock_bh */ 107 rcu_read_lock(); 108 ret = nf_hook_slow(skb, &state, e, 0); 109 rcu_read_unlock(); 110 111 if (ret == 1) { 112 return skb; 113 } else if (ret < 0) { 114 *rc = NET_XMIT_DROP; 115 return NULL; 116 } else { /* ret == 0 */ 117 *rc = NET_XMIT_SUCCESS; 118 return NULL; 119 } 120} 121#else /* CONFIG_NETFILTER_EGRESS */ 122static inline bool nf_hook_egress_active(void) 123{ 124 return false; 125} 126 127static inline struct sk_buff *nf_hook_egress(struct sk_buff *skb, int *rc, 128 struct net_device *dev) 129{ 130 return skb; 131} 132#endif /* CONFIG_NETFILTER_EGRESS */ 133 134static inline void nf_skip_egress(struct sk_buff *skb, bool skip) 135{ 136#ifdef CONFIG_NETFILTER_SKIP_EGRESS 137 skb->nf_skip_egress = skip; 138#endif 139} 140 141static inline void nf_hook_netdev_init(struct net_device *dev) 142{ 143#ifdef CONFIG_NETFILTER_INGRESS 144 RCU_INIT_POINTER(dev->nf_hooks_ingress, NULL); 145#endif 146#ifdef CONFIG_NETFILTER_EGRESS 147 RCU_INIT_POINTER(dev->nf_hooks_egress, NULL); 148#endif 149} 150 151#endif /* _NETFILTER_NETDEV_H_ */