196518518SPatrick McHardy #ifndef _NET_NF_TABLES_H
296518518SPatrick McHardy #define _NET_NF_TABLES_H
396518518SPatrick McHardy 
40b2d8a7bSPatrick McHardy #include <linux/module.h>
596518518SPatrick McHardy #include <linux/list.h>
696518518SPatrick McHardy #include <linux/netfilter.h>
767a8fc27SPatrick McHardy #include <linux/netfilter/nfnetlink.h>
80ca743a5SPablo Neira Ayuso #include <linux/netfilter/x_tables.h>
996518518SPatrick McHardy #include <linux/netfilter/nf_tables.h>
10ce355e20SEric Dumazet #include <linux/u64_stats_sync.h>
1196518518SPatrick McHardy #include <net/netlink.h>
1296518518SPatrick McHardy 
1320a69341SPatrick McHardy #define NFT_JUMP_STACK_SIZE	16
1420a69341SPatrick McHardy 
1596518518SPatrick McHardy struct nft_pktinfo {
1696518518SPatrick McHardy 	struct sk_buff			*skb;
1796518518SPatrick McHardy 	const struct net_device		*in;
1896518518SPatrick McHardy 	const struct net_device		*out;
19c9484874SPatrick McHardy 	const struct nf_hook_ops	*ops;
2096518518SPatrick McHardy 	u8				nhoff;
2196518518SPatrick McHardy 	u8				thoff;
224566bf27SPatrick McHardy 	u8				tprot;
230ca743a5SPablo Neira Ayuso 	/* for x_tables compatibility */
240ca743a5SPablo Neira Ayuso 	struct xt_action_param		xt;
2596518518SPatrick McHardy };
2696518518SPatrick McHardy 
270ca743a5SPablo Neira Ayuso static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
280ca743a5SPablo Neira Ayuso 				   const struct nf_hook_ops *ops,
290ca743a5SPablo Neira Ayuso 				   struct sk_buff *skb,
30073bfd56SDavid S. Miller 				   const struct nf_hook_state *state)
310ca743a5SPablo Neira Ayuso {
320ca743a5SPablo Neira Ayuso 	pkt->skb = skb;
33073bfd56SDavid S. Miller 	pkt->in = pkt->xt.in = state->in;
34073bfd56SDavid S. Miller 	pkt->out = pkt->xt.out = state->out;
35c9484874SPatrick McHardy 	pkt->ops = ops;
36c9484874SPatrick McHardy 	pkt->xt.hooknum = ops->hooknum;
370ca743a5SPablo Neira Ayuso 	pkt->xt.family = ops->pf;
380ca743a5SPablo Neira Ayuso }
390ca743a5SPablo Neira Ayuso 
40a55e22e9SPatrick McHardy /**
41a55e22e9SPatrick McHardy  * 	struct nft_verdict - nf_tables verdict
42a55e22e9SPatrick McHardy  *
43a55e22e9SPatrick McHardy  * 	@code: nf_tables/netfilter verdict code
44a55e22e9SPatrick McHardy  * 	@chain: destination chain for NFT_JUMP/NFT_GOTO
45a55e22e9SPatrick McHardy  */
46a55e22e9SPatrick McHardy struct nft_verdict {
47a55e22e9SPatrick McHardy 	u32				code;
48a55e22e9SPatrick McHardy 	struct nft_chain		*chain;
49a55e22e9SPatrick McHardy };
50a55e22e9SPatrick McHardy 
5196518518SPatrick McHardy struct nft_data {
5296518518SPatrick McHardy 	union {
5396518518SPatrick McHardy 		u32			data[4];
541ca2e170SPatrick McHardy 		struct nft_verdict	verdict;
5596518518SPatrick McHardy 	};
5696518518SPatrick McHardy } __attribute__((aligned(__alignof__(u64))));
5796518518SPatrick McHardy 
58a55e22e9SPatrick McHardy /**
59a55e22e9SPatrick McHardy  *	struct nft_regs - nf_tables register set
60a55e22e9SPatrick McHardy  *
61a55e22e9SPatrick McHardy  *	@data: data registers
62a55e22e9SPatrick McHardy  *	@verdict: verdict register
63a55e22e9SPatrick McHardy  *
64a55e22e9SPatrick McHardy  *	The first four data registers alias to the verdict register.
65a55e22e9SPatrick McHardy  */
66a55e22e9SPatrick McHardy struct nft_regs {
67a55e22e9SPatrick McHardy 	union {
6849499c3eSPatrick McHardy 		u32			data[20];
69a55e22e9SPatrick McHardy 		struct nft_verdict	verdict;
70a55e22e9SPatrick McHardy 	};
71a55e22e9SPatrick McHardy };
72a55e22e9SPatrick McHardy 
7349499c3eSPatrick McHardy static inline void nft_data_copy(u32 *dst, const struct nft_data *src,
7449499c3eSPatrick McHardy 				 unsigned int len)
7596518518SPatrick McHardy {
7649499c3eSPatrick McHardy 	memcpy(dst, src, len);
7796518518SPatrick McHardy }
7896518518SPatrick McHardy 
7996518518SPatrick McHardy static inline void nft_data_debug(const struct nft_data *data)
8096518518SPatrick McHardy {
8196518518SPatrick McHardy 	pr_debug("data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n",
8296518518SPatrick McHardy 		 data->data[0], data->data[1],
8396518518SPatrick McHardy 		 data->data[2], data->data[3]);
8496518518SPatrick McHardy }
8596518518SPatrick McHardy 
8696518518SPatrick McHardy /**
8720a69341SPatrick McHardy  *	struct nft_ctx - nf_tables rule/set context
8896518518SPatrick McHardy  *
8999633ab2SPablo Neira Ayuso  *	@net: net namespace
9096518518SPatrick McHardy  * 	@afi: address family info
9196518518SPatrick McHardy  * 	@table: the table the chain is contained in
9296518518SPatrick McHardy  * 	@chain: the chain the rule is contained in
930ca743a5SPablo Neira Ayuso  *	@nla: netlink attributes
94128ad332SPablo Neira Ayuso  *	@portid: netlink portID of the original message
95128ad332SPablo Neira Ayuso  *	@seq: netlink sequence number
96128ad332SPablo Neira Ayuso  *	@report: notify via unicast netlink message
9796518518SPatrick McHardy  */
9896518518SPatrick McHardy struct nft_ctx {
9999633ab2SPablo Neira Ayuso 	struct net			*net;
1007c95f6d8SPablo Neira Ayuso 	struct nft_af_info		*afi;
1017c95f6d8SPablo Neira Ayuso 	struct nft_table		*table;
1027c95f6d8SPablo Neira Ayuso 	struct nft_chain		*chain;
1030ca743a5SPablo Neira Ayuso 	const struct nlattr * const 	*nla;
104128ad332SPablo Neira Ayuso 	u32				portid;
105128ad332SPablo Neira Ayuso 	u32				seq;
106128ad332SPablo Neira Ayuso 	bool				report;
10796518518SPatrick McHardy };
10896518518SPatrick McHardy 
10996518518SPatrick McHardy struct nft_data_desc {
11096518518SPatrick McHardy 	enum nft_data_types		type;
11196518518SPatrick McHardy 	unsigned int			len;
11296518518SPatrick McHardy };
11396518518SPatrick McHardy 
114d0a11fc3SPatrick McHardy int nft_data_init(const struct nft_ctx *ctx,
115d0a11fc3SPatrick McHardy 		  struct nft_data *data, unsigned int size,
11696518518SPatrick McHardy 		  struct nft_data_desc *desc, const struct nlattr *nla);
1175eccdfaaSJoe Perches void nft_data_uninit(const struct nft_data *data, enum nft_data_types type);
1185eccdfaaSJoe Perches int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
11996518518SPatrick McHardy 		  enum nft_data_types type, unsigned int len);
12096518518SPatrick McHardy 
12196518518SPatrick McHardy static inline enum nft_data_types nft_dreg_to_type(enum nft_registers reg)
12296518518SPatrick McHardy {
12396518518SPatrick McHardy 	return reg == NFT_REG_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE;
12496518518SPatrick McHardy }
12596518518SPatrick McHardy 
12620a69341SPatrick McHardy static inline enum nft_registers nft_type_to_reg(enum nft_data_types type)
12720a69341SPatrick McHardy {
12820a69341SPatrick McHardy 	return type == NFT_DATA_VERDICT ? NFT_REG_VERDICT : NFT_REG_1;
12920a69341SPatrick McHardy }
13020a69341SPatrick McHardy 
131b1c96ed3SPatrick McHardy unsigned int nft_parse_register(const struct nlattr *attr);
132b1c96ed3SPatrick McHardy int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg);
133b1c96ed3SPatrick McHardy 
134d07db988SPatrick McHardy int nft_validate_register_load(enum nft_registers reg, unsigned int len);
1351ec10212SPatrick McHardy int nft_validate_register_store(const struct nft_ctx *ctx,
1361ec10212SPatrick McHardy 				enum nft_registers reg,
13796518518SPatrick McHardy 				const struct nft_data *data,
13845d9bcdaSPatrick McHardy 				enum nft_data_types type, unsigned int len);
13996518518SPatrick McHardy 
14086f1ec32SPatrick McHardy /**
14186f1ec32SPatrick McHardy  *	struct nft_userdata - user defined data associated with an object
14286f1ec32SPatrick McHardy  *
14386f1ec32SPatrick McHardy  *	@len: length of the data
14486f1ec32SPatrick McHardy  *	@data: content
14586f1ec32SPatrick McHardy  *
14686f1ec32SPatrick McHardy  *	The presence of user data is indicated in an object specific fashion,
14786f1ec32SPatrick McHardy  *	so a length of zero can't occur and the value "len" indicates data
14886f1ec32SPatrick McHardy  *	of length len + 1.
14986f1ec32SPatrick McHardy  */
15086f1ec32SPatrick McHardy struct nft_userdata {
15186f1ec32SPatrick McHardy 	u8			len;
15286f1ec32SPatrick McHardy 	unsigned char		data[0];
15386f1ec32SPatrick McHardy };
15486f1ec32SPatrick McHardy 
15596518518SPatrick McHardy /**
15620a69341SPatrick McHardy  *	struct nft_set_elem - generic representation of set elements
15720a69341SPatrick McHardy  *
15820a69341SPatrick McHardy  *	@key: element key
159fe2811ebSPatrick McHardy  *	@priv: element private data and extensions
16020a69341SPatrick McHardy  */
16120a69341SPatrick McHardy struct nft_set_elem {
1627d740264SPatrick McHardy 	union {
1637d740264SPatrick McHardy 		u32		buf[NFT_DATA_VALUE_MAXLEN / sizeof(u32)];
1647d740264SPatrick McHardy 		struct nft_data	val;
1657d740264SPatrick McHardy 	} key;
166fe2811ebSPatrick McHardy 	void			*priv;
16720a69341SPatrick McHardy };
16820a69341SPatrick McHardy 
16920a69341SPatrick McHardy struct nft_set;
17020a69341SPatrick McHardy struct nft_set_iter {
17120a69341SPatrick McHardy 	unsigned int	count;
17220a69341SPatrick McHardy 	unsigned int	skip;
17320a69341SPatrick McHardy 	int		err;
17420a69341SPatrick McHardy 	int		(*fn)(const struct nft_ctx *ctx,
17520a69341SPatrick McHardy 			      const struct nft_set *set,
17620a69341SPatrick McHardy 			      const struct nft_set_iter *iter,
17720a69341SPatrick McHardy 			      const struct nft_set_elem *elem);
17820a69341SPatrick McHardy };
17920a69341SPatrick McHardy 
18020a69341SPatrick McHardy /**
181c50b960cSPatrick McHardy  *	struct nft_set_desc - description of set elements
182c50b960cSPatrick McHardy  *
183c50b960cSPatrick McHardy  *	@klen: key length
184c50b960cSPatrick McHardy  *	@dlen: data length
185c50b960cSPatrick McHardy  *	@size: number of set elements
186c50b960cSPatrick McHardy  */
187c50b960cSPatrick McHardy struct nft_set_desc {
188c50b960cSPatrick McHardy 	unsigned int		klen;
189c50b960cSPatrick McHardy 	unsigned int		dlen;
190c50b960cSPatrick McHardy 	unsigned int		size;
191c50b960cSPatrick McHardy };
192c50b960cSPatrick McHardy 
193c50b960cSPatrick McHardy /**
194c50b960cSPatrick McHardy  *	enum nft_set_class - performance class
195c50b960cSPatrick McHardy  *
196c50b960cSPatrick McHardy  *	@NFT_LOOKUP_O_1: constant, O(1)
197c50b960cSPatrick McHardy  *	@NFT_LOOKUP_O_LOG_N: logarithmic, O(log N)
198c50b960cSPatrick McHardy  *	@NFT_LOOKUP_O_N: linear, O(N)
199c50b960cSPatrick McHardy  */
200c50b960cSPatrick McHardy enum nft_set_class {
201c50b960cSPatrick McHardy 	NFT_SET_CLASS_O_1,
202c50b960cSPatrick McHardy 	NFT_SET_CLASS_O_LOG_N,
203c50b960cSPatrick McHardy 	NFT_SET_CLASS_O_N,
204c50b960cSPatrick McHardy };
205c50b960cSPatrick McHardy 
206c50b960cSPatrick McHardy /**
207c50b960cSPatrick McHardy  *	struct nft_set_estimate - estimation of memory and performance
208c50b960cSPatrick McHardy  *				  characteristics
209c50b960cSPatrick McHardy  *
210c50b960cSPatrick McHardy  *	@size: required memory
211c50b960cSPatrick McHardy  *	@class: lookup performance class
212c50b960cSPatrick McHardy  */
213c50b960cSPatrick McHardy struct nft_set_estimate {
214c50b960cSPatrick McHardy 	unsigned int		size;
215c50b960cSPatrick McHardy 	enum nft_set_class	class;
216c50b960cSPatrick McHardy };
217c50b960cSPatrick McHardy 
218b2832dd6SPatrick McHardy struct nft_set_ext;
21922fe54d5SPatrick McHardy struct nft_expr;
220b2832dd6SPatrick McHardy 
221c50b960cSPatrick McHardy /**
22220a69341SPatrick McHardy  *	struct nft_set_ops - nf_tables set operations
22320a69341SPatrick McHardy  *
22420a69341SPatrick McHardy  *	@lookup: look up an element within the set
22520a69341SPatrick McHardy  *	@insert: insert new element into set
226cc02e457SPatrick McHardy  *	@activate: activate new element in the next generation
227cc02e457SPatrick McHardy  *	@deactivate: deactivate element in the next generation
22820a69341SPatrick McHardy  *	@remove: remove element from set
22920a69341SPatrick McHardy  *	@walk: iterate over all set elemeennts
23020a69341SPatrick McHardy  *	@privsize: function to return size of set private data
23120a69341SPatrick McHardy  *	@init: initialize private data of new set instance
23220a69341SPatrick McHardy  *	@destroy: destroy private data of set instance
23320a69341SPatrick McHardy  *	@list: nf_tables_set_ops list node
23420a69341SPatrick McHardy  *	@owner: module reference
235fe2811ebSPatrick McHardy  *	@elemsize: element private size
23620a69341SPatrick McHardy  *	@features: features supported by the implementation
23720a69341SPatrick McHardy  */
23820a69341SPatrick McHardy struct nft_set_ops {
23920a69341SPatrick McHardy 	bool				(*lookup)(const struct nft_set *set,
2408cd8937aSPatrick McHardy 						  const u32 *key,
241b2832dd6SPatrick McHardy 						  const struct nft_set_ext **ext);
24222fe54d5SPatrick McHardy 	bool				(*update)(struct nft_set *set,
2438cd8937aSPatrick McHardy 						  const u32 *key,
24422fe54d5SPatrick McHardy 						  void *(*new)(struct nft_set *,
24522fe54d5SPatrick McHardy 							       const struct nft_expr *,
246a55e22e9SPatrick McHardy 							       struct nft_regs *),
24722fe54d5SPatrick McHardy 						  const struct nft_expr *expr,
248a55e22e9SPatrick McHardy 						  struct nft_regs *regs,
24922fe54d5SPatrick McHardy 						  const struct nft_set_ext **ext);
25022fe54d5SPatrick McHardy 
25120a69341SPatrick McHardy 	int				(*insert)(const struct nft_set *set,
25220a69341SPatrick McHardy 						  const struct nft_set_elem *elem);
253cc02e457SPatrick McHardy 	void				(*activate)(const struct nft_set *set,
254cc02e457SPatrick McHardy 						    const struct nft_set_elem *elem);
255cc02e457SPatrick McHardy 	void *				(*deactivate)(const struct nft_set *set,
256cc02e457SPatrick McHardy 						      const struct nft_set_elem *elem);
25720a69341SPatrick McHardy 	void				(*remove)(const struct nft_set *set,
25820a69341SPatrick McHardy 						  const struct nft_set_elem *elem);
25920a69341SPatrick McHardy 	void				(*walk)(const struct nft_ctx *ctx,
26020a69341SPatrick McHardy 						const struct nft_set *set,
26120a69341SPatrick McHardy 						struct nft_set_iter *iter);
26220a69341SPatrick McHardy 
26320a69341SPatrick McHardy 	unsigned int			(*privsize)(const struct nlattr * const nla[]);
264c50b960cSPatrick McHardy 	bool				(*estimate)(const struct nft_set_desc *desc,
265c50b960cSPatrick McHardy 						    u32 features,
266c50b960cSPatrick McHardy 						    struct nft_set_estimate *est);
26720a69341SPatrick McHardy 	int				(*init)(const struct nft_set *set,
268c50b960cSPatrick McHardy 						const struct nft_set_desc *desc,
26920a69341SPatrick McHardy 						const struct nlattr * const nla[]);
27020a69341SPatrick McHardy 	void				(*destroy)(const struct nft_set *set);
27120a69341SPatrick McHardy 
27220a69341SPatrick McHardy 	struct list_head		list;
27320a69341SPatrick McHardy 	struct module			*owner;
274fe2811ebSPatrick McHardy 	unsigned int			elemsize;
27520a69341SPatrick McHardy 	u32				features;
27620a69341SPatrick McHardy };
27720a69341SPatrick McHardy 
2785eccdfaaSJoe Perches int nft_register_set(struct nft_set_ops *ops);
2795eccdfaaSJoe Perches void nft_unregister_set(struct nft_set_ops *ops);
28020a69341SPatrick McHardy 
28120a69341SPatrick McHardy /**
28220a69341SPatrick McHardy  * 	struct nft_set - nf_tables set instance
28320a69341SPatrick McHardy  *
28420a69341SPatrick McHardy  *	@list: table set list node
28520a69341SPatrick McHardy  *	@bindings: list of set bindings
28620a69341SPatrick McHardy  * 	@name: name of the set
28720a69341SPatrick McHardy  * 	@ktype: key type (numeric type defined by userspace, not used in the kernel)
28820a69341SPatrick McHardy  * 	@dtype: data type (verdict or numeric type defined by userspace)
289c50b960cSPatrick McHardy  * 	@size: maximum set size
290c50b960cSPatrick McHardy  * 	@nelems: number of elements
2913dd0673aSPatrick McHardy  * 	@ndeact: number of deactivated elements queued for removal
292761da293SPatrick McHardy  * 	@timeout: default timeout value in msecs
293761da293SPatrick McHardy  * 	@gc_int: garbage collection interval in msecs
2949363dc4bSArturo Borrero  *	@policy: set parameterization (see enum nft_set_policies)
29520a69341SPatrick McHardy  * 	@ops: set ops
296cc02e457SPatrick McHardy  * 	@pnet: network namespace
29720a69341SPatrick McHardy  * 	@flags: set flags
29820a69341SPatrick McHardy  * 	@klen: key length
29920a69341SPatrick McHardy  * 	@dlen: data length
30020a69341SPatrick McHardy  * 	@data: private set data
30120a69341SPatrick McHardy  */
30220a69341SPatrick McHardy struct nft_set {
30320a69341SPatrick McHardy 	struct list_head		list;
30420a69341SPatrick McHardy 	struct list_head		bindings;
30520a69341SPatrick McHardy 	char				name[IFNAMSIZ];
30620a69341SPatrick McHardy 	u32				ktype;
30720a69341SPatrick McHardy 	u32				dtype;
308c50b960cSPatrick McHardy 	u32				size;
3093dd0673aSPatrick McHardy 	atomic_t			nelems;
3103dd0673aSPatrick McHardy 	u32				ndeact;
311761da293SPatrick McHardy 	u64				timeout;
312761da293SPatrick McHardy 	u32				gc_int;
3139363dc4bSArturo Borrero 	u16				policy;
31420a69341SPatrick McHardy 	/* runtime data below here */
31520a69341SPatrick McHardy 	const struct nft_set_ops	*ops ____cacheline_aligned;
316cc02e457SPatrick McHardy 	possible_net_t			pnet;
31720a69341SPatrick McHardy 	u16				flags;
31820a69341SPatrick McHardy 	u8				klen;
31920a69341SPatrick McHardy 	u8				dlen;
32020a69341SPatrick McHardy 	unsigned char			data[]
32120a69341SPatrick McHardy 		__attribute__((aligned(__alignof__(u64))));
32220a69341SPatrick McHardy };
32320a69341SPatrick McHardy 
32420a69341SPatrick McHardy static inline void *nft_set_priv(const struct nft_set *set)
32520a69341SPatrick McHardy {
32620a69341SPatrick McHardy 	return (void *)set->data;
32720a69341SPatrick McHardy }
32820a69341SPatrick McHardy 
3299d098292SPatrick McHardy static inline struct nft_set *nft_set_container_of(const void *priv)
3309d098292SPatrick McHardy {
3319d098292SPatrick McHardy 	return (void *)priv - offsetof(struct nft_set, data);
3329d098292SPatrick McHardy }
3339d098292SPatrick McHardy 
3345eccdfaaSJoe Perches struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
33520a69341SPatrick McHardy 				     const struct nlattr *nla);
336958bee14SPablo Neira Ayuso struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
337958bee14SPablo Neira Ayuso 					  const struct nlattr *nla);
33820a69341SPatrick McHardy 
339761da293SPatrick McHardy static inline unsigned long nft_set_gc_interval(const struct nft_set *set)
340761da293SPatrick McHardy {
341761da293SPatrick McHardy 	return set->gc_int ? msecs_to_jiffies(set->gc_int) : HZ;
342761da293SPatrick McHardy }
343761da293SPatrick McHardy 
34420a69341SPatrick McHardy /**
34520a69341SPatrick McHardy  *	struct nft_set_binding - nf_tables set binding
34620a69341SPatrick McHardy  *
34720a69341SPatrick McHardy  *	@list: set bindings list node
34820a69341SPatrick McHardy  *	@chain: chain containing the rule bound to the set
34911113e19SPatrick McHardy  *	@flags: set action flags
35020a69341SPatrick McHardy  *
35120a69341SPatrick McHardy  *	A set binding contains all information necessary for validation
35220a69341SPatrick McHardy  *	of new elements added to a bound set.
35320a69341SPatrick McHardy  */
35420a69341SPatrick McHardy struct nft_set_binding {
35520a69341SPatrick McHardy 	struct list_head		list;
35620a69341SPatrick McHardy 	const struct nft_chain		*chain;
35711113e19SPatrick McHardy 	u32				flags;
35820a69341SPatrick McHardy };
35920a69341SPatrick McHardy 
3605eccdfaaSJoe Perches int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
36120a69341SPatrick McHardy 		       struct nft_set_binding *binding);
3625eccdfaaSJoe Perches void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
36320a69341SPatrick McHardy 			  struct nft_set_binding *binding);
36420a69341SPatrick McHardy 
3653ac4c07aSPatrick McHardy /**
3663ac4c07aSPatrick McHardy  *	enum nft_set_extensions - set extension type IDs
3673ac4c07aSPatrick McHardy  *
3683ac4c07aSPatrick McHardy  *	@NFT_SET_EXT_KEY: element key
3693ac4c07aSPatrick McHardy  *	@NFT_SET_EXT_DATA: mapping data
3703ac4c07aSPatrick McHardy  *	@NFT_SET_EXT_FLAGS: element flags
371c3e1b005SPatrick McHardy  *	@NFT_SET_EXT_TIMEOUT: element timeout
372c3e1b005SPatrick McHardy  *	@NFT_SET_EXT_EXPIRATION: element expiration time
37368e942e8SPatrick McHardy  *	@NFT_SET_EXT_USERDATA: user data associated with the element
374f25ad2e9SPatrick McHardy  *	@NFT_SET_EXT_EXPR: expression assiociated with the element
3753ac4c07aSPatrick McHardy  *	@NFT_SET_EXT_NUM: number of extension types
3763ac4c07aSPatrick McHardy  */
3773ac4c07aSPatrick McHardy enum nft_set_extensions {
3783ac4c07aSPatrick McHardy 	NFT_SET_EXT_KEY,
3793ac4c07aSPatrick McHardy 	NFT_SET_EXT_DATA,
3803ac4c07aSPatrick McHardy 	NFT_SET_EXT_FLAGS,
381c3e1b005SPatrick McHardy 	NFT_SET_EXT_TIMEOUT,
382c3e1b005SPatrick McHardy 	NFT_SET_EXT_EXPIRATION,
38368e942e8SPatrick McHardy 	NFT_SET_EXT_USERDATA,
384f25ad2e9SPatrick McHardy 	NFT_SET_EXT_EXPR,
3853ac4c07aSPatrick McHardy 	NFT_SET_EXT_NUM
3863ac4c07aSPatrick McHardy };
3873ac4c07aSPatrick McHardy 
3883ac4c07aSPatrick McHardy /**
3893ac4c07aSPatrick McHardy  *	struct nft_set_ext_type - set extension type
3903ac4c07aSPatrick McHardy  *
3913ac4c07aSPatrick McHardy  * 	@len: fixed part length of the extension
3923ac4c07aSPatrick McHardy  * 	@align: alignment requirements of the extension
3933ac4c07aSPatrick McHardy  */
3943ac4c07aSPatrick McHardy struct nft_set_ext_type {
3953ac4c07aSPatrick McHardy 	u8	len;
3963ac4c07aSPatrick McHardy 	u8	align;
3973ac4c07aSPatrick McHardy };
3983ac4c07aSPatrick McHardy 
3993ac4c07aSPatrick McHardy extern const struct nft_set_ext_type nft_set_ext_types[];
4003ac4c07aSPatrick McHardy 
4013ac4c07aSPatrick McHardy /**
4023ac4c07aSPatrick McHardy  *	struct nft_set_ext_tmpl - set extension template
4033ac4c07aSPatrick McHardy  *
4043ac4c07aSPatrick McHardy  *	@len: length of extension area
4053ac4c07aSPatrick McHardy  *	@offset: offsets of individual extension types
4063ac4c07aSPatrick McHardy  */
4073ac4c07aSPatrick McHardy struct nft_set_ext_tmpl {
4083ac4c07aSPatrick McHardy 	u16	len;
4093ac4c07aSPatrick McHardy 	u8	offset[NFT_SET_EXT_NUM];
4103ac4c07aSPatrick McHardy };
4113ac4c07aSPatrick McHardy 
4123ac4c07aSPatrick McHardy /**
4133ac4c07aSPatrick McHardy  *	struct nft_set_ext - set extensions
4143ac4c07aSPatrick McHardy  *
415cc02e457SPatrick McHardy  *	@genmask: generation mask
4163ac4c07aSPatrick McHardy  *	@offset: offsets of individual extension types
4173ac4c07aSPatrick McHardy  *	@data: beginning of extension data
4183ac4c07aSPatrick McHardy  */
4193ac4c07aSPatrick McHardy struct nft_set_ext {
420cc02e457SPatrick McHardy 	u8	genmask;
4213ac4c07aSPatrick McHardy 	u8	offset[NFT_SET_EXT_NUM];
4223ac4c07aSPatrick McHardy 	char	data[0];
4233ac4c07aSPatrick McHardy };
4243ac4c07aSPatrick McHardy 
4253ac4c07aSPatrick McHardy static inline void nft_set_ext_prepare(struct nft_set_ext_tmpl *tmpl)
4263ac4c07aSPatrick McHardy {
4273ac4c07aSPatrick McHardy 	memset(tmpl, 0, sizeof(*tmpl));
4283ac4c07aSPatrick McHardy 	tmpl->len = sizeof(struct nft_set_ext);
4293ac4c07aSPatrick McHardy }
4303ac4c07aSPatrick McHardy 
4313ac4c07aSPatrick McHardy static inline void nft_set_ext_add_length(struct nft_set_ext_tmpl *tmpl, u8 id,
4323ac4c07aSPatrick McHardy 					  unsigned int len)
4333ac4c07aSPatrick McHardy {
4343ac4c07aSPatrick McHardy 	tmpl->len	 = ALIGN(tmpl->len, nft_set_ext_types[id].align);
4353ac4c07aSPatrick McHardy 	BUG_ON(tmpl->len > U8_MAX);
4363ac4c07aSPatrick McHardy 	tmpl->offset[id] = tmpl->len;
4373ac4c07aSPatrick McHardy 	tmpl->len	+= nft_set_ext_types[id].len + len;
4383ac4c07aSPatrick McHardy }
4393ac4c07aSPatrick McHardy 
4403ac4c07aSPatrick McHardy static inline void nft_set_ext_add(struct nft_set_ext_tmpl *tmpl, u8 id)
4413ac4c07aSPatrick McHardy {
4423ac4c07aSPatrick McHardy 	nft_set_ext_add_length(tmpl, id, 0);
4433ac4c07aSPatrick McHardy }
4443ac4c07aSPatrick McHardy 
4453ac4c07aSPatrick McHardy static inline void nft_set_ext_init(struct nft_set_ext *ext,
4463ac4c07aSPatrick McHardy 				    const struct nft_set_ext_tmpl *tmpl)
4473ac4c07aSPatrick McHardy {
4483ac4c07aSPatrick McHardy 	memcpy(ext->offset, tmpl->offset, sizeof(ext->offset));
4493ac4c07aSPatrick McHardy }
4503ac4c07aSPatrick McHardy 
4513ac4c07aSPatrick McHardy static inline bool __nft_set_ext_exists(const struct nft_set_ext *ext, u8 id)
4523ac4c07aSPatrick McHardy {
4533ac4c07aSPatrick McHardy 	return !!ext->offset[id];
4543ac4c07aSPatrick McHardy }
4553ac4c07aSPatrick McHardy 
4563ac4c07aSPatrick McHardy static inline bool nft_set_ext_exists(const struct nft_set_ext *ext, u8 id)
4573ac4c07aSPatrick McHardy {
4583ac4c07aSPatrick McHardy 	return ext && __nft_set_ext_exists(ext, id);
4593ac4c07aSPatrick McHardy }
4603ac4c07aSPatrick McHardy 
4613ac4c07aSPatrick McHardy static inline void *nft_set_ext(const struct nft_set_ext *ext, u8 id)
4623ac4c07aSPatrick McHardy {
4633ac4c07aSPatrick McHardy 	return (void *)ext + ext->offset[id];
4643ac4c07aSPatrick McHardy }
4653ac4c07aSPatrick McHardy 
4663ac4c07aSPatrick McHardy static inline struct nft_data *nft_set_ext_key(const struct nft_set_ext *ext)
4673ac4c07aSPatrick McHardy {
4683ac4c07aSPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_KEY);
4693ac4c07aSPatrick McHardy }
4703ac4c07aSPatrick McHardy 
4713ac4c07aSPatrick McHardy static inline struct nft_data *nft_set_ext_data(const struct nft_set_ext *ext)
4723ac4c07aSPatrick McHardy {
4733ac4c07aSPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_DATA);
4743ac4c07aSPatrick McHardy }
4753ac4c07aSPatrick McHardy 
4763ac4c07aSPatrick McHardy static inline u8 *nft_set_ext_flags(const struct nft_set_ext *ext)
4773ac4c07aSPatrick McHardy {
4783ac4c07aSPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_FLAGS);
4793ac4c07aSPatrick McHardy }
480ef1f7df9SPatrick McHardy 
481c3e1b005SPatrick McHardy static inline u64 *nft_set_ext_timeout(const struct nft_set_ext *ext)
482c3e1b005SPatrick McHardy {
483c3e1b005SPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_TIMEOUT);
484c3e1b005SPatrick McHardy }
485c3e1b005SPatrick McHardy 
486c3e1b005SPatrick McHardy static inline unsigned long *nft_set_ext_expiration(const struct nft_set_ext *ext)
487c3e1b005SPatrick McHardy {
488c3e1b005SPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_EXPIRATION);
489c3e1b005SPatrick McHardy }
490c3e1b005SPatrick McHardy 
49168e942e8SPatrick McHardy static inline struct nft_userdata *nft_set_ext_userdata(const struct nft_set_ext *ext)
49268e942e8SPatrick McHardy {
49368e942e8SPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_USERDATA);
49468e942e8SPatrick McHardy }
49568e942e8SPatrick McHardy 
496f25ad2e9SPatrick McHardy static inline struct nft_expr *nft_set_ext_expr(const struct nft_set_ext *ext)
497f25ad2e9SPatrick McHardy {
498f25ad2e9SPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_EXPR);
499f25ad2e9SPatrick McHardy }
500f25ad2e9SPatrick McHardy 
501c3e1b005SPatrick McHardy static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
502c3e1b005SPatrick McHardy {
503c3e1b005SPatrick McHardy 	return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) &&
504c3e1b005SPatrick McHardy 	       time_is_before_eq_jiffies(*nft_set_ext_expiration(ext));
505c3e1b005SPatrick McHardy }
506c3e1b005SPatrick McHardy 
507fe2811ebSPatrick McHardy static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
508fe2811ebSPatrick McHardy 						   void *elem)
509fe2811ebSPatrick McHardy {
510fe2811ebSPatrick McHardy 	return elem + set->ops->elemsize;
511fe2811ebSPatrick McHardy }
512fe2811ebSPatrick McHardy 
51322fe54d5SPatrick McHardy void *nft_set_elem_init(const struct nft_set *set,
51422fe54d5SPatrick McHardy 			const struct nft_set_ext_tmpl *tmpl,
51549499c3eSPatrick McHardy 			const u32 *key, const u32 *data,
51622fe54d5SPatrick McHardy 			u64 timeout, gfp_t gfp);
51761edafbbSPatrick McHardy void nft_set_elem_destroy(const struct nft_set *set, void *elem);
51861edafbbSPatrick McHardy 
51920a69341SPatrick McHardy /**
520cfed7e1bSPatrick McHardy  *	struct nft_set_gc_batch_head - nf_tables set garbage collection batch
521cfed7e1bSPatrick McHardy  *
522cfed7e1bSPatrick McHardy  *	@rcu: rcu head
523cfed7e1bSPatrick McHardy  *	@set: set the elements belong to
524cfed7e1bSPatrick McHardy  *	@cnt: count of elements
525cfed7e1bSPatrick McHardy  */
526cfed7e1bSPatrick McHardy struct nft_set_gc_batch_head {
527cfed7e1bSPatrick McHardy 	struct rcu_head			rcu;
528cfed7e1bSPatrick McHardy 	const struct nft_set		*set;
529cfed7e1bSPatrick McHardy 	unsigned int			cnt;
530cfed7e1bSPatrick McHardy };
531cfed7e1bSPatrick McHardy 
532cfed7e1bSPatrick McHardy #define NFT_SET_GC_BATCH_SIZE	((PAGE_SIZE -				  \
533cfed7e1bSPatrick McHardy 				  sizeof(struct nft_set_gc_batch_head)) / \
534cfed7e1bSPatrick McHardy 				 sizeof(void *))
535cfed7e1bSPatrick McHardy 
536cfed7e1bSPatrick McHardy /**
537cfed7e1bSPatrick McHardy  *	struct nft_set_gc_batch - nf_tables set garbage collection batch
538cfed7e1bSPatrick McHardy  *
539cfed7e1bSPatrick McHardy  * 	@head: GC batch head
540cfed7e1bSPatrick McHardy  * 	@elems: garbage collection elements
541cfed7e1bSPatrick McHardy  */
542cfed7e1bSPatrick McHardy struct nft_set_gc_batch {
543cfed7e1bSPatrick McHardy 	struct nft_set_gc_batch_head	head;
544cfed7e1bSPatrick McHardy 	void				*elems[NFT_SET_GC_BATCH_SIZE];
545cfed7e1bSPatrick McHardy };
546cfed7e1bSPatrick McHardy 
547cfed7e1bSPatrick McHardy struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
548cfed7e1bSPatrick McHardy 						gfp_t gfp);
549cfed7e1bSPatrick McHardy void nft_set_gc_batch_release(struct rcu_head *rcu);
550cfed7e1bSPatrick McHardy 
551cfed7e1bSPatrick McHardy static inline void nft_set_gc_batch_complete(struct nft_set_gc_batch *gcb)
552cfed7e1bSPatrick McHardy {
553cfed7e1bSPatrick McHardy 	if (gcb != NULL)
554cfed7e1bSPatrick McHardy 		call_rcu(&gcb->head.rcu, nft_set_gc_batch_release);
555cfed7e1bSPatrick McHardy }
556cfed7e1bSPatrick McHardy 
557cfed7e1bSPatrick McHardy static inline struct nft_set_gc_batch *
558cfed7e1bSPatrick McHardy nft_set_gc_batch_check(const struct nft_set *set, struct nft_set_gc_batch *gcb,
559cfed7e1bSPatrick McHardy 		       gfp_t gfp)
560cfed7e1bSPatrick McHardy {
561cfed7e1bSPatrick McHardy 	if (gcb != NULL) {
562cfed7e1bSPatrick McHardy 		if (gcb->head.cnt + 1 < ARRAY_SIZE(gcb->elems))
563cfed7e1bSPatrick McHardy 			return gcb;
564cfed7e1bSPatrick McHardy 		nft_set_gc_batch_complete(gcb);
565cfed7e1bSPatrick McHardy 	}
566cfed7e1bSPatrick McHardy 	return nft_set_gc_batch_alloc(set, gfp);
567cfed7e1bSPatrick McHardy }
568cfed7e1bSPatrick McHardy 
569cfed7e1bSPatrick McHardy static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb,
570cfed7e1bSPatrick McHardy 					void *elem)
571cfed7e1bSPatrick McHardy {
572cfed7e1bSPatrick McHardy 	gcb->elems[gcb->head.cnt++] = elem;
573cfed7e1bSPatrick McHardy }
574cfed7e1bSPatrick McHardy 
575cfed7e1bSPatrick McHardy /**
576ef1f7df9SPatrick McHardy  *	struct nft_expr_type - nf_tables expression type
57796518518SPatrick McHardy  *
578ef1f7df9SPatrick McHardy  *	@select_ops: function to select nft_expr_ops
579ef1f7df9SPatrick McHardy  *	@ops: default ops, used when no select_ops functions is present
58096518518SPatrick McHardy  *	@list: used internally
58196518518SPatrick McHardy  *	@name: Identifier
58296518518SPatrick McHardy  *	@owner: module reference
58396518518SPatrick McHardy  *	@policy: netlink attribute policy
58496518518SPatrick McHardy  *	@maxattr: highest netlink attribute number
58564d46806SPatrick McHardy  *	@family: address family for AF-specific types
586151d799aSPatrick McHardy  *	@flags: expression type flags
587ef1f7df9SPatrick McHardy  */
588ef1f7df9SPatrick McHardy struct nft_expr_type {
5890ca743a5SPablo Neira Ayuso 	const struct nft_expr_ops	*(*select_ops)(const struct nft_ctx *,
5900ca743a5SPablo Neira Ayuso 						       const struct nlattr * const tb[]);
591ef1f7df9SPatrick McHardy 	const struct nft_expr_ops	*ops;
592ef1f7df9SPatrick McHardy 	struct list_head		list;
593ef1f7df9SPatrick McHardy 	const char			*name;
594ef1f7df9SPatrick McHardy 	struct module			*owner;
595ef1f7df9SPatrick McHardy 	const struct nla_policy		*policy;
596ef1f7df9SPatrick McHardy 	unsigned int			maxattr;
59764d46806SPatrick McHardy 	u8				family;
598151d799aSPatrick McHardy 	u8				flags;
599ef1f7df9SPatrick McHardy };
600ef1f7df9SPatrick McHardy 
601151d799aSPatrick McHardy #define NFT_EXPR_STATEFUL		0x1
602151d799aSPatrick McHardy 
603ef1f7df9SPatrick McHardy /**
604ef1f7df9SPatrick McHardy  *	struct nft_expr_ops - nf_tables expression operations
605ef1f7df9SPatrick McHardy  *
606ef1f7df9SPatrick McHardy  *	@eval: Expression evaluation function
60796518518SPatrick McHardy  *	@size: full expression size, including private data size
608ef1f7df9SPatrick McHardy  *	@init: initialization function
609ef1f7df9SPatrick McHardy  *	@destroy: destruction function
610ef1f7df9SPatrick McHardy  *	@dump: function to dump parameters
611ef1f7df9SPatrick McHardy  *	@type: expression type
6120ca743a5SPablo Neira Ayuso  *	@validate: validate expression, called during loop detection
6130ca743a5SPablo Neira Ayuso  *	@data: extra data to attach to this expression operation
61496518518SPatrick McHardy  */
61596518518SPatrick McHardy struct nft_expr;
61696518518SPatrick McHardy struct nft_expr_ops {
61796518518SPatrick McHardy 	void				(*eval)(const struct nft_expr *expr,
618a55e22e9SPatrick McHardy 						struct nft_regs *regs,
61996518518SPatrick McHardy 						const struct nft_pktinfo *pkt);
620ef1f7df9SPatrick McHardy 	unsigned int			size;
621ef1f7df9SPatrick McHardy 
62296518518SPatrick McHardy 	int				(*init)(const struct nft_ctx *ctx,
62396518518SPatrick McHardy 						const struct nft_expr *expr,
62496518518SPatrick McHardy 						const struct nlattr * const tb[]);
62562472bceSPatrick McHardy 	void				(*destroy)(const struct nft_ctx *ctx,
62662472bceSPatrick McHardy 						   const struct nft_expr *expr);
62796518518SPatrick McHardy 	int				(*dump)(struct sk_buff *skb,
62896518518SPatrick McHardy 						const struct nft_expr *expr);
6290ca743a5SPablo Neira Ayuso 	int				(*validate)(const struct nft_ctx *ctx,
6300ca743a5SPablo Neira Ayuso 						    const struct nft_expr *expr,
6310ca743a5SPablo Neira Ayuso 						    const struct nft_data **data);
632ef1f7df9SPatrick McHardy 	const struct nft_expr_type	*type;
6330ca743a5SPablo Neira Ayuso 	void				*data;
63496518518SPatrick McHardy };
63596518518SPatrick McHardy 
636ef1f7df9SPatrick McHardy #define NFT_EXPR_MAXATTR		16
63796518518SPatrick McHardy #define NFT_EXPR_SIZE(size)		(sizeof(struct nft_expr) + \
63896518518SPatrick McHardy 					 ALIGN(size, __alignof__(struct nft_expr)))
63996518518SPatrick McHardy 
64096518518SPatrick McHardy /**
64196518518SPatrick McHardy  *	struct nft_expr - nf_tables expression
64296518518SPatrick McHardy  *
64396518518SPatrick McHardy  *	@ops: expression ops
64496518518SPatrick McHardy  *	@data: expression private data
64596518518SPatrick McHardy  */
64696518518SPatrick McHardy struct nft_expr {
64796518518SPatrick McHardy 	const struct nft_expr_ops	*ops;
64896518518SPatrick McHardy 	unsigned char			data[];
64996518518SPatrick McHardy };
65096518518SPatrick McHardy 
65196518518SPatrick McHardy static inline void *nft_expr_priv(const struct nft_expr *expr)
65296518518SPatrick McHardy {
65396518518SPatrick McHardy 	return (void *)expr->data;
65496518518SPatrick McHardy }
65596518518SPatrick McHardy 
6560b2d8a7bSPatrick McHardy struct nft_expr *nft_expr_init(const struct nft_ctx *ctx,
6570b2d8a7bSPatrick McHardy 			       const struct nlattr *nla);
6580b2d8a7bSPatrick McHardy void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr);
6590b2d8a7bSPatrick McHardy int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
6600b2d8a7bSPatrick McHardy 		  const struct nft_expr *expr);
6610b2d8a7bSPatrick McHardy 
6620b2d8a7bSPatrick McHardy static inline void nft_expr_clone(struct nft_expr *dst, struct nft_expr *src)
6630b2d8a7bSPatrick McHardy {
6640b2d8a7bSPatrick McHardy 	__module_get(src->ops->type->owner);
6650b2d8a7bSPatrick McHardy 	memcpy(dst, src, src->ops->size);
6660b2d8a7bSPatrick McHardy }
6670b2d8a7bSPatrick McHardy 
66896518518SPatrick McHardy /**
66996518518SPatrick McHardy  *	struct nft_rule - nf_tables rule
67096518518SPatrick McHardy  *
67196518518SPatrick McHardy  *	@list: used internally
67296518518SPatrick McHardy  *	@handle: rule handle
6730628b123SPablo Neira Ayuso  *	@genmask: generation mask
67496518518SPatrick McHardy  *	@dlen: length of expression data
67586f1ec32SPatrick McHardy  *	@udata: user data is appended to the rule
67696518518SPatrick McHardy  *	@data: expression data
67796518518SPatrick McHardy  */
67896518518SPatrick McHardy struct nft_rule {
67996518518SPatrick McHardy 	struct list_head		list;
6800768b3b3SPablo Neira Ayuso 	u64				handle:42,
6810628b123SPablo Neira Ayuso 					genmask:2,
6820768b3b3SPablo Neira Ayuso 					dlen:12,
68386f1ec32SPatrick McHardy 					udata:1;
68496518518SPatrick McHardy 	unsigned char			data[]
68596518518SPatrick McHardy 		__attribute__((aligned(__alignof__(struct nft_expr))));
68696518518SPatrick McHardy };
68796518518SPatrick McHardy 
68896518518SPatrick McHardy static inline struct nft_expr *nft_expr_first(const struct nft_rule *rule)
68996518518SPatrick McHardy {
69096518518SPatrick McHardy 	return (struct nft_expr *)&rule->data[0];
69196518518SPatrick McHardy }
69296518518SPatrick McHardy 
69396518518SPatrick McHardy static inline struct nft_expr *nft_expr_next(const struct nft_expr *expr)
69496518518SPatrick McHardy {
69596518518SPatrick McHardy 	return ((void *)expr) + expr->ops->size;
69696518518SPatrick McHardy }
69796518518SPatrick McHardy 
69896518518SPatrick McHardy static inline struct nft_expr *nft_expr_last(const struct nft_rule *rule)
69996518518SPatrick McHardy {
70096518518SPatrick McHardy 	return (struct nft_expr *)&rule->data[rule->dlen];
70196518518SPatrick McHardy }
70296518518SPatrick McHardy 
70386f1ec32SPatrick McHardy static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
7040768b3b3SPablo Neira Ayuso {
7050768b3b3SPablo Neira Ayuso 	return (void *)&rule->data[rule->dlen];
7060768b3b3SPablo Neira Ayuso }
7070768b3b3SPablo Neira Ayuso 
70896518518SPatrick McHardy /*
70996518518SPatrick McHardy  * The last pointer isn't really necessary, but the compiler isn't able to
71096518518SPatrick McHardy  * determine that the result of nft_expr_last() is always the same since it
71196518518SPatrick McHardy  * can't assume that the dlen value wasn't changed within calls in the loop.
71296518518SPatrick McHardy  */
71396518518SPatrick McHardy #define nft_rule_for_each_expr(expr, last, rule) \
71496518518SPatrick McHardy 	for ((expr) = nft_expr_first(rule), (last) = nft_expr_last(rule); \
71596518518SPatrick McHardy 	     (expr) != (last); \
71696518518SPatrick McHardy 	     (expr) = nft_expr_next(expr))
71796518518SPatrick McHardy 
71896518518SPatrick McHardy enum nft_chain_flags {
71996518518SPatrick McHardy 	NFT_BASE_CHAIN			= 0x1,
72091c7b38dSPablo Neira Ayuso 	NFT_CHAIN_INACTIVE		= 0x2,
72196518518SPatrick McHardy };
72296518518SPatrick McHardy 
72396518518SPatrick McHardy /**
72496518518SPatrick McHardy  *	struct nft_chain - nf_tables chain
72596518518SPatrick McHardy  *
72696518518SPatrick McHardy  *	@rules: list of rules in the chain
72796518518SPatrick McHardy  *	@list: used internally
728b5bc89bfSPablo Neira Ayuso  *	@table: table that this chain belongs to
72996518518SPatrick McHardy  *	@handle: chain handle
73096518518SPatrick McHardy  *	@use: number of jump references to this chain
73196518518SPatrick McHardy  *	@level: length of longest path to this chain
732a0a7379eSPablo Neira Ayuso  *	@flags: bitmask of enum nft_chain_flags
73396518518SPatrick McHardy  *	@name: name of the chain
73496518518SPatrick McHardy  */
73596518518SPatrick McHardy struct nft_chain {
73696518518SPatrick McHardy 	struct list_head		rules;
73796518518SPatrick McHardy 	struct list_head		list;
738b5bc89bfSPablo Neira Ayuso 	struct nft_table		*table;
73996518518SPatrick McHardy 	u64				handle;
740a0a7379eSPablo Neira Ayuso 	u32				use;
74196518518SPatrick McHardy 	u16				level;
742a0a7379eSPablo Neira Ayuso 	u8				flags;
74396518518SPatrick McHardy 	char				name[NFT_CHAIN_MAXNAMELEN];
74496518518SPatrick McHardy };
74596518518SPatrick McHardy 
7469370761cSPablo Neira Ayuso enum nft_chain_type {
7479370761cSPablo Neira Ayuso 	NFT_CHAIN_T_DEFAULT = 0,
7489370761cSPablo Neira Ayuso 	NFT_CHAIN_T_ROUTE,
7499370761cSPablo Neira Ayuso 	NFT_CHAIN_T_NAT,
7509370761cSPablo Neira Ayuso 	NFT_CHAIN_T_MAX
7519370761cSPablo Neira Ayuso };
7529370761cSPablo Neira Ayuso 
7531a1e1a12SPatrick McHardy /**
7541a1e1a12SPatrick McHardy  * 	struct nf_chain_type - nf_tables chain type info
7551a1e1a12SPatrick McHardy  *
7561a1e1a12SPatrick McHardy  * 	@name: name of the type
7571a1e1a12SPatrick McHardy  * 	@type: numeric identifier
7581a1e1a12SPatrick McHardy  * 	@family: address family
7591a1e1a12SPatrick McHardy  * 	@owner: module owner
7601a1e1a12SPatrick McHardy  * 	@hook_mask: mask of valid hooks
7611a1e1a12SPatrick McHardy  * 	@hooks: hookfn overrides
7621a1e1a12SPatrick McHardy  */
7631a1e1a12SPatrick McHardy struct nf_chain_type {
7641a1e1a12SPatrick McHardy 	const char			*name;
7651a1e1a12SPatrick McHardy 	enum nft_chain_type		type;
7661a1e1a12SPatrick McHardy 	int				family;
7671a1e1a12SPatrick McHardy 	struct module			*owner;
7681a1e1a12SPatrick McHardy 	unsigned int			hook_mask;
7691a1e1a12SPatrick McHardy 	nf_hookfn			*hooks[NF_MAX_HOOKS];
7701a1e1a12SPatrick McHardy };
7711a1e1a12SPatrick McHardy 
7727210e4e3SPablo Neira Ayuso int nft_chain_validate_dependency(const struct nft_chain *chain,
7737210e4e3SPablo Neira Ayuso 				  enum nft_chain_type type);
77475e8d06dSPablo Neira Ayuso int nft_chain_validate_hooks(const struct nft_chain *chain,
77575e8d06dSPablo Neira Ayuso                              unsigned int hook_flags);
7767210e4e3SPablo Neira Ayuso 
7770ca743a5SPablo Neira Ayuso struct nft_stats {
7780ca743a5SPablo Neira Ayuso 	u64			bytes;
7790ca743a5SPablo Neira Ayuso 	u64			pkts;
780ce355e20SEric Dumazet 	struct u64_stats_sync	syncp;
7810ca743a5SPablo Neira Ayuso };
7820ca743a5SPablo Neira Ayuso 
783115a60b1SPatrick McHardy #define NFT_HOOK_OPS_MAX		2
784115a60b1SPatrick McHardy 
78596518518SPatrick McHardy /**
78696518518SPatrick McHardy  *	struct nft_base_chain - nf_tables base chain
78796518518SPatrick McHardy  *
78896518518SPatrick McHardy  *	@ops: netfilter hook ops
7895ebb335dSPatrick McHardy  *	@pnet: net namespace that this chain belongs to
7909370761cSPablo Neira Ayuso  *	@type: chain type
7910ca743a5SPablo Neira Ayuso  *	@policy: default policy
7920ca743a5SPablo Neira Ayuso  *	@stats: per-cpu chain stats
79396518518SPatrick McHardy  *	@chain: the chain
79496518518SPatrick McHardy  */
79596518518SPatrick McHardy struct nft_base_chain {
796115a60b1SPatrick McHardy 	struct nf_hook_ops		ops[NFT_HOOK_OPS_MAX];
7975ebb335dSPatrick McHardy 	possible_net_t			pnet;
7982a37d755SPatrick McHardy 	const struct nf_chain_type	*type;
7990ca743a5SPablo Neira Ayuso 	u8				policy;
8000ca743a5SPablo Neira Ayuso 	struct nft_stats __percpu	*stats;
80196518518SPatrick McHardy 	struct nft_chain		chain;
80296518518SPatrick McHardy };
80396518518SPatrick McHardy 
80496518518SPatrick McHardy static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chain)
80596518518SPatrick McHardy {
80696518518SPatrick McHardy 	return container_of(chain, struct nft_base_chain, chain);
80796518518SPatrick McHardy }
80896518518SPatrick McHardy 
8093876d22dSPatrick McHardy unsigned int nft_do_chain(struct nft_pktinfo *pkt,
8100ca743a5SPablo Neira Ayuso 			  const struct nf_hook_ops *ops);
81196518518SPatrick McHardy 
81296518518SPatrick McHardy /**
81396518518SPatrick McHardy  *	struct nft_table - nf_tables table
81496518518SPatrick McHardy  *
81596518518SPatrick McHardy  *	@list: used internally
81696518518SPatrick McHardy  *	@chains: chains in the table
81796518518SPatrick McHardy  *	@sets: sets in the table
81896518518SPatrick McHardy  *	@hgenerator: handle generator state
81996518518SPatrick McHardy  *	@use: number of chain references to this table
82096518518SPatrick McHardy  *	@flags: table flag (see enum nft_table_flags)
82196518518SPatrick McHardy  *	@name: name of the table
822ebddf1a8SPablo Neira Ayuso  *	@dev: this table is bound to this device (if any)
82396518518SPatrick McHardy  */
82496518518SPatrick McHardy struct nft_table {
82596518518SPatrick McHardy 	struct list_head		list;
82696518518SPatrick McHardy 	struct list_head		chains;
82796518518SPatrick McHardy 	struct list_head		sets;
82896518518SPatrick McHardy 	u64				hgenerator;
82996518518SPatrick McHardy 	u32				use;
83096518518SPatrick McHardy 	u16				flags;
8311cae565eSPablo Neira Ayuso 	char				name[NFT_TABLE_MAXNAMELEN];
832ebddf1a8SPablo Neira Ayuso 	struct net_device		*dev;
833ebddf1a8SPablo Neira Ayuso };
834ebddf1a8SPablo Neira Ayuso 
835ebddf1a8SPablo Neira Ayuso enum nft_af_flags {
836ebddf1a8SPablo Neira Ayuso 	NFT_AF_NEEDS_DEV	= (1 << 0),
83796518518SPatrick McHardy };
83896518518SPatrick McHardy 
83996518518SPatrick McHardy /**
84096518518SPatrick McHardy  *	struct nft_af_info - nf_tables address family info
84196518518SPatrick McHardy  *
84296518518SPatrick McHardy  *	@list: used internally
84396518518SPatrick McHardy  *	@family: address family
84496518518SPatrick McHardy  *	@nhooks: number of hooks in this family
84596518518SPatrick McHardy  *	@owner: module owner
84696518518SPatrick McHardy  *	@tables: used internally
847ebddf1a8SPablo Neira Ayuso  *	@flags: family flags
848115a60b1SPatrick McHardy  *	@nops: number of hook ops in this family
849115a60b1SPatrick McHardy  *	@hook_ops_init: initialization function for chain hook ops
85096518518SPatrick McHardy  *	@hooks: hookfn overrides for packet validation
85196518518SPatrick McHardy  */
85296518518SPatrick McHardy struct nft_af_info {
85396518518SPatrick McHardy 	struct list_head		list;
85496518518SPatrick McHardy 	int				family;
85596518518SPatrick McHardy 	unsigned int			nhooks;
85696518518SPatrick McHardy 	struct module			*owner;
85796518518SPatrick McHardy 	struct list_head		tables;
858ebddf1a8SPablo Neira Ayuso 	u32				flags;
859115a60b1SPatrick McHardy 	unsigned int			nops;
860115a60b1SPatrick McHardy 	void				(*hook_ops_init)(struct nf_hook_ops *,
861115a60b1SPatrick McHardy 							 unsigned int);
86296518518SPatrick McHardy 	nf_hookfn			*hooks[NF_MAX_HOOKS];
86396518518SPatrick McHardy };
86496518518SPatrick McHardy 
8655eccdfaaSJoe Perches int nft_register_afinfo(struct net *, struct nft_af_info *);
8665eccdfaaSJoe Perches void nft_unregister_afinfo(struct nft_af_info *);
86796518518SPatrick McHardy 
8682a37d755SPatrick McHardy int nft_register_chain_type(const struct nf_chain_type *);
8692a37d755SPatrick McHardy void nft_unregister_chain_type(const struct nf_chain_type *);
87096518518SPatrick McHardy 
8715eccdfaaSJoe Perches int nft_register_expr(struct nft_expr_type *);
8725eccdfaaSJoe Perches void nft_unregister_expr(struct nft_expr_type *);
87396518518SPatrick McHardy 
87467a8fc27SPatrick McHardy #define nft_dereference(p)					\
87567a8fc27SPatrick McHardy 	nfnl_dereference(p, NFNL_SUBSYS_NFTABLES)
87667a8fc27SPatrick McHardy 
87796518518SPatrick McHardy #define MODULE_ALIAS_NFT_FAMILY(family)	\
87896518518SPatrick McHardy 	MODULE_ALIAS("nft-afinfo-" __stringify(family))
87996518518SPatrick McHardy 
8809370761cSPablo Neira Ayuso #define MODULE_ALIAS_NFT_CHAIN(family, name) \
8819370761cSPablo Neira Ayuso 	MODULE_ALIAS("nft-chain-" __stringify(family) "-" name)
88296518518SPatrick McHardy 
88364d46806SPatrick McHardy #define MODULE_ALIAS_NFT_AF_EXPR(family, name) \
88464d46806SPatrick McHardy 	MODULE_ALIAS("nft-expr-" __stringify(family) "-" name)
88564d46806SPatrick McHardy 
88696518518SPatrick McHardy #define MODULE_ALIAS_NFT_EXPR(name) \
88796518518SPatrick McHardy 	MODULE_ALIAS("nft-expr-" name)
88896518518SPatrick McHardy 
88920a69341SPatrick McHardy #define MODULE_ALIAS_NFT_SET() \
89020a69341SPatrick McHardy 	MODULE_ALIAS("nft-set")
89120a69341SPatrick McHardy 
892ea4bd995SPatrick McHardy /*
893ea4bd995SPatrick McHardy  * The gencursor defines two generations, the currently active and the
894ea4bd995SPatrick McHardy  * next one. Objects contain a bitmask of 2 bits specifying the generations
895ea4bd995SPatrick McHardy  * they're active in. A set bit means they're inactive in the generation
896ea4bd995SPatrick McHardy  * represented by that bit.
897ea4bd995SPatrick McHardy  *
898ea4bd995SPatrick McHardy  * New objects start out as inactive in the current and active in the
899ea4bd995SPatrick McHardy  * next generation. When committing the ruleset the bitmask is cleared,
900ea4bd995SPatrick McHardy  * meaning they're active in all generations. When removing an object,
901ea4bd995SPatrick McHardy  * it is set inactive in the next generation. After committing the ruleset,
902ea4bd995SPatrick McHardy  * the objects are removed.
903ea4bd995SPatrick McHardy  */
904ea4bd995SPatrick McHardy static inline unsigned int nft_gencursor_next(const struct net *net)
905ea4bd995SPatrick McHardy {
906ea4bd995SPatrick McHardy 	return net->nft.gencursor + 1 == 1 ? 1 : 0;
907ea4bd995SPatrick McHardy }
908ea4bd995SPatrick McHardy 
909ea4bd995SPatrick McHardy static inline u8 nft_genmask_next(const struct net *net)
910ea4bd995SPatrick McHardy {
911ea4bd995SPatrick McHardy 	return 1 << nft_gencursor_next(net);
912ea4bd995SPatrick McHardy }
913ea4bd995SPatrick McHardy 
914ea4bd995SPatrick McHardy static inline u8 nft_genmask_cur(const struct net *net)
915ea4bd995SPatrick McHardy {
916ea4bd995SPatrick McHardy 	/* Use ACCESS_ONCE() to prevent refetching the value for atomicity */
917ea4bd995SPatrick McHardy 	return 1 << ACCESS_ONCE(net->nft.gencursor);
918ea4bd995SPatrick McHardy }
919ea4bd995SPatrick McHardy 
92022fe54d5SPatrick McHardy #define NFT_GENMASK_ANY		((1 << 0) | (1 << 1))
92122fe54d5SPatrick McHardy 
922cc02e457SPatrick McHardy /*
923cc02e457SPatrick McHardy  * Set element transaction helpers
924cc02e457SPatrick McHardy  */
925cc02e457SPatrick McHardy 
926cc02e457SPatrick McHardy static inline bool nft_set_elem_active(const struct nft_set_ext *ext,
927cc02e457SPatrick McHardy 				       u8 genmask)
928cc02e457SPatrick McHardy {
929cc02e457SPatrick McHardy 	return !(ext->genmask & genmask);
930cc02e457SPatrick McHardy }
931cc02e457SPatrick McHardy 
932cc02e457SPatrick McHardy static inline void nft_set_elem_change_active(const struct nft_set *set,
933cc02e457SPatrick McHardy 					      struct nft_set_ext *ext)
934cc02e457SPatrick McHardy {
935cc02e457SPatrick McHardy 	ext->genmask ^= nft_genmask_next(read_pnet(&set->pnet));
936cc02e457SPatrick McHardy }
937cc02e457SPatrick McHardy 
93869086658SPatrick McHardy /*
93969086658SPatrick McHardy  * We use a free bit in the genmask field to indicate the element
94069086658SPatrick McHardy  * is busy, meaning it is currently being processed either by
94169086658SPatrick McHardy  * the netlink API or GC.
94269086658SPatrick McHardy  *
94369086658SPatrick McHardy  * Even though the genmask is only a single byte wide, this works
94469086658SPatrick McHardy  * because the extension structure if fully constant once initialized,
94569086658SPatrick McHardy  * so there are no non-atomic write accesses unless it is already
94669086658SPatrick McHardy  * marked busy.
94769086658SPatrick McHardy  */
94869086658SPatrick McHardy #define NFT_SET_ELEM_BUSY_MASK	(1 << 2)
94969086658SPatrick McHardy 
95069086658SPatrick McHardy #if defined(__LITTLE_ENDIAN_BITFIELD)
95169086658SPatrick McHardy #define NFT_SET_ELEM_BUSY_BIT	2
95269086658SPatrick McHardy #elif defined(__BIG_ENDIAN_BITFIELD)
95369086658SPatrick McHardy #define NFT_SET_ELEM_BUSY_BIT	(BITS_PER_LONG - BITS_PER_BYTE + 2)
95469086658SPatrick McHardy #else
95569086658SPatrick McHardy #error
95669086658SPatrick McHardy #endif
95769086658SPatrick McHardy 
95869086658SPatrick McHardy static inline int nft_set_elem_mark_busy(struct nft_set_ext *ext)
95969086658SPatrick McHardy {
96069086658SPatrick McHardy 	unsigned long *word = (unsigned long *)ext;
96169086658SPatrick McHardy 
96269086658SPatrick McHardy 	BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
96369086658SPatrick McHardy 	return test_and_set_bit(NFT_SET_ELEM_BUSY_BIT, word);
96469086658SPatrick McHardy }
96569086658SPatrick McHardy 
96669086658SPatrick McHardy static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
96769086658SPatrick McHardy {
96869086658SPatrick McHardy 	unsigned long *word = (unsigned long *)ext;
96969086658SPatrick McHardy 
97069086658SPatrick McHardy 	clear_bit(NFT_SET_ELEM_BUSY_BIT, word);
97169086658SPatrick McHardy }
97269086658SPatrick McHardy 
9731a1e1a12SPatrick McHardy /**
9741a1e1a12SPatrick McHardy  *	struct nft_trans - nf_tables object update in transaction
9751a1e1a12SPatrick McHardy  *
9761a1e1a12SPatrick McHardy  *	@list: used internally
9771a1e1a12SPatrick McHardy  *	@msg_type: message type
9781a1e1a12SPatrick McHardy  *	@ctx: transaction context
9791a1e1a12SPatrick McHardy  *	@data: internal information related to the transaction
9801a1e1a12SPatrick McHardy  */
9811a1e1a12SPatrick McHardy struct nft_trans {
9821a1e1a12SPatrick McHardy 	struct list_head		list;
9831a1e1a12SPatrick McHardy 	int				msg_type;
9841a1e1a12SPatrick McHardy 	struct nft_ctx			ctx;
9851a1e1a12SPatrick McHardy 	char				data[0];
9861a1e1a12SPatrick McHardy };
9871a1e1a12SPatrick McHardy 
9881a1e1a12SPatrick McHardy struct nft_trans_rule {
9891a1e1a12SPatrick McHardy 	struct nft_rule			*rule;
9901a1e1a12SPatrick McHardy };
9911a1e1a12SPatrick McHardy 
9921a1e1a12SPatrick McHardy #define nft_trans_rule(trans)	\
9931a1e1a12SPatrick McHardy 	(((struct nft_trans_rule *)trans->data)->rule)
9941a1e1a12SPatrick McHardy 
9951a1e1a12SPatrick McHardy struct nft_trans_set {
9961a1e1a12SPatrick McHardy 	struct nft_set			*set;
9971a1e1a12SPatrick McHardy 	u32				set_id;
9981a1e1a12SPatrick McHardy };
9991a1e1a12SPatrick McHardy 
10001a1e1a12SPatrick McHardy #define nft_trans_set(trans)	\
10011a1e1a12SPatrick McHardy 	(((struct nft_trans_set *)trans->data)->set)
10021a1e1a12SPatrick McHardy #define nft_trans_set_id(trans)	\
10031a1e1a12SPatrick McHardy 	(((struct nft_trans_set *)trans->data)->set_id)
10041a1e1a12SPatrick McHardy 
10051a1e1a12SPatrick McHardy struct nft_trans_chain {
10061a1e1a12SPatrick McHardy 	bool				update;
10071a1e1a12SPatrick McHardy 	char				name[NFT_CHAIN_MAXNAMELEN];
10081a1e1a12SPatrick McHardy 	struct nft_stats __percpu	*stats;
10091a1e1a12SPatrick McHardy 	u8				policy;
10101a1e1a12SPatrick McHardy };
10111a1e1a12SPatrick McHardy 
10121a1e1a12SPatrick McHardy #define nft_trans_chain_update(trans)	\
10131a1e1a12SPatrick McHardy 	(((struct nft_trans_chain *)trans->data)->update)
10141a1e1a12SPatrick McHardy #define nft_trans_chain_name(trans)	\
10151a1e1a12SPatrick McHardy 	(((struct nft_trans_chain *)trans->data)->name)
10161a1e1a12SPatrick McHardy #define nft_trans_chain_stats(trans)	\
10171a1e1a12SPatrick McHardy 	(((struct nft_trans_chain *)trans->data)->stats)
10181a1e1a12SPatrick McHardy #define nft_trans_chain_policy(trans)	\
10191a1e1a12SPatrick McHardy 	(((struct nft_trans_chain *)trans->data)->policy)
10201a1e1a12SPatrick McHardy 
10211a1e1a12SPatrick McHardy struct nft_trans_table {
10221a1e1a12SPatrick McHardy 	bool				update;
10231a1e1a12SPatrick McHardy 	bool				enable;
10241a1e1a12SPatrick McHardy };
10251a1e1a12SPatrick McHardy 
10261a1e1a12SPatrick McHardy #define nft_trans_table_update(trans)	\
10271a1e1a12SPatrick McHardy 	(((struct nft_trans_table *)trans->data)->update)
10281a1e1a12SPatrick McHardy #define nft_trans_table_enable(trans)	\
10291a1e1a12SPatrick McHardy 	(((struct nft_trans_table *)trans->data)->enable)
10301a1e1a12SPatrick McHardy 
10311a1e1a12SPatrick McHardy struct nft_trans_elem {
10321a1e1a12SPatrick McHardy 	struct nft_set			*set;
10331a1e1a12SPatrick McHardy 	struct nft_set_elem		elem;
10341a1e1a12SPatrick McHardy };
10351a1e1a12SPatrick McHardy 
10361a1e1a12SPatrick McHardy #define nft_trans_elem_set(trans)	\
10371a1e1a12SPatrick McHardy 	(((struct nft_trans_elem *)trans->data)->set)
10381a1e1a12SPatrick McHardy #define nft_trans_elem(trans)	\
10391a1e1a12SPatrick McHardy 	(((struct nft_trans_elem *)trans->data)->elem)
10401a1e1a12SPatrick McHardy 
104196518518SPatrick McHardy #endif /* _NET_NF_TABLES_H */
1042