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 9 static 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 */ 19 static 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 */ 42 static inline int nf_hook_ingress_active(struct sk_buff *skb) 43 { 44 return 0; 45 } 46 47 static 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 54 static 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 * Returns @skb on success or %NULL if the packet was consumed or filtered. 70 * Caller must hold rcu_read_lock. 71 * 72 * On ingress, packets are classified first by tc, then by netfilter. 73 * On egress, the order is reversed for symmetry. Conceptually, tc and 74 * netfilter can be thought of as layers, with netfilter layered above tc: 75 * When tc redirects a packet to another interface, netfilter is not applied 76 * because the packet is on the tc layer. 77 * 78 * The nf_skip_egress flag controls whether netfilter is applied on egress. 79 * It is updated by __netif_receive_skb_core() and __dev_queue_xmit() when the 80 * packet passes through tc and netfilter. Because __dev_queue_xmit() may be 81 * called recursively by tunnel drivers such as vxlan, the flag is reverted to 82 * false after sch_handle_egress(). This ensures that netfilter is applied 83 * both on the overlay and underlying network. 84 */ 85 static inline struct sk_buff *nf_hook_egress(struct sk_buff *skb, int *rc, 86 struct net_device *dev) 87 { 88 struct nf_hook_entries *e; 89 struct nf_hook_state state; 90 int ret; 91 92 #ifdef CONFIG_NETFILTER_SKIP_EGRESS 93 if (skb->nf_skip_egress) 94 return skb; 95 #endif 96 97 e = rcu_dereference_check(dev->nf_hooks_egress, rcu_read_lock_bh_held()); 98 if (!e) 99 return skb; 100 101 nf_hook_state_init(&state, NF_NETDEV_EGRESS, 102 NFPROTO_NETDEV, NULL, dev, NULL, 103 dev_net(dev), NULL); 104 105 /* nf assumes rcu_read_lock, not just read_lock_bh */ 106 rcu_read_lock(); 107 ret = nf_hook_slow(skb, &state, e, 0); 108 rcu_read_unlock(); 109 110 if (ret == 1) { 111 return skb; 112 } else if (ret < 0) { 113 *rc = NET_XMIT_DROP; 114 return NULL; 115 } else { /* ret == 0 */ 116 *rc = NET_XMIT_SUCCESS; 117 return NULL; 118 } 119 } 120 #else /* CONFIG_NETFILTER_EGRESS */ 121 static inline bool nf_hook_egress_active(void) 122 { 123 return false; 124 } 125 126 static inline struct sk_buff *nf_hook_egress(struct sk_buff *skb, int *rc, 127 struct net_device *dev) 128 { 129 return skb; 130 } 131 #endif /* CONFIG_NETFILTER_EGRESS */ 132 133 static inline void nf_skip_egress(struct sk_buff *skb, bool skip) 134 { 135 #ifdef CONFIG_NETFILTER_SKIP_EGRESS 136 skb->nf_skip_egress = skip; 137 #endif 138 } 139 140 static inline void nf_hook_netdev_init(struct net_device *dev) 141 { 142 #ifdef CONFIG_NETFILTER_INGRESS 143 RCU_INIT_POINTER(dev->nf_hooks_ingress, NULL); 144 #endif 145 #ifdef CONFIG_NETFILTER_EGRESS 146 RCU_INIT_POINTER(dev->nf_hooks_egress, NULL); 147 #endif 148 } 149 150 #endif /* _NETFILTER_NETDEV_H_ */ 151