Linux Audio

Check our new training course

Loading...
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 *
  4 * Generic part shared by ipv4 and ipv6 backends.
  5 */
  6
  7#include <linux/kernel.h>
  8#include <linux/init.h>
  9#include <linux/module.h>
 10#include <linux/netlink.h>
 11#include <linux/netfilter.h>
 12#include <linux/netfilter/nf_tables.h>
 13#include <net/netfilter/nf_tables_core.h>
 14#include <net/netfilter/nf_tables.h>
 15#include <net/netfilter/nft_fib.h>
 16
 
 
 
 
 17const struct nla_policy nft_fib_policy[NFTA_FIB_MAX + 1] = {
 18	[NFTA_FIB_DREG]		= { .type = NLA_U32 },
 19	[NFTA_FIB_RESULT]	= { .type = NLA_U32 },
 20	[NFTA_FIB_FLAGS]	= { .type = NLA_U32 },
 
 21};
 22EXPORT_SYMBOL(nft_fib_policy);
 23
 24#define NFTA_FIB_F_ALL (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR | \
 25			NFTA_FIB_F_MARK | NFTA_FIB_F_IIF | NFTA_FIB_F_OIF | \
 26			NFTA_FIB_F_PRESENT)
 27
 28int nft_fib_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
 29		     const struct nft_data **data)
 30{
 31	const struct nft_fib *priv = nft_expr_priv(expr);
 32	unsigned int hooks;
 33
 34	switch (priv->result) {
 35	case NFT_FIB_RESULT_OIF:
 36	case NFT_FIB_RESULT_OIFNAME:
 37		hooks = (1 << NF_INET_PRE_ROUTING);
 
 
 
 
 38		break;
 39	case NFT_FIB_RESULT_ADDRTYPE:
 40		if (priv->flags & NFTA_FIB_F_IIF)
 41			hooks = (1 << NF_INET_PRE_ROUTING) |
 42				(1 << NF_INET_LOCAL_IN) |
 43				(1 << NF_INET_FORWARD);
 44		else if (priv->flags & NFTA_FIB_F_OIF)
 45			hooks = (1 << NF_INET_LOCAL_OUT) |
 46				(1 << NF_INET_POST_ROUTING) |
 47				(1 << NF_INET_FORWARD);
 48		else
 49			hooks = (1 << NF_INET_LOCAL_IN) |
 50				(1 << NF_INET_LOCAL_OUT) |
 51				(1 << NF_INET_FORWARD) |
 52				(1 << NF_INET_PRE_ROUTING) |
 53				(1 << NF_INET_POST_ROUTING);
 54
 55		break;
 56	default:
 57		return -EINVAL;
 58	}
 59
 60	return nft_chain_validate_hooks(ctx->chain, hooks);
 61}
 62EXPORT_SYMBOL_GPL(nft_fib_validate);
 63
 64int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 65		 const struct nlattr * const tb[])
 66{
 67	struct nft_fib *priv = nft_expr_priv(expr);
 68	unsigned int len;
 69	int err;
 70
 71	if (!tb[NFTA_FIB_DREG] || !tb[NFTA_FIB_RESULT] || !tb[NFTA_FIB_FLAGS])
 72		return -EINVAL;
 73
 74	priv->flags = ntohl(nla_get_be32(tb[NFTA_FIB_FLAGS]));
 75
 76	if (priv->flags == 0 || (priv->flags & ~NFTA_FIB_F_ALL))
 77		return -EINVAL;
 78
 79	if ((priv->flags & (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR)) ==
 80			   (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR))
 81		return -EINVAL;
 82	if ((priv->flags & (NFTA_FIB_F_IIF | NFTA_FIB_F_OIF)) ==
 83			   (NFTA_FIB_F_IIF | NFTA_FIB_F_OIF))
 84		return -EINVAL;
 85	if ((priv->flags & (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR)) == 0)
 86		return -EINVAL;
 87
 88	priv->result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT]));
 89
 90	switch (priv->result) {
 91	case NFT_FIB_RESULT_OIF:
 92		if (priv->flags & NFTA_FIB_F_OIF)
 93			return -EINVAL;
 94		len = sizeof(int);
 95		break;
 96	case NFT_FIB_RESULT_OIFNAME:
 97		if (priv->flags & NFTA_FIB_F_OIF)
 98			return -EINVAL;
 99		len = IFNAMSIZ;
100		break;
101	case NFT_FIB_RESULT_ADDRTYPE:
102		len = sizeof(u32);
103		break;
104	default:
105		return -EINVAL;
106	}
107
108	err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg,
109				       NULL, NFT_DATA_VALUE, len);
110	if (err < 0)
111		return err;
112
113	return 0;
114}
115EXPORT_SYMBOL_GPL(nft_fib_init);
116
117int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr)
118{
119	const struct nft_fib *priv = nft_expr_priv(expr);
120
121	if (nft_dump_register(skb, NFTA_FIB_DREG, priv->dreg))
122		return -1;
123
124	if (nla_put_be32(skb, NFTA_FIB_RESULT, htonl(priv->result)))
125		return -1;
126
127	if (nla_put_be32(skb, NFTA_FIB_FLAGS, htonl(priv->flags)))
128		return -1;
129
130	return 0;
131}
132EXPORT_SYMBOL_GPL(nft_fib_dump);
133
134void nft_fib_store_result(void *reg, const struct nft_fib *priv,
135			  const struct net_device *dev)
136{
137	u32 *dreg = reg;
138	int index;
139
140	switch (priv->result) {
141	case NFT_FIB_RESULT_OIF:
142		index = dev ? dev->ifindex : 0;
143		*dreg = (priv->flags & NFTA_FIB_F_PRESENT) ? !!index : index;
 
 
 
 
144		break;
145	case NFT_FIB_RESULT_OIFNAME:
146		if (priv->flags & NFTA_FIB_F_PRESENT)
147			*dreg = !!dev;
148		else
149			strncpy(reg, dev ? dev->name : "", IFNAMSIZ);
150		break;
151	default:
152		WARN_ON_ONCE(1);
153		*dreg = 0;
154		break;
155	}
156}
157EXPORT_SYMBOL_GPL(nft_fib_store_result);
158
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159MODULE_LICENSE("GPL");
 
160MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
v6.8
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 *
  4 * Generic part shared by ipv4 and ipv6 backends.
  5 */
  6
  7#include <linux/kernel.h>
  8#include <linux/init.h>
  9#include <linux/module.h>
 10#include <linux/netlink.h>
 11#include <linux/netfilter.h>
 12#include <linux/netfilter/nf_tables.h>
 13#include <net/netfilter/nf_tables_core.h>
 14#include <net/netfilter/nf_tables.h>
 15#include <net/netfilter/nft_fib.h>
 16
 17#define NFTA_FIB_F_ALL (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR | \
 18			NFTA_FIB_F_MARK | NFTA_FIB_F_IIF | NFTA_FIB_F_OIF | \
 19			NFTA_FIB_F_PRESENT)
 20
 21const struct nla_policy nft_fib_policy[NFTA_FIB_MAX + 1] = {
 22	[NFTA_FIB_DREG]		= { .type = NLA_U32 },
 23	[NFTA_FIB_RESULT]	= { .type = NLA_U32 },
 24	[NFTA_FIB_FLAGS]	=
 25		NLA_POLICY_MASK(NLA_BE32, NFTA_FIB_F_ALL),
 26};
 27EXPORT_SYMBOL(nft_fib_policy);
 28
 
 
 
 
 29int nft_fib_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
 30		     const struct nft_data **data)
 31{
 32	const struct nft_fib *priv = nft_expr_priv(expr);
 33	unsigned int hooks;
 34
 35	switch (priv->result) {
 36	case NFT_FIB_RESULT_OIF:
 37	case NFT_FIB_RESULT_OIFNAME:
 38		hooks = (1 << NF_INET_PRE_ROUTING);
 39		if (priv->flags & NFTA_FIB_F_IIF) {
 40			hooks |= (1 << NF_INET_LOCAL_IN) |
 41				 (1 << NF_INET_FORWARD);
 42		}
 43		break;
 44	case NFT_FIB_RESULT_ADDRTYPE:
 45		if (priv->flags & NFTA_FIB_F_IIF)
 46			hooks = (1 << NF_INET_PRE_ROUTING) |
 47				(1 << NF_INET_LOCAL_IN) |
 48				(1 << NF_INET_FORWARD);
 49		else if (priv->flags & NFTA_FIB_F_OIF)
 50			hooks = (1 << NF_INET_LOCAL_OUT) |
 51				(1 << NF_INET_POST_ROUTING) |
 52				(1 << NF_INET_FORWARD);
 53		else
 54			hooks = (1 << NF_INET_LOCAL_IN) |
 55				(1 << NF_INET_LOCAL_OUT) |
 56				(1 << NF_INET_FORWARD) |
 57				(1 << NF_INET_PRE_ROUTING) |
 58				(1 << NF_INET_POST_ROUTING);
 59
 60		break;
 61	default:
 62		return -EINVAL;
 63	}
 64
 65	return nft_chain_validate_hooks(ctx->chain, hooks);
 66}
 67EXPORT_SYMBOL_GPL(nft_fib_validate);
 68
 69int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 70		 const struct nlattr * const tb[])
 71{
 72	struct nft_fib *priv = nft_expr_priv(expr);
 73	unsigned int len;
 74	int err;
 75
 76	if (!tb[NFTA_FIB_DREG] || !tb[NFTA_FIB_RESULT] || !tb[NFTA_FIB_FLAGS])
 77		return -EINVAL;
 78
 79	priv->flags = ntohl(nla_get_be32(tb[NFTA_FIB_FLAGS]));
 80
 81	if (priv->flags == 0)
 82		return -EINVAL;
 83
 84	if ((priv->flags & (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR)) ==
 85			   (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR))
 86		return -EINVAL;
 87	if ((priv->flags & (NFTA_FIB_F_IIF | NFTA_FIB_F_OIF)) ==
 88			   (NFTA_FIB_F_IIF | NFTA_FIB_F_OIF))
 89		return -EINVAL;
 90	if ((priv->flags & (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR)) == 0)
 91		return -EINVAL;
 92
 93	priv->result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT]));
 94
 95	switch (priv->result) {
 96	case NFT_FIB_RESULT_OIF:
 97		if (priv->flags & NFTA_FIB_F_OIF)
 98			return -EINVAL;
 99		len = sizeof(int);
100		break;
101	case NFT_FIB_RESULT_OIFNAME:
102		if (priv->flags & NFTA_FIB_F_OIF)
103			return -EINVAL;
104		len = IFNAMSIZ;
105		break;
106	case NFT_FIB_RESULT_ADDRTYPE:
107		len = sizeof(u32);
108		break;
109	default:
110		return -EINVAL;
111	}
112
113	err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg,
114				       NULL, NFT_DATA_VALUE, len);
115	if (err < 0)
116		return err;
117
118	return 0;
119}
120EXPORT_SYMBOL_GPL(nft_fib_init);
121
122int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr, bool reset)
123{
124	const struct nft_fib *priv = nft_expr_priv(expr);
125
126	if (nft_dump_register(skb, NFTA_FIB_DREG, priv->dreg))
127		return -1;
128
129	if (nla_put_be32(skb, NFTA_FIB_RESULT, htonl(priv->result)))
130		return -1;
131
132	if (nla_put_be32(skb, NFTA_FIB_FLAGS, htonl(priv->flags)))
133		return -1;
134
135	return 0;
136}
137EXPORT_SYMBOL_GPL(nft_fib_dump);
138
139void nft_fib_store_result(void *reg, const struct nft_fib *priv,
140			  const struct net_device *dev)
141{
142	u32 *dreg = reg;
143	int index;
144
145	switch (priv->result) {
146	case NFT_FIB_RESULT_OIF:
147		index = dev ? dev->ifindex : 0;
148		if (priv->flags & NFTA_FIB_F_PRESENT)
149			nft_reg_store8(dreg, !!index);
150		else
151			*dreg = index;
152
153		break;
154	case NFT_FIB_RESULT_OIFNAME:
155		if (priv->flags & NFTA_FIB_F_PRESENT)
156			nft_reg_store8(dreg, !!dev);
157		else
158			strscpy_pad(reg, dev ? dev->name : "", IFNAMSIZ);
159		break;
160	default:
161		WARN_ON_ONCE(1);
162		*dreg = 0;
163		break;
164	}
165}
166EXPORT_SYMBOL_GPL(nft_fib_store_result);
167
168bool nft_fib_reduce(struct nft_regs_track *track,
169		    const struct nft_expr *expr)
170{
171	const struct nft_fib *priv = nft_expr_priv(expr);
172	unsigned int len = NFT_REG32_SIZE;
173	const struct nft_fib *fib;
174
175	switch (priv->result) {
176	case NFT_FIB_RESULT_OIF:
177		break;
178	case NFT_FIB_RESULT_OIFNAME:
179		if (priv->flags & NFTA_FIB_F_PRESENT)
180			len = NFT_REG32_SIZE;
181		else
182			len = IFNAMSIZ;
183		break;
184	case NFT_FIB_RESULT_ADDRTYPE:
185	     break;
186	default:
187		WARN_ON_ONCE(1);
188		break;
189	}
190
191	if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
192		nft_reg_track_update(track, expr, priv->dreg, len);
193		return false;
194	}
195
196	fib = nft_expr_priv(track->regs[priv->dreg].selector);
197	if (priv->result != fib->result ||
198	    priv->flags != fib->flags) {
199		nft_reg_track_update(track, expr, priv->dreg, len);
200		return false;
201	}
202
203	if (!track->regs[priv->dreg].bitwise)
204		return true;
205
206	return false;
207}
208EXPORT_SYMBOL_GPL(nft_fib_reduce);
209
210MODULE_LICENSE("GPL");
211MODULE_DESCRIPTION("Query routing table from nftables");
212MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");