brintos

brintos / linux-shallow public Read only

0
0
Text · 4.0 KiB · 8676316 Raw
151 lines · c
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_INGRESS9static inline bool nf_hook_ingress_active(const struct sk_buff *skb)10{11#ifdef CONFIG_JUMP_LABEL12	if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][NF_NETDEV_INGRESS]))13		return false;14#endif15	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 NULL26	 * 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_EGRESS54static inline bool nf_hook_egress_active(void)55{56#ifdef CONFIG_JUMP_LABEL57	if (!static_key_false(&nf_hooks_needed[NFPROTO_NETDEV][NF_NETDEV_EGRESS]))58		return false;59#endif60	return true;61}62 63/**64 * nf_hook_egress - classify packets before transmission65 * @skb: packet to be classified66 * @rc: result code which shall be returned by __dev_queue_xmit() on failure67 * @dev: netdev whose egress hooks shall be applied to @skb68 *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 and74 * netfilter can be thought of as layers, with netfilter layered above tc:75 * When tc redirects a packet to another interface, netfilter is not applied76 * 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 the80 * packet passes through tc and netfilter.  Because __dev_queue_xmit() may be81 * called recursively by tunnel drivers such as vxlan, the flag is reverted to82 * false after sch_handle_egress().  This ensures that netfilter is applied83 * both on the overlay and underlying network.84 */85static 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_EGRESS93	if (skb->nf_skip_egress)94		return skb;95#endif96 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 */121static inline bool nf_hook_egress_active(void)122{123	return false;124}125 126static 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 133static inline void nf_skip_egress(struct sk_buff *skb, bool skip)134{135#ifdef CONFIG_NETFILTER_SKIP_EGRESS136	skb->nf_skip_egress = skip;137#endif138}139 140static inline void nf_hook_netdev_init(struct net_device *dev)141{142#ifdef CONFIG_NETFILTER_INGRESS143	RCU_INIT_POINTER(dev->nf_hooks_ingress, NULL);144#endif145#ifdef CONFIG_NETFILTER_EGRESS146	RCU_INIT_POINTER(dev->nf_hooks_egress, NULL);147#endif148}149 150#endif /* _NETFILTER_NETDEV_H_ */151