196518518SPatrick McHardy #ifndef _NET_NF_TABLES_H
296518518SPatrick McHardy #define _NET_NF_TABLES_H
396518518SPatrick McHardy 
496518518SPatrick McHardy #include <linux/list.h>
596518518SPatrick McHardy #include <linux/netfilter.h>
667a8fc27SPatrick McHardy #include <linux/netfilter/nfnetlink.h>
70ca743a5SPablo Neira Ayuso #include <linux/netfilter/x_tables.h>
896518518SPatrick McHardy #include <linux/netfilter/nf_tables.h>
9ce355e20SEric Dumazet #include <linux/u64_stats_sync.h>
1096518518SPatrick McHardy #include <net/netlink.h>
1196518518SPatrick McHardy 
1220a69341SPatrick McHardy #define NFT_JUMP_STACK_SIZE	16
1320a69341SPatrick McHardy 
1496518518SPatrick McHardy struct nft_pktinfo {
1596518518SPatrick McHardy 	struct sk_buff			*skb;
1696518518SPatrick McHardy 	const struct net_device		*in;
1796518518SPatrick McHardy 	const struct net_device		*out;
18c9484874SPatrick McHardy 	const struct nf_hook_ops	*ops;
1996518518SPatrick McHardy 	u8				nhoff;
2096518518SPatrick McHardy 	u8				thoff;
214566bf27SPatrick McHardy 	u8				tprot;
220ca743a5SPablo Neira Ayuso 	/* for x_tables compatibility */
230ca743a5SPablo Neira Ayuso 	struct xt_action_param		xt;
2496518518SPatrick McHardy };
2596518518SPatrick McHardy 
260ca743a5SPablo Neira Ayuso static inline void nft_set_pktinfo(struct nft_pktinfo *pkt,
270ca743a5SPablo Neira Ayuso 				   const struct nf_hook_ops *ops,
280ca743a5SPablo Neira Ayuso 				   struct sk_buff *skb,
29073bfd56SDavid S. Miller 				   const struct nf_hook_state *state)
300ca743a5SPablo Neira Ayuso {
310ca743a5SPablo Neira Ayuso 	pkt->skb = skb;
32073bfd56SDavid S. Miller 	pkt->in = pkt->xt.in = state->in;
33073bfd56SDavid S. Miller 	pkt->out = pkt->xt.out = state->out;
34c9484874SPatrick McHardy 	pkt->ops = ops;
35c9484874SPatrick McHardy 	pkt->xt.hooknum = ops->hooknum;
360ca743a5SPablo Neira Ayuso 	pkt->xt.family = ops->pf;
370ca743a5SPablo Neira Ayuso }
380ca743a5SPablo Neira Ayuso 
39a55e22e9SPatrick McHardy /**
40a55e22e9SPatrick McHardy  * 	struct nft_verdict - nf_tables verdict
41a55e22e9SPatrick McHardy  *
42a55e22e9SPatrick McHardy  * 	@code: nf_tables/netfilter verdict code
43a55e22e9SPatrick McHardy  * 	@chain: destination chain for NFT_JUMP/NFT_GOTO
44a55e22e9SPatrick McHardy  */
45a55e22e9SPatrick McHardy struct nft_verdict {
46a55e22e9SPatrick McHardy 	u32				code;
47a55e22e9SPatrick McHardy 	struct nft_chain		*chain;
48a55e22e9SPatrick McHardy };
49a55e22e9SPatrick McHardy 
5096518518SPatrick McHardy struct nft_data {
5196518518SPatrick McHardy 	union {
5296518518SPatrick McHardy 		u32			data[4];
531ca2e170SPatrick McHardy 		struct nft_verdict	verdict;
5496518518SPatrick McHardy 	};
5596518518SPatrick McHardy } __attribute__((aligned(__alignof__(u64))));
5696518518SPatrick McHardy 
57a55e22e9SPatrick McHardy /**
58a55e22e9SPatrick McHardy  *	struct nft_regs - nf_tables register set
59a55e22e9SPatrick McHardy  *
60a55e22e9SPatrick McHardy  *	@data: data registers
61a55e22e9SPatrick McHardy  *	@verdict: verdict register
62a55e22e9SPatrick McHardy  *
63a55e22e9SPatrick McHardy  *	The first four data registers alias to the verdict register.
64a55e22e9SPatrick McHardy  */
65a55e22e9SPatrick McHardy struct nft_regs {
66a55e22e9SPatrick McHardy 	union {
67a55e22e9SPatrick McHardy 		struct nft_data 	data[NFT_REG_MAX + 1];
68a55e22e9SPatrick McHardy 		struct nft_verdict	verdict;
69a55e22e9SPatrick McHardy 	};
70a55e22e9SPatrick McHardy };
71a55e22e9SPatrick McHardy 
7296518518SPatrick McHardy static inline void nft_data_copy(struct nft_data *dst,
7396518518SPatrick McHardy 				 const struct nft_data *src)
7496518518SPatrick McHardy {
7596518518SPatrick McHardy 	BUILD_BUG_ON(__alignof__(*dst) != __alignof__(u64));
7696518518SPatrick McHardy 	*(u64 *)&dst->data[0] = *(u64 *)&src->data[0];
7796518518SPatrick McHardy 	*(u64 *)&dst->data[2] = *(u64 *)&src->data[2];
7896518518SPatrick McHardy }
7996518518SPatrick McHardy 
8096518518SPatrick McHardy static inline void nft_data_debug(const struct nft_data *data)
8196518518SPatrick McHardy {
8296518518SPatrick McHardy 	pr_debug("data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n",
8396518518SPatrick McHardy 		 data->data[0], data->data[1],
8496518518SPatrick McHardy 		 data->data[2], data->data[3]);
8596518518SPatrick McHardy }
8696518518SPatrick McHardy 
8796518518SPatrick McHardy /**
8820a69341SPatrick McHardy  *	struct nft_ctx - nf_tables rule/set context
8996518518SPatrick McHardy  *
9099633ab2SPablo Neira Ayuso  *	@net: net namespace
9196518518SPatrick McHardy  * 	@afi: address family info
9296518518SPatrick McHardy  * 	@table: the table the chain is contained in
9396518518SPatrick McHardy  * 	@chain: the chain the rule is contained in
940ca743a5SPablo Neira Ayuso  *	@nla: netlink attributes
95128ad332SPablo Neira Ayuso  *	@portid: netlink portID of the original message
96128ad332SPablo Neira Ayuso  *	@seq: netlink sequence number
97128ad332SPablo Neira Ayuso  *	@report: notify via unicast netlink message
9896518518SPatrick McHardy  */
9996518518SPatrick McHardy struct nft_ctx {
10099633ab2SPablo Neira Ayuso 	struct net			*net;
1017c95f6d8SPablo Neira Ayuso 	struct nft_af_info		*afi;
1027c95f6d8SPablo Neira Ayuso 	struct nft_table		*table;
1037c95f6d8SPablo Neira Ayuso 	struct nft_chain		*chain;
1040ca743a5SPablo Neira Ayuso 	const struct nlattr * const 	*nla;
105128ad332SPablo Neira Ayuso 	u32				portid;
106128ad332SPablo Neira Ayuso 	u32				seq;
107128ad332SPablo Neira Ayuso 	bool				report;
10896518518SPatrick McHardy };
10996518518SPatrick McHardy 
11096518518SPatrick McHardy struct nft_data_desc {
11196518518SPatrick McHardy 	enum nft_data_types		type;
11296518518SPatrick McHardy 	unsigned int			len;
11396518518SPatrick McHardy };
11496518518SPatrick McHardy 
1155eccdfaaSJoe Perches int nft_data_init(const struct nft_ctx *ctx, struct nft_data *data,
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 
131d07db988SPatrick McHardy int nft_validate_register_load(enum nft_registers reg, unsigned int len);
1321ec10212SPatrick McHardy int nft_validate_register_store(const struct nft_ctx *ctx,
1331ec10212SPatrick McHardy 				enum nft_registers reg,
13496518518SPatrick McHardy 				const struct nft_data *data,
13545d9bcdaSPatrick McHardy 				enum nft_data_types type, unsigned int len);
13696518518SPatrick McHardy 
13786f1ec32SPatrick McHardy /**
13886f1ec32SPatrick McHardy  *	struct nft_userdata - user defined data associated with an object
13986f1ec32SPatrick McHardy  *
14086f1ec32SPatrick McHardy  *	@len: length of the data
14186f1ec32SPatrick McHardy  *	@data: content
14286f1ec32SPatrick McHardy  *
14386f1ec32SPatrick McHardy  *	The presence of user data is indicated in an object specific fashion,
14486f1ec32SPatrick McHardy  *	so a length of zero can't occur and the value "len" indicates data
14586f1ec32SPatrick McHardy  *	of length len + 1.
14686f1ec32SPatrick McHardy  */
14786f1ec32SPatrick McHardy struct nft_userdata {
14886f1ec32SPatrick McHardy 	u8			len;
14986f1ec32SPatrick McHardy 	unsigned char		data[0];
15086f1ec32SPatrick McHardy };
15186f1ec32SPatrick McHardy 
15296518518SPatrick McHardy /**
15320a69341SPatrick McHardy  *	struct nft_set_elem - generic representation of set elements
15420a69341SPatrick McHardy  *
15520a69341SPatrick McHardy  *	@key: element key
156fe2811ebSPatrick McHardy  *	@priv: element private data and extensions
15720a69341SPatrick McHardy  */
15820a69341SPatrick McHardy struct nft_set_elem {
15920a69341SPatrick McHardy 	struct nft_data		key;
160fe2811ebSPatrick McHardy 	void			*priv;
16120a69341SPatrick McHardy };
16220a69341SPatrick McHardy 
16320a69341SPatrick McHardy struct nft_set;
16420a69341SPatrick McHardy struct nft_set_iter {
16520a69341SPatrick McHardy 	unsigned int	count;
16620a69341SPatrick McHardy 	unsigned int	skip;
16720a69341SPatrick McHardy 	int		err;
16820a69341SPatrick McHardy 	int		(*fn)(const struct nft_ctx *ctx,
16920a69341SPatrick McHardy 			      const struct nft_set *set,
17020a69341SPatrick McHardy 			      const struct nft_set_iter *iter,
17120a69341SPatrick McHardy 			      const struct nft_set_elem *elem);
17220a69341SPatrick McHardy };
17320a69341SPatrick McHardy 
17420a69341SPatrick McHardy /**
175c50b960cSPatrick McHardy  *	struct nft_set_desc - description of set elements
176c50b960cSPatrick McHardy  *
177c50b960cSPatrick McHardy  *	@klen: key length
178c50b960cSPatrick McHardy  *	@dlen: data length
179c50b960cSPatrick McHardy  *	@size: number of set elements
180c50b960cSPatrick McHardy  */
181c50b960cSPatrick McHardy struct nft_set_desc {
182c50b960cSPatrick McHardy 	unsigned int		klen;
183c50b960cSPatrick McHardy 	unsigned int		dlen;
184c50b960cSPatrick McHardy 	unsigned int		size;
185c50b960cSPatrick McHardy };
186c50b960cSPatrick McHardy 
187c50b960cSPatrick McHardy /**
188c50b960cSPatrick McHardy  *	enum nft_set_class - performance class
189c50b960cSPatrick McHardy  *
190c50b960cSPatrick McHardy  *	@NFT_LOOKUP_O_1: constant, O(1)
191c50b960cSPatrick McHardy  *	@NFT_LOOKUP_O_LOG_N: logarithmic, O(log N)
192c50b960cSPatrick McHardy  *	@NFT_LOOKUP_O_N: linear, O(N)
193c50b960cSPatrick McHardy  */
194c50b960cSPatrick McHardy enum nft_set_class {
195c50b960cSPatrick McHardy 	NFT_SET_CLASS_O_1,
196c50b960cSPatrick McHardy 	NFT_SET_CLASS_O_LOG_N,
197c50b960cSPatrick McHardy 	NFT_SET_CLASS_O_N,
198c50b960cSPatrick McHardy };
199c50b960cSPatrick McHardy 
200c50b960cSPatrick McHardy /**
201c50b960cSPatrick McHardy  *	struct nft_set_estimate - estimation of memory and performance
202c50b960cSPatrick McHardy  *				  characteristics
203c50b960cSPatrick McHardy  *
204c50b960cSPatrick McHardy  *	@size: required memory
205c50b960cSPatrick McHardy  *	@class: lookup performance class
206c50b960cSPatrick McHardy  */
207c50b960cSPatrick McHardy struct nft_set_estimate {
208c50b960cSPatrick McHardy 	unsigned int		size;
209c50b960cSPatrick McHardy 	enum nft_set_class	class;
210c50b960cSPatrick McHardy };
211c50b960cSPatrick McHardy 
212b2832dd6SPatrick McHardy struct nft_set_ext;
21322fe54d5SPatrick McHardy struct nft_expr;
214b2832dd6SPatrick McHardy 
215c50b960cSPatrick McHardy /**
21620a69341SPatrick McHardy  *	struct nft_set_ops - nf_tables set operations
21720a69341SPatrick McHardy  *
21820a69341SPatrick McHardy  *	@lookup: look up an element within the set
21920a69341SPatrick McHardy  *	@insert: insert new element into set
220cc02e457SPatrick McHardy  *	@activate: activate new element in the next generation
221cc02e457SPatrick McHardy  *	@deactivate: deactivate element in the next generation
22220a69341SPatrick McHardy  *	@remove: remove element from set
22320a69341SPatrick McHardy  *	@walk: iterate over all set elemeennts
22420a69341SPatrick McHardy  *	@privsize: function to return size of set private data
22520a69341SPatrick McHardy  *	@init: initialize private data of new set instance
22620a69341SPatrick McHardy  *	@destroy: destroy private data of set instance
22720a69341SPatrick McHardy  *	@list: nf_tables_set_ops list node
22820a69341SPatrick McHardy  *	@owner: module reference
229fe2811ebSPatrick McHardy  *	@elemsize: element private size
23020a69341SPatrick McHardy  *	@features: features supported by the implementation
23120a69341SPatrick McHardy  */
23220a69341SPatrick McHardy struct nft_set_ops {
23320a69341SPatrick McHardy 	bool				(*lookup)(const struct nft_set *set,
2348cd8937aSPatrick McHardy 						  const u32 *key,
235b2832dd6SPatrick McHardy 						  const struct nft_set_ext **ext);
23622fe54d5SPatrick McHardy 	bool				(*update)(struct nft_set *set,
2378cd8937aSPatrick McHardy 						  const u32 *key,
23822fe54d5SPatrick McHardy 						  void *(*new)(struct nft_set *,
23922fe54d5SPatrick McHardy 							       const struct nft_expr *,
240a55e22e9SPatrick McHardy 							       struct nft_regs *),
24122fe54d5SPatrick McHardy 						  const struct nft_expr *expr,
242a55e22e9SPatrick McHardy 						  struct nft_regs *regs,
24322fe54d5SPatrick McHardy 						  const struct nft_set_ext **ext);
24422fe54d5SPatrick McHardy 
24520a69341SPatrick McHardy 	int				(*insert)(const struct nft_set *set,
24620a69341SPatrick McHardy 						  const struct nft_set_elem *elem);
247cc02e457SPatrick McHardy 	void				(*activate)(const struct nft_set *set,
248cc02e457SPatrick McHardy 						    const struct nft_set_elem *elem);
249cc02e457SPatrick McHardy 	void *				(*deactivate)(const struct nft_set *set,
250cc02e457SPatrick McHardy 						      const struct nft_set_elem *elem);
25120a69341SPatrick McHardy 	void				(*remove)(const struct nft_set *set,
25220a69341SPatrick McHardy 						  const struct nft_set_elem *elem);
25320a69341SPatrick McHardy 	void				(*walk)(const struct nft_ctx *ctx,
25420a69341SPatrick McHardy 						const struct nft_set *set,
25520a69341SPatrick McHardy 						struct nft_set_iter *iter);
25620a69341SPatrick McHardy 
25720a69341SPatrick McHardy 	unsigned int			(*privsize)(const struct nlattr * const nla[]);
258c50b960cSPatrick McHardy 	bool				(*estimate)(const struct nft_set_desc *desc,
259c50b960cSPatrick McHardy 						    u32 features,
260c50b960cSPatrick McHardy 						    struct nft_set_estimate *est);
26120a69341SPatrick McHardy 	int				(*init)(const struct nft_set *set,
262c50b960cSPatrick McHardy 						const struct nft_set_desc *desc,
26320a69341SPatrick McHardy 						const struct nlattr * const nla[]);
26420a69341SPatrick McHardy 	void				(*destroy)(const struct nft_set *set);
26520a69341SPatrick McHardy 
26620a69341SPatrick McHardy 	struct list_head		list;
26720a69341SPatrick McHardy 	struct module			*owner;
268fe2811ebSPatrick McHardy 	unsigned int			elemsize;
26920a69341SPatrick McHardy 	u32				features;
27020a69341SPatrick McHardy };
27120a69341SPatrick McHardy 
2725eccdfaaSJoe Perches int nft_register_set(struct nft_set_ops *ops);
2735eccdfaaSJoe Perches void nft_unregister_set(struct nft_set_ops *ops);
27420a69341SPatrick McHardy 
27520a69341SPatrick McHardy /**
27620a69341SPatrick McHardy  * 	struct nft_set - nf_tables set instance
27720a69341SPatrick McHardy  *
27820a69341SPatrick McHardy  *	@list: table set list node
27920a69341SPatrick McHardy  *	@bindings: list of set bindings
28020a69341SPatrick McHardy  * 	@name: name of the set
28120a69341SPatrick McHardy  * 	@ktype: key type (numeric type defined by userspace, not used in the kernel)
28220a69341SPatrick McHardy  * 	@dtype: data type (verdict or numeric type defined by userspace)
283c50b960cSPatrick McHardy  * 	@size: maximum set size
284c50b960cSPatrick McHardy  * 	@nelems: number of elements
2853dd0673aSPatrick McHardy  * 	@ndeact: number of deactivated elements queued for removal
286761da293SPatrick McHardy  * 	@timeout: default timeout value in msecs
287761da293SPatrick McHardy  * 	@gc_int: garbage collection interval in msecs
2889363dc4bSArturo Borrero  *	@policy: set parameterization (see enum nft_set_policies)
28920a69341SPatrick McHardy  * 	@ops: set ops
290cc02e457SPatrick McHardy  * 	@pnet: network namespace
29120a69341SPatrick McHardy  * 	@flags: set flags
29220a69341SPatrick McHardy  * 	@klen: key length
29320a69341SPatrick McHardy  * 	@dlen: data length
29420a69341SPatrick McHardy  * 	@data: private set data
29520a69341SPatrick McHardy  */
29620a69341SPatrick McHardy struct nft_set {
29720a69341SPatrick McHardy 	struct list_head		list;
29820a69341SPatrick McHardy 	struct list_head		bindings;
29920a69341SPatrick McHardy 	char				name[IFNAMSIZ];
30020a69341SPatrick McHardy 	u32				ktype;
30120a69341SPatrick McHardy 	u32				dtype;
302c50b960cSPatrick McHardy 	u32				size;
3033dd0673aSPatrick McHardy 	atomic_t			nelems;
3043dd0673aSPatrick McHardy 	u32				ndeact;
305761da293SPatrick McHardy 	u64				timeout;
306761da293SPatrick McHardy 	u32				gc_int;
3079363dc4bSArturo Borrero 	u16				policy;
30820a69341SPatrick McHardy 	/* runtime data below here */
30920a69341SPatrick McHardy 	const struct nft_set_ops	*ops ____cacheline_aligned;
310cc02e457SPatrick McHardy 	possible_net_t			pnet;
31120a69341SPatrick McHardy 	u16				flags;
31220a69341SPatrick McHardy 	u8				klen;
31320a69341SPatrick McHardy 	u8				dlen;
31420a69341SPatrick McHardy 	unsigned char			data[]
31520a69341SPatrick McHardy 		__attribute__((aligned(__alignof__(u64))));
31620a69341SPatrick McHardy };
31720a69341SPatrick McHardy 
31820a69341SPatrick McHardy static inline void *nft_set_priv(const struct nft_set *set)
31920a69341SPatrick McHardy {
32020a69341SPatrick McHardy 	return (void *)set->data;
32120a69341SPatrick McHardy }
32220a69341SPatrick McHardy 
3239d098292SPatrick McHardy static inline struct nft_set *nft_set_container_of(const void *priv)
3249d098292SPatrick McHardy {
3259d098292SPatrick McHardy 	return (void *)priv - offsetof(struct nft_set, data);
3269d098292SPatrick McHardy }
3279d098292SPatrick McHardy 
3285eccdfaaSJoe Perches struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
32920a69341SPatrick McHardy 				     const struct nlattr *nla);
330958bee14SPablo Neira Ayuso struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
331958bee14SPablo Neira Ayuso 					  const struct nlattr *nla);
33220a69341SPatrick McHardy 
333761da293SPatrick McHardy static inline unsigned long nft_set_gc_interval(const struct nft_set *set)
334761da293SPatrick McHardy {
335761da293SPatrick McHardy 	return set->gc_int ? msecs_to_jiffies(set->gc_int) : HZ;
336761da293SPatrick McHardy }
337761da293SPatrick McHardy 
33820a69341SPatrick McHardy /**
33920a69341SPatrick McHardy  *	struct nft_set_binding - nf_tables set binding
34020a69341SPatrick McHardy  *
34120a69341SPatrick McHardy  *	@list: set bindings list node
34220a69341SPatrick McHardy  *	@chain: chain containing the rule bound to the set
34311113e19SPatrick McHardy  *	@flags: set action flags
34420a69341SPatrick McHardy  *
34520a69341SPatrick McHardy  *	A set binding contains all information necessary for validation
34620a69341SPatrick McHardy  *	of new elements added to a bound set.
34720a69341SPatrick McHardy  */
34820a69341SPatrick McHardy struct nft_set_binding {
34920a69341SPatrick McHardy 	struct list_head		list;
35020a69341SPatrick McHardy 	const struct nft_chain		*chain;
35111113e19SPatrick McHardy 	u32				flags;
35220a69341SPatrick McHardy };
35320a69341SPatrick McHardy 
3545eccdfaaSJoe Perches int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
35520a69341SPatrick McHardy 		       struct nft_set_binding *binding);
3565eccdfaaSJoe Perches void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
35720a69341SPatrick McHardy 			  struct nft_set_binding *binding);
35820a69341SPatrick McHardy 
3593ac4c07aSPatrick McHardy /**
3603ac4c07aSPatrick McHardy  *	enum nft_set_extensions - set extension type IDs
3613ac4c07aSPatrick McHardy  *
3623ac4c07aSPatrick McHardy  *	@NFT_SET_EXT_KEY: element key
3633ac4c07aSPatrick McHardy  *	@NFT_SET_EXT_DATA: mapping data
3643ac4c07aSPatrick McHardy  *	@NFT_SET_EXT_FLAGS: element flags
365c3e1b005SPatrick McHardy  *	@NFT_SET_EXT_TIMEOUT: element timeout
366c3e1b005SPatrick McHardy  *	@NFT_SET_EXT_EXPIRATION: element expiration time
36768e942e8SPatrick McHardy  *	@NFT_SET_EXT_USERDATA: user data associated with the element
3683ac4c07aSPatrick McHardy  *	@NFT_SET_EXT_NUM: number of extension types
3693ac4c07aSPatrick McHardy  */
3703ac4c07aSPatrick McHardy enum nft_set_extensions {
3713ac4c07aSPatrick McHardy 	NFT_SET_EXT_KEY,
3723ac4c07aSPatrick McHardy 	NFT_SET_EXT_DATA,
3733ac4c07aSPatrick McHardy 	NFT_SET_EXT_FLAGS,
374c3e1b005SPatrick McHardy 	NFT_SET_EXT_TIMEOUT,
375c3e1b005SPatrick McHardy 	NFT_SET_EXT_EXPIRATION,
37668e942e8SPatrick McHardy 	NFT_SET_EXT_USERDATA,
3773ac4c07aSPatrick McHardy 	NFT_SET_EXT_NUM
3783ac4c07aSPatrick McHardy };
3793ac4c07aSPatrick McHardy 
3803ac4c07aSPatrick McHardy /**
3813ac4c07aSPatrick McHardy  *	struct nft_set_ext_type - set extension type
3823ac4c07aSPatrick McHardy  *
3833ac4c07aSPatrick McHardy  * 	@len: fixed part length of the extension
3843ac4c07aSPatrick McHardy  * 	@align: alignment requirements of the extension
3853ac4c07aSPatrick McHardy  */
3863ac4c07aSPatrick McHardy struct nft_set_ext_type {
3873ac4c07aSPatrick McHardy 	u8	len;
3883ac4c07aSPatrick McHardy 	u8	align;
3893ac4c07aSPatrick McHardy };
3903ac4c07aSPatrick McHardy 
3913ac4c07aSPatrick McHardy extern const struct nft_set_ext_type nft_set_ext_types[];
3923ac4c07aSPatrick McHardy 
3933ac4c07aSPatrick McHardy /**
3943ac4c07aSPatrick McHardy  *	struct nft_set_ext_tmpl - set extension template
3953ac4c07aSPatrick McHardy  *
3963ac4c07aSPatrick McHardy  *	@len: length of extension area
3973ac4c07aSPatrick McHardy  *	@offset: offsets of individual extension types
3983ac4c07aSPatrick McHardy  */
3993ac4c07aSPatrick McHardy struct nft_set_ext_tmpl {
4003ac4c07aSPatrick McHardy 	u16	len;
4013ac4c07aSPatrick McHardy 	u8	offset[NFT_SET_EXT_NUM];
4023ac4c07aSPatrick McHardy };
4033ac4c07aSPatrick McHardy 
4043ac4c07aSPatrick McHardy /**
4053ac4c07aSPatrick McHardy  *	struct nft_set_ext - set extensions
4063ac4c07aSPatrick McHardy  *
407cc02e457SPatrick McHardy  *	@genmask: generation mask
4083ac4c07aSPatrick McHardy  *	@offset: offsets of individual extension types
4093ac4c07aSPatrick McHardy  *	@data: beginning of extension data
4103ac4c07aSPatrick McHardy  */
4113ac4c07aSPatrick McHardy struct nft_set_ext {
412cc02e457SPatrick McHardy 	u8	genmask;
4133ac4c07aSPatrick McHardy 	u8	offset[NFT_SET_EXT_NUM];
4143ac4c07aSPatrick McHardy 	char	data[0];
4153ac4c07aSPatrick McHardy };
4163ac4c07aSPatrick McHardy 
4173ac4c07aSPatrick McHardy static inline void nft_set_ext_prepare(struct nft_set_ext_tmpl *tmpl)
4183ac4c07aSPatrick McHardy {
4193ac4c07aSPatrick McHardy 	memset(tmpl, 0, sizeof(*tmpl));
4203ac4c07aSPatrick McHardy 	tmpl->len = sizeof(struct nft_set_ext);
4213ac4c07aSPatrick McHardy }
4223ac4c07aSPatrick McHardy 
4233ac4c07aSPatrick McHardy static inline void nft_set_ext_add_length(struct nft_set_ext_tmpl *tmpl, u8 id,
4243ac4c07aSPatrick McHardy 					  unsigned int len)
4253ac4c07aSPatrick McHardy {
4263ac4c07aSPatrick McHardy 	tmpl->len	 = ALIGN(tmpl->len, nft_set_ext_types[id].align);
4273ac4c07aSPatrick McHardy 	BUG_ON(tmpl->len > U8_MAX);
4283ac4c07aSPatrick McHardy 	tmpl->offset[id] = tmpl->len;
4293ac4c07aSPatrick McHardy 	tmpl->len	+= nft_set_ext_types[id].len + len;
4303ac4c07aSPatrick McHardy }
4313ac4c07aSPatrick McHardy 
4323ac4c07aSPatrick McHardy static inline void nft_set_ext_add(struct nft_set_ext_tmpl *tmpl, u8 id)
4333ac4c07aSPatrick McHardy {
4343ac4c07aSPatrick McHardy 	nft_set_ext_add_length(tmpl, id, 0);
4353ac4c07aSPatrick McHardy }
4363ac4c07aSPatrick McHardy 
4373ac4c07aSPatrick McHardy static inline void nft_set_ext_init(struct nft_set_ext *ext,
4383ac4c07aSPatrick McHardy 				    const struct nft_set_ext_tmpl *tmpl)
4393ac4c07aSPatrick McHardy {
4403ac4c07aSPatrick McHardy 	memcpy(ext->offset, tmpl->offset, sizeof(ext->offset));
4413ac4c07aSPatrick McHardy }
4423ac4c07aSPatrick McHardy 
4433ac4c07aSPatrick McHardy static inline bool __nft_set_ext_exists(const struct nft_set_ext *ext, u8 id)
4443ac4c07aSPatrick McHardy {
4453ac4c07aSPatrick McHardy 	return !!ext->offset[id];
4463ac4c07aSPatrick McHardy }
4473ac4c07aSPatrick McHardy 
4483ac4c07aSPatrick McHardy static inline bool nft_set_ext_exists(const struct nft_set_ext *ext, u8 id)
4493ac4c07aSPatrick McHardy {
4503ac4c07aSPatrick McHardy 	return ext && __nft_set_ext_exists(ext, id);
4513ac4c07aSPatrick McHardy }
4523ac4c07aSPatrick McHardy 
4533ac4c07aSPatrick McHardy static inline void *nft_set_ext(const struct nft_set_ext *ext, u8 id)
4543ac4c07aSPatrick McHardy {
4553ac4c07aSPatrick McHardy 	return (void *)ext + ext->offset[id];
4563ac4c07aSPatrick McHardy }
4573ac4c07aSPatrick McHardy 
4583ac4c07aSPatrick McHardy static inline struct nft_data *nft_set_ext_key(const struct nft_set_ext *ext)
4593ac4c07aSPatrick McHardy {
4603ac4c07aSPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_KEY);
4613ac4c07aSPatrick McHardy }
4623ac4c07aSPatrick McHardy 
4633ac4c07aSPatrick McHardy static inline struct nft_data *nft_set_ext_data(const struct nft_set_ext *ext)
4643ac4c07aSPatrick McHardy {
4653ac4c07aSPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_DATA);
4663ac4c07aSPatrick McHardy }
4673ac4c07aSPatrick McHardy 
4683ac4c07aSPatrick McHardy static inline u8 *nft_set_ext_flags(const struct nft_set_ext *ext)
4693ac4c07aSPatrick McHardy {
4703ac4c07aSPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_FLAGS);
4713ac4c07aSPatrick McHardy }
472ef1f7df9SPatrick McHardy 
473c3e1b005SPatrick McHardy static inline u64 *nft_set_ext_timeout(const struct nft_set_ext *ext)
474c3e1b005SPatrick McHardy {
475c3e1b005SPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_TIMEOUT);
476c3e1b005SPatrick McHardy }
477c3e1b005SPatrick McHardy 
478c3e1b005SPatrick McHardy static inline unsigned long *nft_set_ext_expiration(const struct nft_set_ext *ext)
479c3e1b005SPatrick McHardy {
480c3e1b005SPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_EXPIRATION);
481c3e1b005SPatrick McHardy }
482c3e1b005SPatrick McHardy 
48368e942e8SPatrick McHardy static inline struct nft_userdata *nft_set_ext_userdata(const struct nft_set_ext *ext)
48468e942e8SPatrick McHardy {
48568e942e8SPatrick McHardy 	return nft_set_ext(ext, NFT_SET_EXT_USERDATA);
48668e942e8SPatrick McHardy }
48768e942e8SPatrick McHardy 
488c3e1b005SPatrick McHardy static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
489c3e1b005SPatrick McHardy {
490c3e1b005SPatrick McHardy 	return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) &&
491c3e1b005SPatrick McHardy 	       time_is_before_eq_jiffies(*nft_set_ext_expiration(ext));
492c3e1b005SPatrick McHardy }
493c3e1b005SPatrick McHardy 
494fe2811ebSPatrick McHardy static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
495fe2811ebSPatrick McHardy 						   void *elem)
496fe2811ebSPatrick McHardy {
497fe2811ebSPatrick McHardy 	return elem + set->ops->elemsize;
498fe2811ebSPatrick McHardy }
499fe2811ebSPatrick McHardy 
50022fe54d5SPatrick McHardy void *nft_set_elem_init(const struct nft_set *set,
50122fe54d5SPatrick McHardy 			const struct nft_set_ext_tmpl *tmpl,
50222fe54d5SPatrick McHardy 			const struct nft_data *key,
50322fe54d5SPatrick McHardy 			const struct nft_data *data,
50422fe54d5SPatrick McHardy 			u64 timeout, gfp_t gfp);
50561edafbbSPatrick McHardy void nft_set_elem_destroy(const struct nft_set *set, void *elem);
50661edafbbSPatrick McHardy 
50720a69341SPatrick McHardy /**
508cfed7e1bSPatrick McHardy  *	struct nft_set_gc_batch_head - nf_tables set garbage collection batch
509cfed7e1bSPatrick McHardy  *
510cfed7e1bSPatrick McHardy  *	@rcu: rcu head
511cfed7e1bSPatrick McHardy  *	@set: set the elements belong to
512cfed7e1bSPatrick McHardy  *	@cnt: count of elements
513cfed7e1bSPatrick McHardy  */
514cfed7e1bSPatrick McHardy struct nft_set_gc_batch_head {
515cfed7e1bSPatrick McHardy 	struct rcu_head			rcu;
516cfed7e1bSPatrick McHardy 	const struct nft_set		*set;
517cfed7e1bSPatrick McHardy 	unsigned int			cnt;
518cfed7e1bSPatrick McHardy };
519cfed7e1bSPatrick McHardy 
520cfed7e1bSPatrick McHardy #define NFT_SET_GC_BATCH_SIZE	((PAGE_SIZE -				  \
521cfed7e1bSPatrick McHardy 				  sizeof(struct nft_set_gc_batch_head)) / \
522cfed7e1bSPatrick McHardy 				 sizeof(void *))
523cfed7e1bSPatrick McHardy 
524cfed7e1bSPatrick McHardy /**
525cfed7e1bSPatrick McHardy  *	struct nft_set_gc_batch - nf_tables set garbage collection batch
526cfed7e1bSPatrick McHardy  *
527cfed7e1bSPatrick McHardy  * 	@head: GC batch head
528cfed7e1bSPatrick McHardy  * 	@elems: garbage collection elements
529cfed7e1bSPatrick McHardy  */
530cfed7e1bSPatrick McHardy struct nft_set_gc_batch {
531cfed7e1bSPatrick McHardy 	struct nft_set_gc_batch_head	head;
532cfed7e1bSPatrick McHardy 	void				*elems[NFT_SET_GC_BATCH_SIZE];
533cfed7e1bSPatrick McHardy };
534cfed7e1bSPatrick McHardy 
535cfed7e1bSPatrick McHardy struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
536cfed7e1bSPatrick McHardy 						gfp_t gfp);
537cfed7e1bSPatrick McHardy void nft_set_gc_batch_release(struct rcu_head *rcu);
538cfed7e1bSPatrick McHardy 
539cfed7e1bSPatrick McHardy static inline void nft_set_gc_batch_complete(struct nft_set_gc_batch *gcb)
540cfed7e1bSPatrick McHardy {
541cfed7e1bSPatrick McHardy 	if (gcb != NULL)
542cfed7e1bSPatrick McHardy 		call_rcu(&gcb->head.rcu, nft_set_gc_batch_release);
543cfed7e1bSPatrick McHardy }
544cfed7e1bSPatrick McHardy 
545cfed7e1bSPatrick McHardy static inline struct nft_set_gc_batch *
546cfed7e1bSPatrick McHardy nft_set_gc_batch_check(const struct nft_set *set, struct nft_set_gc_batch *gcb,
547cfed7e1bSPatrick McHardy 		       gfp_t gfp)
548cfed7e1bSPatrick McHardy {
549cfed7e1bSPatrick McHardy 	if (gcb != NULL) {
550cfed7e1bSPatrick McHardy 		if (gcb->head.cnt + 1 < ARRAY_SIZE(gcb->elems))
551cfed7e1bSPatrick McHardy 			return gcb;
552cfed7e1bSPatrick McHardy 		nft_set_gc_batch_complete(gcb);
553cfed7e1bSPatrick McHardy 	}
554cfed7e1bSPatrick McHardy 	return nft_set_gc_batch_alloc(set, gfp);
555cfed7e1bSPatrick McHardy }
556cfed7e1bSPatrick McHardy 
557cfed7e1bSPatrick McHardy static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb,
558cfed7e1bSPatrick McHardy 					void *elem)
559cfed7e1bSPatrick McHardy {
560cfed7e1bSPatrick McHardy 	gcb->elems[gcb->head.cnt++] = elem;
561cfed7e1bSPatrick McHardy }
562cfed7e1bSPatrick McHardy 
563cfed7e1bSPatrick McHardy /**
564ef1f7df9SPatrick McHardy  *	struct nft_expr_type - nf_tables expression type
56596518518SPatrick McHardy  *
566ef1f7df9SPatrick McHardy  *	@select_ops: function to select nft_expr_ops
567ef1f7df9SPatrick McHardy  *	@ops: default ops, used when no select_ops functions is present
56896518518SPatrick McHardy  *	@list: used internally
56996518518SPatrick McHardy  *	@name: Identifier
57096518518SPatrick McHardy  *	@owner: module reference
57196518518SPatrick McHardy  *	@policy: netlink attribute policy
57296518518SPatrick McHardy  *	@maxattr: highest netlink attribute number
57364d46806SPatrick McHardy  *	@family: address family for AF-specific types
574ef1f7df9SPatrick McHardy  */
575ef1f7df9SPatrick McHardy struct nft_expr_type {
5760ca743a5SPablo Neira Ayuso 	const struct nft_expr_ops	*(*select_ops)(const struct nft_ctx *,
5770ca743a5SPablo Neira Ayuso 						       const struct nlattr * const tb[]);
578ef1f7df9SPatrick McHardy 	const struct nft_expr_ops	*ops;
579ef1f7df9SPatrick McHardy 	struct list_head		list;
580ef1f7df9SPatrick McHardy 	const char			*name;
581ef1f7df9SPatrick McHardy 	struct module			*owner;
582ef1f7df9SPatrick McHardy 	const struct nla_policy		*policy;
583ef1f7df9SPatrick McHardy 	unsigned int			maxattr;
58464d46806SPatrick McHardy 	u8				family;
585ef1f7df9SPatrick McHardy };
586ef1f7df9SPatrick McHardy 
587ef1f7df9SPatrick McHardy /**
588ef1f7df9SPatrick McHardy  *	struct nft_expr_ops - nf_tables expression operations
589ef1f7df9SPatrick McHardy  *
590ef1f7df9SPatrick McHardy  *	@eval: Expression evaluation function
59196518518SPatrick McHardy  *	@size: full expression size, including private data size
592ef1f7df9SPatrick McHardy  *	@init: initialization function
593ef1f7df9SPatrick McHardy  *	@destroy: destruction function
594ef1f7df9SPatrick McHardy  *	@dump: function to dump parameters
595ef1f7df9SPatrick McHardy  *	@type: expression type
5960ca743a5SPablo Neira Ayuso  *	@validate: validate expression, called during loop detection
5970ca743a5SPablo Neira Ayuso  *	@data: extra data to attach to this expression operation
59896518518SPatrick McHardy  */
59996518518SPatrick McHardy struct nft_expr;
60096518518SPatrick McHardy struct nft_expr_ops {
60196518518SPatrick McHardy 	void				(*eval)(const struct nft_expr *expr,
602a55e22e9SPatrick McHardy 						struct nft_regs *regs,
60396518518SPatrick McHardy 						const struct nft_pktinfo *pkt);
604ef1f7df9SPatrick McHardy 	unsigned int			size;
605ef1f7df9SPatrick McHardy 
60696518518SPatrick McHardy 	int				(*init)(const struct nft_ctx *ctx,
60796518518SPatrick McHardy 						const struct nft_expr *expr,
60896518518SPatrick McHardy 						const struct nlattr * const tb[]);
60962472bceSPatrick McHardy 	void				(*destroy)(const struct nft_ctx *ctx,
61062472bceSPatrick McHardy 						   const struct nft_expr *expr);
61196518518SPatrick McHardy 	int				(*dump)(struct sk_buff *skb,
61296518518SPatrick McHardy 						const struct nft_expr *expr);
6130ca743a5SPablo Neira Ayuso 	int				(*validate)(const struct nft_ctx *ctx,
6140ca743a5SPablo Neira Ayuso 						    const struct nft_expr *expr,
6150ca743a5SPablo Neira Ayuso 						    const struct nft_data **data);
616ef1f7df9SPatrick McHardy 	const struct nft_expr_type	*type;
6170ca743a5SPablo Neira Ayuso 	void				*data;
61896518518SPatrick McHardy };
61996518518SPatrick McHardy 
620ef1f7df9SPatrick McHardy #define NFT_EXPR_MAXATTR		16
62196518518SPatrick McHardy #define NFT_EXPR_SIZE(size)		(sizeof(struct nft_expr) + \
62296518518SPatrick McHardy 					 ALIGN(size, __alignof__(struct nft_expr)))
62396518518SPatrick McHardy 
62496518518SPatrick McHardy /**
62596518518SPatrick McHardy  *	struct nft_expr - nf_tables expression
62696518518SPatrick McHardy  *
62796518518SPatrick McHardy  *	@ops: expression ops
62896518518SPatrick McHardy  *	@data: expression private data
62996518518SPatrick McHardy  */
63096518518SPatrick McHardy struct nft_expr {
63196518518SPatrick McHardy 	const struct nft_expr_ops	*ops;
63296518518SPatrick McHardy 	unsigned char			data[];
63396518518SPatrick McHardy };
63496518518SPatrick McHardy 
63596518518SPatrick McHardy static inline void *nft_expr_priv(const struct nft_expr *expr)
63696518518SPatrick McHardy {
63796518518SPatrick McHardy 	return (void *)expr->data;
63896518518SPatrick McHardy }
63996518518SPatrick McHardy 
64096518518SPatrick McHardy /**
64196518518SPatrick McHardy  *	struct nft_rule - nf_tables rule
64296518518SPatrick McHardy  *
64396518518SPatrick McHardy  *	@list: used internally
64496518518SPatrick McHardy  *	@handle: rule handle
6450628b123SPablo Neira Ayuso  *	@genmask: generation mask
64696518518SPatrick McHardy  *	@dlen: length of expression data
64786f1ec32SPatrick McHardy  *	@udata: user data is appended to the rule
64896518518SPatrick McHardy  *	@data: expression data
64996518518SPatrick McHardy  */
65096518518SPatrick McHardy struct nft_rule {
65196518518SPatrick McHardy 	struct list_head		list;
6520768b3b3SPablo Neira Ayuso 	u64				handle:42,
6530628b123SPablo Neira Ayuso 					genmask:2,
6540768b3b3SPablo Neira Ayuso 					dlen:12,
65586f1ec32SPatrick McHardy 					udata:1;
65696518518SPatrick McHardy 	unsigned char			data[]
65796518518SPatrick McHardy 		__attribute__((aligned(__alignof__(struct nft_expr))));
65896518518SPatrick McHardy };
65996518518SPatrick McHardy 
66096518518SPatrick McHardy static inline struct nft_expr *nft_expr_first(const struct nft_rule *rule)
66196518518SPatrick McHardy {
66296518518SPatrick McHardy 	return (struct nft_expr *)&rule->data[0];
66396518518SPatrick McHardy }
66496518518SPatrick McHardy 
66596518518SPatrick McHardy static inline struct nft_expr *nft_expr_next(const struct nft_expr *expr)
66696518518SPatrick McHardy {
66796518518SPatrick McHardy 	return ((void *)expr) + expr->ops->size;
66896518518SPatrick McHardy }
66996518518SPatrick McHardy 
67096518518SPatrick McHardy static inline struct nft_expr *nft_expr_last(const struct nft_rule *rule)
67196518518SPatrick McHardy {
67296518518SPatrick McHardy 	return (struct nft_expr *)&rule->data[rule->dlen];
67396518518SPatrick McHardy }
67496518518SPatrick McHardy 
67586f1ec32SPatrick McHardy static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)
6760768b3b3SPablo Neira Ayuso {
6770768b3b3SPablo Neira Ayuso 	return (void *)&rule->data[rule->dlen];
6780768b3b3SPablo Neira Ayuso }
6790768b3b3SPablo Neira Ayuso 
68096518518SPatrick McHardy /*
68196518518SPatrick McHardy  * The last pointer isn't really necessary, but the compiler isn't able to
68296518518SPatrick McHardy  * determine that the result of nft_expr_last() is always the same since it
68396518518SPatrick McHardy  * can't assume that the dlen value wasn't changed within calls in the loop.
68496518518SPatrick McHardy  */
68596518518SPatrick McHardy #define nft_rule_for_each_expr(expr, last, rule) \
68696518518SPatrick McHardy 	for ((expr) = nft_expr_first(rule), (last) = nft_expr_last(rule); \
68796518518SPatrick McHardy 	     (expr) != (last); \
68896518518SPatrick McHardy 	     (expr) = nft_expr_next(expr))
68996518518SPatrick McHardy 
69096518518SPatrick McHardy enum nft_chain_flags {
69196518518SPatrick McHardy 	NFT_BASE_CHAIN			= 0x1,
69291c7b38dSPablo Neira Ayuso 	NFT_CHAIN_INACTIVE		= 0x2,
69396518518SPatrick McHardy };
69496518518SPatrick McHardy 
69596518518SPatrick McHardy /**
69696518518SPatrick McHardy  *	struct nft_chain - nf_tables chain
69796518518SPatrick McHardy  *
69896518518SPatrick McHardy  *	@rules: list of rules in the chain
69996518518SPatrick McHardy  *	@list: used internally
700b5bc89bfSPablo Neira Ayuso  *	@table: table that this chain belongs to
70196518518SPatrick McHardy  *	@handle: chain handle
70296518518SPatrick McHardy  *	@use: number of jump references to this chain
70396518518SPatrick McHardy  *	@level: length of longest path to this chain
704a0a7379eSPablo Neira Ayuso  *	@flags: bitmask of enum nft_chain_flags
70596518518SPatrick McHardy  *	@name: name of the chain
70696518518SPatrick McHardy  */
70796518518SPatrick McHardy struct nft_chain {
70896518518SPatrick McHardy 	struct list_head		rules;
70996518518SPatrick McHardy 	struct list_head		list;
710b5bc89bfSPablo Neira Ayuso 	struct nft_table		*table;
71196518518SPatrick McHardy 	u64				handle;
712a0a7379eSPablo Neira Ayuso 	u32				use;
71396518518SPatrick McHardy 	u16				level;
714a0a7379eSPablo Neira Ayuso 	u8				flags;
71596518518SPatrick McHardy 	char				name[NFT_CHAIN_MAXNAMELEN];
71696518518SPatrick McHardy };
71796518518SPatrick McHardy 
7189370761cSPablo Neira Ayuso enum nft_chain_type {
7199370761cSPablo Neira Ayuso 	NFT_CHAIN_T_DEFAULT = 0,
7209370761cSPablo Neira Ayuso 	NFT_CHAIN_T_ROUTE,
7219370761cSPablo Neira Ayuso 	NFT_CHAIN_T_NAT,
7229370761cSPablo Neira Ayuso 	NFT_CHAIN_T_MAX
7239370761cSPablo Neira Ayuso };
7249370761cSPablo Neira Ayuso 
7251a1e1a12SPatrick McHardy /**
7261a1e1a12SPatrick McHardy  * 	struct nf_chain_type - nf_tables chain type info
7271a1e1a12SPatrick McHardy  *
7281a1e1a12SPatrick McHardy  * 	@name: name of the type
7291a1e1a12SPatrick McHardy  * 	@type: numeric identifier
7301a1e1a12SPatrick McHardy  * 	@family: address family
7311a1e1a12SPatrick McHardy  * 	@owner: module owner
7321a1e1a12SPatrick McHardy  * 	@hook_mask: mask of valid hooks
7331a1e1a12SPatrick McHardy  * 	@hooks: hookfn overrides
7341a1e1a12SPatrick McHardy  */
7351a1e1a12SPatrick McHardy struct nf_chain_type {
7361a1e1a12SPatrick McHardy 	const char			*name;
7371a1e1a12SPatrick McHardy 	enum nft_chain_type		type;
7381a1e1a12SPatrick McHardy 	int				family;
7391a1e1a12SPatrick McHardy 	struct module			*owner;
7401a1e1a12SPatrick McHardy 	unsigned int			hook_mask;
7411a1e1a12SPatrick McHardy 	nf_hookfn			*hooks[NF_MAX_HOOKS];
7421a1e1a12SPatrick McHardy };
7431a1e1a12SPatrick McHardy 
7447210e4e3SPablo Neira Ayuso int nft_chain_validate_dependency(const struct nft_chain *chain,
7457210e4e3SPablo Neira Ayuso 				  enum nft_chain_type type);
74675e8d06dSPablo Neira Ayuso int nft_chain_validate_hooks(const struct nft_chain *chain,
74775e8d06dSPablo Neira Ayuso                              unsigned int hook_flags);
7487210e4e3SPablo Neira Ayuso 
7490ca743a5SPablo Neira Ayuso struct nft_stats {
7500ca743a5SPablo Neira Ayuso 	u64			bytes;
7510ca743a5SPablo Neira Ayuso 	u64			pkts;
752ce355e20SEric Dumazet 	struct u64_stats_sync	syncp;
7530ca743a5SPablo Neira Ayuso };
7540ca743a5SPablo Neira Ayuso 
755115a60b1SPatrick McHardy #define NFT_HOOK_OPS_MAX		2
756115a60b1SPatrick McHardy 
75796518518SPatrick McHardy /**
75896518518SPatrick McHardy  *	struct nft_base_chain - nf_tables base chain
75996518518SPatrick McHardy  *
76096518518SPatrick McHardy  *	@ops: netfilter hook ops
7615ebb335dSPatrick McHardy  *	@pnet: net namespace that this chain belongs to
7629370761cSPablo Neira Ayuso  *	@type: chain type
7630ca743a5SPablo Neira Ayuso  *	@policy: default policy
7640ca743a5SPablo Neira Ayuso  *	@stats: per-cpu chain stats
76596518518SPatrick McHardy  *	@chain: the chain
76696518518SPatrick McHardy  */
76796518518SPatrick McHardy struct nft_base_chain {
768115a60b1SPatrick McHardy 	struct nf_hook_ops		ops[NFT_HOOK_OPS_MAX];
7695ebb335dSPatrick McHardy 	possible_net_t			pnet;
7702a37d755SPatrick McHardy 	const struct nf_chain_type	*type;
7710ca743a5SPablo Neira Ayuso 	u8				policy;
7720ca743a5SPablo Neira Ayuso 	struct nft_stats __percpu	*stats;
77396518518SPatrick McHardy 	struct nft_chain		chain;
77496518518SPatrick McHardy };
77596518518SPatrick McHardy 
77696518518SPatrick McHardy static inline struct nft_base_chain *nft_base_chain(const struct nft_chain *chain)
77796518518SPatrick McHardy {
77896518518SPatrick McHardy 	return container_of(chain, struct nft_base_chain, chain);
77996518518SPatrick McHardy }
78096518518SPatrick McHardy 
7813876d22dSPatrick McHardy unsigned int nft_do_chain(struct nft_pktinfo *pkt,
7820ca743a5SPablo Neira Ayuso 			  const struct nf_hook_ops *ops);
78396518518SPatrick McHardy 
78496518518SPatrick McHardy /**
78596518518SPatrick McHardy  *	struct nft_table - nf_tables table
78696518518SPatrick McHardy  *
78796518518SPatrick McHardy  *	@list: used internally
78896518518SPatrick McHardy  *	@chains: chains in the table
78996518518SPatrick McHardy  *	@sets: sets in the table
79096518518SPatrick McHardy  *	@hgenerator: handle generator state
79196518518SPatrick McHardy  *	@use: number of chain references to this table
79296518518SPatrick McHardy  *	@flags: table flag (see enum nft_table_flags)
79396518518SPatrick McHardy  *	@name: name of the table
79496518518SPatrick McHardy  */
79596518518SPatrick McHardy struct nft_table {
79696518518SPatrick McHardy 	struct list_head		list;
79796518518SPatrick McHardy 	struct list_head		chains;
79896518518SPatrick McHardy 	struct list_head		sets;
79996518518SPatrick McHardy 	u64				hgenerator;
80096518518SPatrick McHardy 	u32				use;
80196518518SPatrick McHardy 	u16				flags;
8021cae565eSPablo Neira Ayuso 	char				name[NFT_TABLE_MAXNAMELEN];
80396518518SPatrick McHardy };
80496518518SPatrick McHardy 
80596518518SPatrick McHardy /**
80696518518SPatrick McHardy  *	struct nft_af_info - nf_tables address family info
80796518518SPatrick McHardy  *
80896518518SPatrick McHardy  *	@list: used internally
80996518518SPatrick McHardy  *	@family: address family
81096518518SPatrick McHardy  *	@nhooks: number of hooks in this family
81196518518SPatrick McHardy  *	@owner: module owner
81296518518SPatrick McHardy  *	@tables: used internally
813115a60b1SPatrick McHardy  *	@nops: number of hook ops in this family
814115a60b1SPatrick McHardy  *	@hook_ops_init: initialization function for chain hook ops
81596518518SPatrick McHardy  *	@hooks: hookfn overrides for packet validation
81696518518SPatrick McHardy  */
81796518518SPatrick McHardy struct nft_af_info {
81896518518SPatrick McHardy 	struct list_head		list;
81996518518SPatrick McHardy 	int				family;
82096518518SPatrick McHardy 	unsigned int			nhooks;
82196518518SPatrick McHardy 	struct module			*owner;
82296518518SPatrick McHardy 	struct list_head		tables;
823115a60b1SPatrick McHardy 	unsigned int			nops;
824115a60b1SPatrick McHardy 	void				(*hook_ops_init)(struct nf_hook_ops *,
825115a60b1SPatrick McHardy 							 unsigned int);
82696518518SPatrick McHardy 	nf_hookfn			*hooks[NF_MAX_HOOKS];
82796518518SPatrick McHardy };
82896518518SPatrick McHardy 
8295eccdfaaSJoe Perches int nft_register_afinfo(struct net *, struct nft_af_info *);
8305eccdfaaSJoe Perches void nft_unregister_afinfo(struct nft_af_info *);
83196518518SPatrick McHardy 
8322a37d755SPatrick McHardy int nft_register_chain_type(const struct nf_chain_type *);
8332a37d755SPatrick McHardy void nft_unregister_chain_type(const struct nf_chain_type *);
83496518518SPatrick McHardy 
8355eccdfaaSJoe Perches int nft_register_expr(struct nft_expr_type *);
8365eccdfaaSJoe Perches void nft_unregister_expr(struct nft_expr_type *);
83796518518SPatrick McHardy 
83867a8fc27SPatrick McHardy #define nft_dereference(p)					\
83967a8fc27SPatrick McHardy 	nfnl_dereference(p, NFNL_SUBSYS_NFTABLES)
84067a8fc27SPatrick McHardy 
84196518518SPatrick McHardy #define MODULE_ALIAS_NFT_FAMILY(family)	\
84296518518SPatrick McHardy 	MODULE_ALIAS("nft-afinfo-" __stringify(family))
84396518518SPatrick McHardy 
8449370761cSPablo Neira Ayuso #define MODULE_ALIAS_NFT_CHAIN(family, name) \
8459370761cSPablo Neira Ayuso 	MODULE_ALIAS("nft-chain-" __stringify(family) "-" name)
84696518518SPatrick McHardy 
84764d46806SPatrick McHardy #define MODULE_ALIAS_NFT_AF_EXPR(family, name) \
84864d46806SPatrick McHardy 	MODULE_ALIAS("nft-expr-" __stringify(family) "-" name)
84964d46806SPatrick McHardy 
85096518518SPatrick McHardy #define MODULE_ALIAS_NFT_EXPR(name) \
85196518518SPatrick McHardy 	MODULE_ALIAS("nft-expr-" name)
85296518518SPatrick McHardy 
85320a69341SPatrick McHardy #define MODULE_ALIAS_NFT_SET() \
85420a69341SPatrick McHardy 	MODULE_ALIAS("nft-set")
85520a69341SPatrick McHardy 
856ea4bd995SPatrick McHardy /*
857ea4bd995SPatrick McHardy  * The gencursor defines two generations, the currently active and the
858ea4bd995SPatrick McHardy  * next one. Objects contain a bitmask of 2 bits specifying the generations
859ea4bd995SPatrick McHardy  * they're active in. A set bit means they're inactive in the generation
860ea4bd995SPatrick McHardy  * represented by that bit.
861ea4bd995SPatrick McHardy  *
862ea4bd995SPatrick McHardy  * New objects start out as inactive in the current and active in the
863ea4bd995SPatrick McHardy  * next generation. When committing the ruleset the bitmask is cleared,
864ea4bd995SPatrick McHardy  * meaning they're active in all generations. When removing an object,
865ea4bd995SPatrick McHardy  * it is set inactive in the next generation. After committing the ruleset,
866ea4bd995SPatrick McHardy  * the objects are removed.
867ea4bd995SPatrick McHardy  */
868ea4bd995SPatrick McHardy static inline unsigned int nft_gencursor_next(const struct net *net)
869ea4bd995SPatrick McHardy {
870ea4bd995SPatrick McHardy 	return net->nft.gencursor + 1 == 1 ? 1 : 0;
871ea4bd995SPatrick McHardy }
872ea4bd995SPatrick McHardy 
873ea4bd995SPatrick McHardy static inline u8 nft_genmask_next(const struct net *net)
874ea4bd995SPatrick McHardy {
875ea4bd995SPatrick McHardy 	return 1 << nft_gencursor_next(net);
876ea4bd995SPatrick McHardy }
877ea4bd995SPatrick McHardy 
878ea4bd995SPatrick McHardy static inline u8 nft_genmask_cur(const struct net *net)
879ea4bd995SPatrick McHardy {
880ea4bd995SPatrick McHardy 	/* Use ACCESS_ONCE() to prevent refetching the value for atomicity */
881ea4bd995SPatrick McHardy 	return 1 << ACCESS_ONCE(net->nft.gencursor);
882ea4bd995SPatrick McHardy }
883ea4bd995SPatrick McHardy 
88422fe54d5SPatrick McHardy #define NFT_GENMASK_ANY		((1 << 0) | (1 << 1))
88522fe54d5SPatrick McHardy 
886cc02e457SPatrick McHardy /*
887cc02e457SPatrick McHardy  * Set element transaction helpers
888cc02e457SPatrick McHardy  */
889cc02e457SPatrick McHardy 
890cc02e457SPatrick McHardy static inline bool nft_set_elem_active(const struct nft_set_ext *ext,
891cc02e457SPatrick McHardy 				       u8 genmask)
892cc02e457SPatrick McHardy {
893cc02e457SPatrick McHardy 	return !(ext->genmask & genmask);
894cc02e457SPatrick McHardy }
895cc02e457SPatrick McHardy 
896cc02e457SPatrick McHardy static inline void nft_set_elem_change_active(const struct nft_set *set,
897cc02e457SPatrick McHardy 					      struct nft_set_ext *ext)
898cc02e457SPatrick McHardy {
899cc02e457SPatrick McHardy 	ext->genmask ^= nft_genmask_next(read_pnet(&set->pnet));
900cc02e457SPatrick McHardy }
901cc02e457SPatrick McHardy 
90269086658SPatrick McHardy /*
90369086658SPatrick McHardy  * We use a free bit in the genmask field to indicate the element
90469086658SPatrick McHardy  * is busy, meaning it is currently being processed either by
90569086658SPatrick McHardy  * the netlink API or GC.
90669086658SPatrick McHardy  *
90769086658SPatrick McHardy  * Even though the genmask is only a single byte wide, this works
90869086658SPatrick McHardy  * because the extension structure if fully constant once initialized,
90969086658SPatrick McHardy  * so there are no non-atomic write accesses unless it is already
91069086658SPatrick McHardy  * marked busy.
91169086658SPatrick McHardy  */
91269086658SPatrick McHardy #define NFT_SET_ELEM_BUSY_MASK	(1 << 2)
91369086658SPatrick McHardy 
91469086658SPatrick McHardy #if defined(__LITTLE_ENDIAN_BITFIELD)
91569086658SPatrick McHardy #define NFT_SET_ELEM_BUSY_BIT	2
91669086658SPatrick McHardy #elif defined(__BIG_ENDIAN_BITFIELD)
91769086658SPatrick McHardy #define NFT_SET_ELEM_BUSY_BIT	(BITS_PER_LONG - BITS_PER_BYTE + 2)
91869086658SPatrick McHardy #else
91969086658SPatrick McHardy #error
92069086658SPatrick McHardy #endif
92169086658SPatrick McHardy 
92269086658SPatrick McHardy static inline int nft_set_elem_mark_busy(struct nft_set_ext *ext)
92369086658SPatrick McHardy {
92469086658SPatrick McHardy 	unsigned long *word = (unsigned long *)ext;
92569086658SPatrick McHardy 
92669086658SPatrick McHardy 	BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
92769086658SPatrick McHardy 	return test_and_set_bit(NFT_SET_ELEM_BUSY_BIT, word);
92869086658SPatrick McHardy }
92969086658SPatrick McHardy 
93069086658SPatrick McHardy static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
93169086658SPatrick McHardy {
93269086658SPatrick McHardy 	unsigned long *word = (unsigned long *)ext;
93369086658SPatrick McHardy 
93469086658SPatrick McHardy 	clear_bit(NFT_SET_ELEM_BUSY_BIT, word);
93569086658SPatrick McHardy }
93669086658SPatrick McHardy 
9371a1e1a12SPatrick McHardy /**
9381a1e1a12SPatrick McHardy  *	struct nft_trans - nf_tables object update in transaction
9391a1e1a12SPatrick McHardy  *
9401a1e1a12SPatrick McHardy  *	@list: used internally
9411a1e1a12SPatrick McHardy  *	@msg_type: message type
9421a1e1a12SPatrick McHardy  *	@ctx: transaction context
9431a1e1a12SPatrick McHardy  *	@data: internal information related to the transaction
9441a1e1a12SPatrick McHardy  */
9451a1e1a12SPatrick McHardy struct nft_trans {
9461a1e1a12SPatrick McHardy 	struct list_head		list;
9471a1e1a12SPatrick McHardy 	int				msg_type;
9481a1e1a12SPatrick McHardy 	struct nft_ctx			ctx;
9491a1e1a12SPatrick McHardy 	char				data[0];
9501a1e1a12SPatrick McHardy };
9511a1e1a12SPatrick McHardy 
9521a1e1a12SPatrick McHardy struct nft_trans_rule {
9531a1e1a12SPatrick McHardy 	struct nft_rule			*rule;
9541a1e1a12SPatrick McHardy };
9551a1e1a12SPatrick McHardy 
9561a1e1a12SPatrick McHardy #define nft_trans_rule(trans)	\
9571a1e1a12SPatrick McHardy 	(((struct nft_trans_rule *)trans->data)->rule)
9581a1e1a12SPatrick McHardy 
9591a1e1a12SPatrick McHardy struct nft_trans_set {
9601a1e1a12SPatrick McHardy 	struct nft_set			*set;
9611a1e1a12SPatrick McHardy 	u32				set_id;
9621a1e1a12SPatrick McHardy };
9631a1e1a12SPatrick McHardy 
9641a1e1a12SPatrick McHardy #define nft_trans_set(trans)	\
9651a1e1a12SPatrick McHardy 	(((struct nft_trans_set *)trans->data)->set)
9661a1e1a12SPatrick McHardy #define nft_trans_set_id(trans)	\
9671a1e1a12SPatrick McHardy 	(((struct nft_trans_set *)trans->data)->set_id)
9681a1e1a12SPatrick McHardy 
9691a1e1a12SPatrick McHardy struct nft_trans_chain {
9701a1e1a12SPatrick McHardy 	bool				update;
9711a1e1a12SPatrick McHardy 	char				name[NFT_CHAIN_MAXNAMELEN];
9721a1e1a12SPatrick McHardy 	struct nft_stats __percpu	*stats;
9731a1e1a12SPatrick McHardy 	u8				policy;
9741a1e1a12SPatrick McHardy };
9751a1e1a12SPatrick McHardy 
9761a1e1a12SPatrick McHardy #define nft_trans_chain_update(trans)	\
9771a1e1a12SPatrick McHardy 	(((struct nft_trans_chain *)trans->data)->update)
9781a1e1a12SPatrick McHardy #define nft_trans_chain_name(trans)	\
9791a1e1a12SPatrick McHardy 	(((struct nft_trans_chain *)trans->data)->name)
9801a1e1a12SPatrick McHardy #define nft_trans_chain_stats(trans)	\
9811a1e1a12SPatrick McHardy 	(((struct nft_trans_chain *)trans->data)->stats)
9821a1e1a12SPatrick McHardy #define nft_trans_chain_policy(trans)	\
9831a1e1a12SPatrick McHardy 	(((struct nft_trans_chain *)trans->data)->policy)
9841a1e1a12SPatrick McHardy 
9851a1e1a12SPatrick McHardy struct nft_trans_table {
9861a1e1a12SPatrick McHardy 	bool				update;
9871a1e1a12SPatrick McHardy 	bool				enable;
9881a1e1a12SPatrick McHardy };
9891a1e1a12SPatrick McHardy 
9901a1e1a12SPatrick McHardy #define nft_trans_table_update(trans)	\
9911a1e1a12SPatrick McHardy 	(((struct nft_trans_table *)trans->data)->update)
9921a1e1a12SPatrick McHardy #define nft_trans_table_enable(trans)	\
9931a1e1a12SPatrick McHardy 	(((struct nft_trans_table *)trans->data)->enable)
9941a1e1a12SPatrick McHardy 
9951a1e1a12SPatrick McHardy struct nft_trans_elem {
9961a1e1a12SPatrick McHardy 	struct nft_set			*set;
9971a1e1a12SPatrick McHardy 	struct nft_set_elem		elem;
9981a1e1a12SPatrick McHardy };
9991a1e1a12SPatrick McHardy 
10001a1e1a12SPatrick McHardy #define nft_trans_elem_set(trans)	\
10011a1e1a12SPatrick McHardy 	(((struct nft_trans_elem *)trans->data)->set)
10021a1e1a12SPatrick McHardy #define nft_trans_elem(trans)	\
10031a1e1a12SPatrick McHardy 	(((struct nft_trans_elem *)trans->data)->elem)
10041a1e1a12SPatrick McHardy 
100596518518SPatrick McHardy #endif /* _NET_NF_TABLES_H */
1006