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(dev->nf_hooks_egress); 98 if (!e) 99 return skb; 100 101 nf_hook_state_init(&state, NF_NETDEV_EGRESS, 102 NFPROTO_NETDEV, dev, NULL, NULL, 103 dev_net(dev), NULL); 104 ret = nf_hook_slow(skb, &state, e, 0); 105 106 if (ret == 1) { 107 return skb; 108 } else if (ret < 0) { 109 *rc = NET_XMIT_DROP; 110 return NULL; 111 } else { /* ret == 0 */ 112 *rc = NET_XMIT_SUCCESS; 113 return NULL; 114 } 115 } 116 #else /* CONFIG_NETFILTER_EGRESS */ 117 static inline bool nf_hook_egress_active(void) 118 { 119 return false; 120 } 121 122 static inline struct sk_buff *nf_hook_egress(struct sk_buff *skb, int *rc, 123 struct net_device *dev) 124 { 125 return skb; 126 } 127 #endif /* CONFIG_NETFILTER_EGRESS */ 128 129 static inline void nf_skip_egress(struct sk_buff *skb, bool skip) 130 { 131 #ifdef CONFIG_NETFILTER_SKIP_EGRESS 132 skb->nf_skip_egress = skip; 133 #endif 134 } 135 136 static inline void nf_hook_netdev_init(struct net_device *dev) 137 { 138 #ifdef CONFIG_NETFILTER_INGRESS 139 RCU_INIT_POINTER(dev->nf_hooks_ingress, NULL); 140 #endif 141 #ifdef CONFIG_NETFILTER_EGRESS 142 RCU_INIT_POINTER(dev->nf_hooks_egress, NULL); 143 #endif 144 } 145 146 #endif /* _NETFILTER_NETDEV_H_ */ 147