]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - net/netfilter/nf_tables_api.c
netfilter: nftables: counter hardware offload support
[mirror_ubuntu-jammy-kernel.git] / net / netfilter / nf_tables_api.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
96518518 2/*
20a69341 3 * Copyright (c) 2007-2009 Patrick McHardy <kaber@trash.net>
96518518 4 *
96518518
PM
5 * Development of this code funded by Astaro AG (http://www.astaro.com/)
6 */
7
8#include <linux/module.h>
9#include <linux/init.h>
10#include <linux/list.h>
11#include <linux/skbuff.h>
12#include <linux/netlink.h>
1ff75a3e 13#include <linux/vmalloc.h>
0eb71a9d 14#include <linux/rhashtable.h>
8e6cf365 15#include <linux/audit.h>
96518518
PM
16#include <linux/netfilter.h>
17#include <linux/netfilter/nfnetlink.h>
18#include <linux/netfilter/nf_tables.h>
3b49e2e9 19#include <net/netfilter/nf_flow_table.h>
96518518
PM
20#include <net/netfilter/nf_tables_core.h>
21#include <net/netfilter/nf_tables.h>
c9626a2c 22#include <net/netfilter/nf_tables_offload.h>
99633ab2 23#include <net/net_namespace.h>
0854db2a 24#include <net/netns/generic.h>
96518518
PM
25#include <net/sock.h>
26
9332d27d
FW
27#define NFT_MODULE_AUTOLOAD_LIMIT (MODULE_NAME_LEN - sizeof("nft-expr-255-"))
28
0854db2a
FW
29unsigned int nf_tables_net_id __read_mostly;
30
96518518 31static LIST_HEAD(nf_tables_expressions);
e5009240 32static LIST_HEAD(nf_tables_objects);
3b49e2e9 33static LIST_HEAD(nf_tables_flowtables);
0935d558
FW
34static LIST_HEAD(nf_tables_destroy_list);
35static DEFINE_SPINLOCK(nf_tables_destroy_list_lock);
3ecbfd65 36static u64 table_handle;
96518518 37
a654de8f
PNA
38enum {
39 NFT_VALIDATE_SKIP = 0,
40 NFT_VALIDATE_NEED,
41 NFT_VALIDATE_DO,
42};
43
4d44175a
FW
44static struct rhltable nft_objname_ht;
45
1b2470e5
FW
46static u32 nft_chain_hash(const void *data, u32 len, u32 seed);
47static u32 nft_chain_hash_obj(const void *data, u32 len, u32 seed);
48static int nft_chain_hash_cmp(struct rhashtable_compare_arg *, const void *);
49
4d44175a
FW
50static u32 nft_objname_hash(const void *data, u32 len, u32 seed);
51static u32 nft_objname_hash_obj(const void *data, u32 len, u32 seed);
52static int nft_objname_hash_cmp(struct rhashtable_compare_arg *, const void *);
53
1b2470e5
FW
54static const struct rhashtable_params nft_chain_ht_params = {
55 .head_offset = offsetof(struct nft_chain, rhlhead),
56 .key_offset = offsetof(struct nft_chain, name),
57 .hashfn = nft_chain_hash,
58 .obj_hashfn = nft_chain_hash_obj,
59 .obj_cmpfn = nft_chain_hash_cmp,
1b2470e5
FW
60 .automatic_shrinking = true,
61};
62
4d44175a
FW
63static const struct rhashtable_params nft_objname_ht_params = {
64 .head_offset = offsetof(struct nft_object, rhlhead),
65 .key_offset = offsetof(struct nft_object, key),
66 .hashfn = nft_objname_hash,
67 .obj_hashfn = nft_objname_hash_obj,
68 .obj_cmpfn = nft_objname_hash_cmp,
69 .automatic_shrinking = true,
70};
71
c520292f
RGB
72struct nft_audit_data {
73 struct nft_table *table;
74 int entries;
75 int op;
76 struct list_head list;
77};
78
79static const u8 nft2audit_op[NFT_MSG_MAX] = { // enum nf_tables_msg_types
80 [NFT_MSG_NEWTABLE] = AUDIT_NFT_OP_TABLE_REGISTER,
81 [NFT_MSG_GETTABLE] = AUDIT_NFT_OP_INVALID,
82 [NFT_MSG_DELTABLE] = AUDIT_NFT_OP_TABLE_UNREGISTER,
83 [NFT_MSG_NEWCHAIN] = AUDIT_NFT_OP_CHAIN_REGISTER,
84 [NFT_MSG_GETCHAIN] = AUDIT_NFT_OP_INVALID,
85 [NFT_MSG_DELCHAIN] = AUDIT_NFT_OP_CHAIN_UNREGISTER,
86 [NFT_MSG_NEWRULE] = AUDIT_NFT_OP_RULE_REGISTER,
87 [NFT_MSG_GETRULE] = AUDIT_NFT_OP_INVALID,
88 [NFT_MSG_DELRULE] = AUDIT_NFT_OP_RULE_UNREGISTER,
89 [NFT_MSG_NEWSET] = AUDIT_NFT_OP_SET_REGISTER,
90 [NFT_MSG_GETSET] = AUDIT_NFT_OP_INVALID,
91 [NFT_MSG_DELSET] = AUDIT_NFT_OP_SET_UNREGISTER,
92 [NFT_MSG_NEWSETELEM] = AUDIT_NFT_OP_SETELEM_REGISTER,
93 [NFT_MSG_GETSETELEM] = AUDIT_NFT_OP_INVALID,
94 [NFT_MSG_DELSETELEM] = AUDIT_NFT_OP_SETELEM_UNREGISTER,
95 [NFT_MSG_NEWGEN] = AUDIT_NFT_OP_GEN_REGISTER,
96 [NFT_MSG_GETGEN] = AUDIT_NFT_OP_INVALID,
97 [NFT_MSG_TRACE] = AUDIT_NFT_OP_INVALID,
98 [NFT_MSG_NEWOBJ] = AUDIT_NFT_OP_OBJ_REGISTER,
99 [NFT_MSG_GETOBJ] = AUDIT_NFT_OP_INVALID,
100 [NFT_MSG_DELOBJ] = AUDIT_NFT_OP_OBJ_UNREGISTER,
101 [NFT_MSG_GETOBJ_RESET] = AUDIT_NFT_OP_OBJ_RESET,
102 [NFT_MSG_NEWFLOWTABLE] = AUDIT_NFT_OP_FLOWTABLE_REGISTER,
103 [NFT_MSG_GETFLOWTABLE] = AUDIT_NFT_OP_INVALID,
104 [NFT_MSG_DELFLOWTABLE] = AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
105};
106
a654de8f
PNA
107static void nft_validate_state_update(struct net *net, u8 new_validate_state)
108{
0854db2a
FW
109 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
110
111 switch (nft_net->validate_state) {
a654de8f
PNA
112 case NFT_VALIDATE_SKIP:
113 WARN_ON_ONCE(new_validate_state == NFT_VALIDATE_DO);
114 break;
115 case NFT_VALIDATE_NEED:
116 break;
117 case NFT_VALIDATE_DO:
118 if (new_validate_state == NFT_VALIDATE_NEED)
119 return;
120 }
121
0854db2a 122 nft_net->validate_state = new_validate_state;
a654de8f 123}
0935d558
FW
124static void nf_tables_trans_destroy_work(struct work_struct *w);
125static DECLARE_WORK(trans_destroy_work, nf_tables_trans_destroy_work);
a654de8f 126
7c95f6d8 127static void nft_ctx_init(struct nft_ctx *ctx,
633c9a84 128 struct net *net,
7c95f6d8
PNA
129 const struct sk_buff *skb,
130 const struct nlmsghdr *nlh,
36596dad 131 u8 family,
7c95f6d8
PNA
132 struct nft_table *table,
133 struct nft_chain *chain,
134 const struct nlattr * const *nla)
135{
633c9a84 136 ctx->net = net;
36596dad 137 ctx->family = family;
26b2f552 138 ctx->level = 0;
128ad332
PNA
139 ctx->table = table;
140 ctx->chain = chain;
141 ctx->nla = nla;
142 ctx->portid = NETLINK_CB(skb).portid;
143 ctx->report = nlmsg_report(nlh);
c9626a2c 144 ctx->flags = nlh->nlmsg_flags;
128ad332 145 ctx->seq = nlh->nlmsg_seq;
7c95f6d8
PNA
146}
147
8411b644
PNA
148static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
149 int msg_type, u32 size, gfp_t gfp)
1081d11b
PNA
150{
151 struct nft_trans *trans;
152
8411b644 153 trans = kzalloc(sizeof(struct nft_trans) + size, gfp);
1081d11b
PNA
154 if (trans == NULL)
155 return NULL;
156
b380e5c7 157 trans->msg_type = msg_type;
1081d11b
PNA
158 trans->ctx = *ctx;
159
160 return trans;
161}
162
8411b644
PNA
163static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx,
164 int msg_type, u32 size)
165{
166 return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL);
167}
168
1081d11b
PNA
169static void nft_trans_destroy(struct nft_trans *trans)
170{
171 list_del(&trans->list);
172 kfree(trans);
173}
174
f6ac8585
PNA
175static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
176{
0854db2a 177 struct nftables_pernet *nft_net;
f6ac8585
PNA
178 struct net *net = ctx->net;
179 struct nft_trans *trans;
180
181 if (!nft_set_is_anonymous(set))
182 return;
183
0854db2a
FW
184 nft_net = net_generic(net, nf_tables_net_id);
185 list_for_each_entry_reverse(trans, &nft_net->commit_list, list) {
6a0a8d10
PNA
186 switch (trans->msg_type) {
187 case NFT_MSG_NEWSET:
188 if (nft_trans_set(trans) == set)
189 nft_trans_set_bound(trans) = true;
190 break;
191 case NFT_MSG_NEWSETELEM:
192 if (nft_trans_elem_set(trans) == set)
193 nft_trans_elem_set_bound(trans) = true;
f6ac8585
PNA
194 break;
195 }
196 }
197}
198
d54725cd
PNA
199static int nft_netdev_register_hooks(struct net *net,
200 struct list_head *hook_list)
201{
202 struct nft_hook *hook;
203 int err, j;
204
205 j = 0;
206 list_for_each_entry(hook, hook_list, list) {
207 err = nf_register_net_hook(net, &hook->ops);
208 if (err < 0)
209 goto err_register;
210
211 j++;
212 }
213 return 0;
214
215err_register:
216 list_for_each_entry(hook, hook_list, list) {
217 if (j-- <= 0)
218 break;
219
220 nf_unregister_net_hook(net, &hook->ops);
221 }
222 return err;
223}
224
225static void nft_netdev_unregister_hooks(struct net *net,
226 struct list_head *hook_list)
227{
228 struct nft_hook *hook;
229
230 list_for_each_entry(hook, hook_list, list)
231 nf_unregister_net_hook(net, &hook->ops);
232}
233
c974a3a3
PNA
234static int nf_tables_register_hook(struct net *net,
235 const struct nft_table *table,
236 struct nft_chain *chain)
d8ee8f7c 237{
d54725cd 238 struct nft_base_chain *basechain;
a37061a6 239 const struct nf_hook_ops *ops;
ae6153b5 240
d8ee8f7c 241 if (table->flags & NFT_TABLE_F_DORMANT ||
f323d954 242 !nft_is_base_chain(chain))
d8ee8f7c
PNA
243 return 0;
244
4e25ceb8
FW
245 basechain = nft_base_chain(chain);
246 ops = &basechain->ops;
ae6153b5 247
4e25ceb8
FW
248 if (basechain->type->ops_register)
249 return basechain->type->ops_register(net, ops);
250
d3519cb8 251 if (nft_base_chain_netdev(table->family, basechain->ops.hooknum))
1e9451cb
FW
252 return nft_netdev_register_hooks(net, &basechain->hook_list);
253
254 return nf_register_net_hook(net, &basechain->ops);
d8ee8f7c
PNA
255}
256
c974a3a3
PNA
257static void nf_tables_unregister_hook(struct net *net,
258 const struct nft_table *table,
259 struct nft_chain *chain)
c5598794 260{
d54725cd 261 struct nft_base_chain *basechain;
4e25ceb8
FW
262 const struct nf_hook_ops *ops;
263
d8ee8f7c 264 if (table->flags & NFT_TABLE_F_DORMANT ||
f323d954 265 !nft_is_base_chain(chain))
d8ee8f7c 266 return;
4e25ceb8
FW
267 basechain = nft_base_chain(chain);
268 ops = &basechain->ops;
d8ee8f7c 269
4e25ceb8
FW
270 if (basechain->type->ops_unregister)
271 return basechain->type->ops_unregister(net, ops);
272
d3519cb8 273 if (nft_base_chain_netdev(table->family, basechain->ops.hooknum))
1e9451cb
FW
274 nft_netdev_unregister_hooks(net, &basechain->hook_list);
275 else
276 nf_unregister_net_hook(net, &basechain->ops);
c5598794
AB
277}
278
0854db2a
FW
279static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *trans)
280{
281 struct nftables_pernet *nft_net;
282
283 nft_net = net_generic(net, nf_tables_net_id);
284 list_add_tail(&trans->list, &nft_net->commit_list);
285}
286
ee01d542
AB
287static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type)
288{
289 struct nft_trans *trans;
290
291 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_table));
292 if (trans == NULL)
293 return -ENOMEM;
294
295 if (msg_type == NFT_MSG_NEWTABLE)
f2a6d766 296 nft_activate_next(ctx->net, ctx->table);
ee01d542 297
0854db2a 298 nft_trans_commit_list_add_tail(ctx->net, trans);
ee01d542
AB
299 return 0;
300}
301
302static int nft_deltable(struct nft_ctx *ctx)
303{
304 int err;
305
306 err = nft_trans_table_add(ctx, NFT_MSG_DELTABLE);
307 if (err < 0)
308 return err;
309
f2a6d766 310 nft_deactivate_next(ctx->net, ctx->table);
ee01d542
AB
311 return err;
312}
313
66293c46 314static struct nft_trans *nft_trans_chain_add(struct nft_ctx *ctx, int msg_type)
ee01d542
AB
315{
316 struct nft_trans *trans;
317
318 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_chain));
319 if (trans == NULL)
66293c46 320 return ERR_PTR(-ENOMEM);
ee01d542 321
74cccc3d 322 if (msg_type == NFT_MSG_NEWCHAIN) {
664b0f8c 323 nft_activate_next(ctx->net, ctx->chain);
ee01d542 324
74cccc3d
PNA
325 if (ctx->nla[NFTA_CHAIN_ID]) {
326 nft_trans_chain_id(trans) =
327 ntohl(nla_get_be32(ctx->nla[NFTA_CHAIN_ID]));
328 }
329 }
330
0854db2a 331 nft_trans_commit_list_add_tail(ctx->net, trans);
66293c46 332 return trans;
ee01d542
AB
333}
334
335static int nft_delchain(struct nft_ctx *ctx)
336{
66293c46 337 struct nft_trans *trans;
ee01d542 338
66293c46
FW
339 trans = nft_trans_chain_add(ctx, NFT_MSG_DELCHAIN);
340 if (IS_ERR(trans))
341 return PTR_ERR(trans);
ee01d542
AB
342
343 ctx->table->use--;
664b0f8c 344 nft_deactivate_next(ctx->net, ctx->chain);
ee01d542 345
66293c46 346 return 0;
ee01d542
AB
347}
348
bb7b40ae
PNA
349static void nft_rule_expr_activate(const struct nft_ctx *ctx,
350 struct nft_rule *rule)
351{
352 struct nft_expr *expr;
353
354 expr = nft_expr_first(rule);
31cc578a 355 while (nft_expr_more(rule, expr)) {
bb7b40ae
PNA
356 if (expr->ops->activate)
357 expr->ops->activate(ctx, expr);
358
359 expr = nft_expr_next(expr);
360 }
361}
362
363static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
f6ac8585
PNA
364 struct nft_rule *rule,
365 enum nft_trans_phase phase)
bb7b40ae
PNA
366{
367 struct nft_expr *expr;
368
369 expr = nft_expr_first(rule);
31cc578a 370 while (nft_expr_more(rule, expr)) {
bb7b40ae 371 if (expr->ops->deactivate)
f6ac8585 372 expr->ops->deactivate(ctx, expr, phase);
bb7b40ae
PNA
373
374 expr = nft_expr_next(expr);
375 }
376}
377
ee01d542
AB
378static int
379nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule)
380{
381 /* You cannot delete the same rule twice */
889f7ee7
PNA
382 if (nft_is_active_next(ctx->net, rule)) {
383 nft_deactivate_next(ctx->net, rule);
ee01d542
AB
384 ctx->chain->use--;
385 return 0;
386 }
387 return -ENOENT;
388}
389
390static struct nft_trans *nft_trans_rule_add(struct nft_ctx *ctx, int msg_type,
391 struct nft_rule *rule)
392{
393 struct nft_trans *trans;
394
395 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_rule));
396 if (trans == NULL)
397 return NULL;
398
1a94e38d
PNA
399 if (msg_type == NFT_MSG_NEWRULE && ctx->nla[NFTA_RULE_ID] != NULL) {
400 nft_trans_rule_id(trans) =
401 ntohl(nla_get_be32(ctx->nla[NFTA_RULE_ID]));
402 }
ee01d542 403 nft_trans_rule(trans) = rule;
0854db2a 404 nft_trans_commit_list_add_tail(ctx->net, trans);
ee01d542
AB
405
406 return trans;
407}
408
409static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule)
410{
63b48c73 411 struct nft_flow_rule *flow;
ee01d542
AB
412 struct nft_trans *trans;
413 int err;
414
415 trans = nft_trans_rule_add(ctx, NFT_MSG_DELRULE, rule);
416 if (trans == NULL)
417 return -ENOMEM;
418
63b48c73
PNA
419 if (ctx->chain->flags & NFT_CHAIN_HW_OFFLOAD) {
420 flow = nft_flow_rule_create(ctx->net, rule);
421 if (IS_ERR(flow)) {
422 nft_trans_destroy(trans);
423 return PTR_ERR(flow);
424 }
425
426 nft_trans_flow_rule(trans) = flow;
427 }
428
ee01d542
AB
429 err = nf_tables_delrule_deactivate(ctx, rule);
430 if (err < 0) {
431 nft_trans_destroy(trans);
432 return err;
433 }
f6ac8585 434 nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_PREPARE);
ee01d542
AB
435
436 return 0;
437}
438
439static int nft_delrule_by_chain(struct nft_ctx *ctx)
440{
441 struct nft_rule *rule;
442 int err;
443
444 list_for_each_entry(rule, &ctx->chain->rules, list) {
23b7ca4f
PNA
445 if (!nft_is_active_next(ctx->net, rule))
446 continue;
447
ee01d542
AB
448 err = nft_delrule(ctx, rule);
449 if (err < 0)
450 return err;
451 }
452 return 0;
453}
454
cd5125d8 455static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
ee01d542
AB
456 struct nft_set *set)
457{
458 struct nft_trans *trans;
459
460 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_set));
461 if (trans == NULL)
462 return -ENOMEM;
463
464 if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) {
465 nft_trans_set_id(trans) =
466 ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID]));
37a9cc52 467 nft_activate_next(ctx->net, set);
ee01d542
AB
468 }
469 nft_trans_set(trans) = set;
0854db2a 470 nft_trans_commit_list_add_tail(ctx->net, trans);
ee01d542
AB
471
472 return 0;
473}
474
cd5125d8 475static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
ee01d542
AB
476{
477 int err;
478
479 err = nft_trans_set_add(ctx, NFT_MSG_DELSET, set);
480 if (err < 0)
481 return err;
482
37a9cc52 483 nft_deactivate_next(ctx->net, set);
ee01d542
AB
484 ctx->table->use--;
485
486 return err;
487}
488
e5009240
PNA
489static int nft_trans_obj_add(struct nft_ctx *ctx, int msg_type,
490 struct nft_object *obj)
491{
492 struct nft_trans *trans;
493
494 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_obj));
495 if (trans == NULL)
496 return -ENOMEM;
497
498 if (msg_type == NFT_MSG_NEWOBJ)
499 nft_activate_next(ctx->net, obj);
500
501 nft_trans_obj(trans) = obj;
0854db2a 502 nft_trans_commit_list_add_tail(ctx->net, trans);
e5009240
PNA
503
504 return 0;
505}
506
507static int nft_delobj(struct nft_ctx *ctx, struct nft_object *obj)
508{
509 int err;
510
511 err = nft_trans_obj_add(ctx, NFT_MSG_DELOBJ, obj);
512 if (err < 0)
513 return err;
514
515 nft_deactivate_next(ctx->net, obj);
516 ctx->table->use--;
517
518 return err;
519}
520
3b49e2e9
PNA
521static int nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type,
522 struct nft_flowtable *flowtable)
523{
524 struct nft_trans *trans;
525
526 trans = nft_trans_alloc(ctx, msg_type,
527 sizeof(struct nft_trans_flowtable));
528 if (trans == NULL)
529 return -ENOMEM;
530
531 if (msg_type == NFT_MSG_NEWFLOWTABLE)
532 nft_activate_next(ctx->net, flowtable);
533
534 nft_trans_flowtable(trans) = flowtable;
0854db2a 535 nft_trans_commit_list_add_tail(ctx->net, trans);
3b49e2e9
PNA
536
537 return 0;
538}
539
540static int nft_delflowtable(struct nft_ctx *ctx,
541 struct nft_flowtable *flowtable)
542{
543 int err;
544
545 err = nft_trans_flowtable_add(ctx, NFT_MSG_DELFLOWTABLE, flowtable);
546 if (err < 0)
547 return err;
548
549 nft_deactivate_next(ctx->net, flowtable);
550 ctx->table->use--;
551
552 return err;
553}
554
96518518
PM
555/*
556 * Tables
557 */
558
36596dad 559static struct nft_table *nft_table_lookup(const struct net *net,
f2a6d766 560 const struct nlattr *nla,
6001a930 561 u8 family, u8 genmask, u32 nlpid)
96518518 562{
0854db2a 563 struct nftables_pernet *nft_net;
96518518
PM
564 struct nft_table *table;
565
cac20fcd
PNA
566 if (nla == NULL)
567 return ERR_PTR(-EINVAL);
568
0854db2a
FW
569 nft_net = net_generic(net, nf_tables_net_id);
570 list_for_each_entry_rcu(table, &nft_net->tables, list,
571 lockdep_is_held(&nft_net->commit_mutex)) {
f2a6d766 572 if (!nla_strcmp(nla, table->name) &&
98319cb9 573 table->family == family &&
6001a930
PNA
574 nft_active_genmask(table, genmask)) {
575 if (nft_table_has_owner(table) &&
576 table->nlpid != nlpid)
577 return ERR_PTR(-EPERM);
578
96518518 579 return table;
6001a930 580 }
96518518 581 }
cac20fcd
PNA
582
583 return ERR_PTR(-ENOENT);
96518518
PM
584}
585
3ecbfd65
HS
586static struct nft_table *nft_table_lookup_byhandle(const struct net *net,
587 const struct nlattr *nla,
588 u8 genmask)
589{
0854db2a 590 struct nftables_pernet *nft_net;
3ecbfd65
HS
591 struct nft_table *table;
592
0854db2a
FW
593 nft_net = net_generic(net, nf_tables_net_id);
594 list_for_each_entry(table, &nft_net->tables, list) {
3ecbfd65
HS
595 if (be64_to_cpu(nla_get_be64(nla)) == table->handle &&
596 nft_active_genmask(table, genmask))
597 return table;
598 }
3ecbfd65
HS
599
600 return ERR_PTR(-ENOENT);
601}
602
96518518
PM
603static inline u64 nf_tables_alloc_handle(struct nft_table *table)
604{
605 return ++table->hgenerator;
606}
607
32537e91 608static const struct nft_chain_type *chain_type[NFPROTO_NUMPROTO][NFT_CHAIN_T_MAX];
9370761c 609
82603549
PNA
610static const struct nft_chain_type *
611__nft_chain_type_get(u8 family, enum nft_chain_types type)
612{
613 if (family >= NFPROTO_NUMPROTO ||
614 type >= NFT_CHAIN_T_MAX)
615 return NULL;
616
617 return chain_type[family][type];
618}
619
32537e91 620static const struct nft_chain_type *
1ea26cca 621__nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family)
9370761c 622{
82603549 623 const struct nft_chain_type *type;
9370761c
PNA
624 int i;
625
baae3e62 626 for (i = 0; i < NFT_CHAIN_T_MAX; i++) {
82603549
PNA
627 type = __nft_chain_type_get(family, i);
628 if (!type)
629 continue;
630 if (!nla_strcmp(nla, type->name))
631 return type;
9370761c 632 }
baae3e62 633 return NULL;
9370761c
PNA
634}
635
eb014de4
PNA
636struct nft_module_request {
637 struct list_head list;
638 char module[MODULE_NAME_LEN];
639 bool done;
640};
641
452238e8 642#ifdef CONFIG_MODULES
cefa31a9
FW
643__printf(2, 3) int nft_request_module(struct net *net, const char *fmt,
644 ...)
452238e8
FW
645{
646 char module_name[MODULE_NAME_LEN];
0854db2a 647 struct nftables_pernet *nft_net;
eb014de4 648 struct nft_module_request *req;
452238e8
FW
649 va_list args;
650 int ret;
651
452238e8
FW
652 va_start(args, fmt);
653 ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
654 va_end(args);
9332d27d 655 if (ret >= MODULE_NAME_LEN)
eb014de4 656 return 0;
452238e8 657
0854db2a
FW
658 nft_net = net_generic(net, nf_tables_net_id);
659 list_for_each_entry(req, &nft_net->module_list, list) {
eb014de4
PNA
660 if (!strcmp(req->module, module_name)) {
661 if (req->done)
662 return 0;
ec7470b8 663
eb014de4
PNA
664 /* A request to load this module already exists. */
665 return -EAGAIN;
666 }
667 }
668
669 req = kmalloc(sizeof(*req), GFP_KERNEL);
670 if (!req)
671 return -ENOMEM;
672
673 req->done = false;
674 strlcpy(req->module, module_name, MODULE_NAME_LEN);
0854db2a 675 list_add_tail(&req->list, &nft_net->module_list);
eb014de4
PNA
676
677 return -EAGAIN;
452238e8 678}
cefa31a9 679EXPORT_SYMBOL_GPL(nft_request_module);
452238e8
FW
680#endif
681
f102d66b
FW
682static void lockdep_nfnl_nft_mutex_not_held(void)
683{
684#ifdef CONFIG_PROVE_LOCKING
c0700dfa
FW
685 if (debug_locks)
686 WARN_ON_ONCE(lockdep_nfnl_is_held(NFNL_SUBSYS_NFTABLES));
f102d66b
FW
687#endif
688}
689
32537e91 690static const struct nft_chain_type *
452238e8
FW
691nf_tables_chain_type_lookup(struct net *net, const struct nlattr *nla,
692 u8 family, bool autoload)
9370761c 693{
32537e91 694 const struct nft_chain_type *type;
9370761c 695
1ea26cca 696 type = __nf_tables_chain_type_lookup(nla, family);
93b0806f
PM
697 if (type != NULL)
698 return type;
f102d66b
FW
699
700 lockdep_nfnl_nft_mutex_not_held();
9370761c 701#ifdef CONFIG_MODULES
93b0806f 702 if (autoload) {
eb014de4
PNA
703 if (nft_request_module(net, "nft-chain-%u-%.*s", family,
704 nla_len(nla),
705 (const char *)nla_data(nla)) == -EAGAIN)
93b0806f 706 return ERR_PTR(-EAGAIN);
9370761c
PNA
707 }
708#endif
93b0806f 709 return ERR_PTR(-ENOENT);
9370761c
PNA
710}
711
802b8051
PNA
712static __be16 nft_base_seq(const struct net *net)
713{
0854db2a
FW
714 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
715
716 return htons(nft_net->base_seq & 0xffff);
802b8051
PNA
717}
718
96518518 719static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = {
1cae565e
PNA
720 [NFTA_TABLE_NAME] = { .type = NLA_STRING,
721 .len = NFT_TABLE_MAXNAMELEN - 1 },
9ddf6323 722 [NFTA_TABLE_FLAGS] = { .type = NLA_U32 },
3ecbfd65 723 [NFTA_TABLE_HANDLE] = { .type = NLA_U64 },
7a81575b
JGG
724 [NFTA_TABLE_USERDATA] = { .type = NLA_BINARY,
725 .len = NFT_USERDATA_MAXLEN }
96518518
PM
726};
727
84d7fce6
PNA
728static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net,
729 u32 portid, u32 seq, int event, u32 flags,
730 int family, const struct nft_table *table)
96518518
PM
731{
732 struct nlmsghdr *nlh;
96518518 733
dedb67c4 734 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
19c28b13
PNA
735 nlh = nfnl_msg_put(skb, portid, seq, event, flags, family,
736 NFNETLINK_V0, nft_base_seq(net));
737 if (!nlh)
96518518
PM
738 goto nla_put_failure;
739
9ddf6323 740 if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) ||
d8bcc768 741 nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) ||
3ecbfd65
HS
742 nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)) ||
743 nla_put_be64(skb, NFTA_TABLE_HANDLE, cpu_to_be64(table->handle),
744 NFTA_TABLE_PAD))
96518518 745 goto nla_put_failure;
6001a930
PNA
746 if (nft_table_has_owner(table) &&
747 nla_put_be32(skb, NFTA_TABLE_OWNER, htonl(table->nlpid)))
748 goto nla_put_failure;
96518518 749
7a81575b
JGG
750 if (table->udata) {
751 if (nla_put(skb, NFTA_TABLE_USERDATA, table->udlen, table->udata))
752 goto nla_put_failure;
753 }
754
053c095a
JB
755 nlmsg_end(skb, nlh);
756 return 0;
96518518
PM
757
758nla_put_failure:
759 nlmsg_trim(skb, nlh);
760 return -1;
761}
762
67cc570e
PNA
763struct nftnl_skb_parms {
764 bool report;
765};
766#define NFT_CB(skb) (*(struct nftnl_skb_parms*)&((skb)->cb))
767
768static void nft_notify_enqueue(struct sk_buff *skb, bool report,
769 struct list_head *notify_list)
770{
771 NFT_CB(skb).report = report;
772 list_add_tail(&skb->list, notify_list);
773}
774
25e94a99 775static void nf_tables_table_notify(const struct nft_ctx *ctx, int event)
96518518 776{
0854db2a 777 struct nftables_pernet *nft_net;
96518518 778 struct sk_buff *skb;
96518518
PM
779 int err;
780
128ad332
PNA
781 if (!ctx->report &&
782 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
25e94a99 783 return;
96518518 784
96518518
PM
785 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
786 if (skb == NULL)
787 goto err;
788
84d7fce6 789 err = nf_tables_fill_table_info(skb, ctx->net, ctx->portid, ctx->seq,
36596dad 790 event, 0, ctx->family, ctx->table);
96518518
PM
791 if (err < 0) {
792 kfree_skb(skb);
793 goto err;
794 }
795
0854db2a
FW
796 nft_net = net_generic(ctx->net, nf_tables_net_id);
797 nft_notify_enqueue(skb, ctx->report, &nft_net->notify_list);
25e94a99 798 return;
96518518 799err:
25e94a99 800 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
96518518
PM
801}
802
803static int nf_tables_dump_tables(struct sk_buff *skb,
804 struct netlink_callback *cb)
805{
806 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
0854db2a 807 struct nftables_pernet *nft_net;
96518518
PM
808 const struct nft_table *table;
809 unsigned int idx = 0, s_idx = cb->args[0];
99633ab2 810 struct net *net = sock_net(skb->sk);
96518518
PM
811 int family = nfmsg->nfgen_family;
812
e688a7f8 813 rcu_read_lock();
0854db2a
FW
814 nft_net = net_generic(net, nf_tables_net_id);
815 cb->seq = nft_net->base_seq;
38e029f1 816
0854db2a 817 list_for_each_entry_rcu(table, &nft_net->tables, list) {
98319cb9 818 if (family != NFPROTO_UNSPEC && family != table->family)
96518518
PM
819 continue;
820
36596dad
PNA
821 if (idx < s_idx)
822 goto cont;
823 if (idx > s_idx)
824 memset(&cb->args[1], 0,
825 sizeof(cb->args) - sizeof(cb->args[0]));
826 if (!nft_is_active(net, table))
827 continue;
828 if (nf_tables_fill_table_info(skb, net,
829 NETLINK_CB(cb->skb).portid,
830 cb->nlh->nlmsg_seq,
831 NFT_MSG_NEWTABLE, NLM_F_MULTI,
98319cb9 832 table->family, table) < 0)
36596dad
PNA
833 goto done;
834
835 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
96518518 836cont:
36596dad 837 idx++;
96518518
PM
838 }
839done:
e688a7f8 840 rcu_read_unlock();
96518518
PM
841 cb->args[0] = idx;
842 return skb->len;
843}
844
d9adf22a
FW
845static int nft_netlink_dump_start_rcu(struct sock *nlsk, struct sk_buff *skb,
846 const struct nlmsghdr *nlh,
847 struct netlink_dump_control *c)
848{
849 int err;
850
851 if (!try_module_get(THIS_MODULE))
852 return -EINVAL;
853
854 rcu_read_unlock();
855 err = netlink_dump_start(nlsk, skb, nlh, c);
856 rcu_read_lock();
857 module_put(THIS_MODULE);
858
859 return err;
860}
861
862/* called with rcu_read_lock held */
7b8002a1
PNA
863static int nf_tables_gettable(struct net *net, struct sock *nlsk,
864 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
865 const struct nlattr * const nla[],
866 struct netlink_ext_ack *extack)
96518518
PM
867{
868 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 869 u8 genmask = nft_genmask_cur(net);
96518518
PM
870 const struct nft_table *table;
871 struct sk_buff *skb2;
872 int family = nfmsg->nfgen_family;
873 int err;
874
875 if (nlh->nlmsg_flags & NLM_F_DUMP) {
876 struct netlink_dump_control c = {
877 .dump = nf_tables_dump_tables,
d9adf22a 878 .module = THIS_MODULE,
96518518 879 };
d9adf22a
FW
880
881 return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
96518518
PM
882 }
883
6001a930 884 table = nft_table_lookup(net, nla[NFTA_TABLE_NAME], family, genmask, 0);
36dd1bcc
PNA
885 if (IS_ERR(table)) {
886 NL_SET_BAD_ATTR(extack, nla[NFTA_TABLE_NAME]);
96518518 887 return PTR_ERR(table);
36dd1bcc 888 }
96518518 889
d9adf22a 890 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
96518518
PM
891 if (!skb2)
892 return -ENOMEM;
893
84d7fce6 894 err = nf_tables_fill_table_info(skb2, net, NETLINK_CB(skb).portid,
96518518
PM
895 nlh->nlmsg_seq, NFT_MSG_NEWTABLE, 0,
896 family, table);
897 if (err < 0)
ee921183 898 goto err_fill_table_info;
96518518 899
ee921183 900 return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
96518518 901
ee921183 902err_fill_table_info:
96518518
PM
903 kfree_skb(skb2);
904 return err;
905}
906
c9c17211 907static void nft_table_disable(struct net *net, struct nft_table *table, u32 cnt)
10435c11
F
908{
909 struct nft_chain *chain;
910 u32 i = 0;
911
912 list_for_each_entry(chain, &table->chains, list) {
913 if (!nft_is_active_next(net, chain))
914 continue;
f323d954 915 if (!nft_is_base_chain(chain))
10435c11
F
916 continue;
917
918 if (cnt && i++ == cnt)
919 break;
920
1e9451cb 921 nf_tables_unregister_hook(net, table, chain);
10435c11
F
922 }
923}
924
c9c17211 925static int nf_tables_table_enable(struct net *net, struct nft_table *table)
9ddf6323
PNA
926{
927 struct nft_chain *chain;
928 int err, i = 0;
929
930 list_for_each_entry(chain, &table->chains, list) {
664b0f8c
PNA
931 if (!nft_is_active_next(net, chain))
932 continue;
f323d954 933 if (!nft_is_base_chain(chain))
d2012975
PNA
934 continue;
935
1e9451cb 936 err = nf_tables_register_hook(net, table, chain);
9ddf6323 937 if (err < 0)
d54725cd 938 goto err_register_hooks;
9ddf6323
PNA
939
940 i++;
941 }
942 return 0;
d54725cd
PNA
943
944err_register_hooks:
10435c11 945 if (i)
c9c17211 946 nft_table_disable(net, table, i);
9ddf6323
PNA
947 return err;
948}
949
c9c17211 950static void nf_tables_table_disable(struct net *net, struct nft_table *table)
9ddf6323 951{
c9c17211 952 nft_table_disable(net, table, 0);
9ddf6323
PNA
953}
954
0ce7cf41
PNA
955enum {
956 NFT_TABLE_STATE_UNCHANGED = 0,
957 NFT_TABLE_STATE_DORMANT,
958 NFT_TABLE_STATE_WAKEUP
959};
960
e1aaca93 961static int nf_tables_updtable(struct nft_ctx *ctx)
9ddf6323 962{
55dd6f93 963 struct nft_trans *trans;
e1aaca93 964 u32 flags;
55dd6f93 965 int ret = 0;
9ddf6323 966
e1aaca93
PNA
967 if (!ctx->nla[NFTA_TABLE_FLAGS])
968 return 0;
9ddf6323 969
e1aaca93 970 flags = ntohl(nla_get_be32(ctx->nla[NFTA_TABLE_FLAGS]));
6001a930
PNA
971 if (flags & ~NFT_TABLE_F_MASK)
972 return -EOPNOTSUPP;
e1aaca93 973
63283dd2
PNA
974 if (flags == ctx->table->flags)
975 return 0;
976
9cc0001a
PNA
977 if ((nft_table_has_owner(ctx->table) &&
978 !(flags & NFT_TABLE_F_OWNER)) ||
979 (!nft_table_has_owner(ctx->table) &&
980 flags & NFT_TABLE_F_OWNER))
981 return -EOPNOTSUPP;
982
55dd6f93
PNA
983 trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE,
984 sizeof(struct nft_trans_table));
985 if (trans == NULL)
986 return -ENOMEM;
9ddf6323 987
e1aaca93
PNA
988 if ((flags & NFT_TABLE_F_DORMANT) &&
989 !(ctx->table->flags & NFT_TABLE_F_DORMANT)) {
0ce7cf41 990 nft_trans_table_state(trans) = NFT_TABLE_STATE_DORMANT;
e1aaca93
PNA
991 } else if (!(flags & NFT_TABLE_F_DORMANT) &&
992 ctx->table->flags & NFT_TABLE_F_DORMANT) {
c9c17211 993 ret = nf_tables_table_enable(ctx->net, ctx->table);
1e9451cb 994 if (ret >= 0)
0ce7cf41 995 nft_trans_table_state(trans) = NFT_TABLE_STATE_WAKEUP;
9ddf6323 996 }
e1aaca93
PNA
997 if (ret < 0)
998 goto err;
9ddf6323 999
0ce7cf41 1000 nft_trans_table_flags(trans) = flags;
55dd6f93 1001 nft_trans_table_update(trans) = true;
0854db2a 1002 nft_trans_commit_list_add_tail(ctx->net, trans);
55dd6f93 1003 return 0;
9ddf6323 1004err:
55dd6f93 1005 nft_trans_destroy(trans);
9ddf6323
PNA
1006 return ret;
1007}
1008
1b2470e5
FW
1009static u32 nft_chain_hash(const void *data, u32 len, u32 seed)
1010{
1011 const char *name = data;
1012
1013 return jhash(name, strlen(name), seed);
1014}
1015
1016static u32 nft_chain_hash_obj(const void *data, u32 len, u32 seed)
1017{
1018 const struct nft_chain *chain = data;
1019
1020 return nft_chain_hash(chain->name, 0, seed);
1021}
1022
1023static int nft_chain_hash_cmp(struct rhashtable_compare_arg *arg,
1024 const void *ptr)
1025{
1026 const struct nft_chain *chain = ptr;
1027 const char *name = arg->key;
1028
1029 return strcmp(chain->name, name);
1030}
1031
4d44175a
FW
1032static u32 nft_objname_hash(const void *data, u32 len, u32 seed)
1033{
1034 const struct nft_object_hash_key *k = data;
1035
1036 seed ^= hash_ptr(k->table, 32);
1037
1038 return jhash(k->name, strlen(k->name), seed);
1039}
1040
1041static u32 nft_objname_hash_obj(const void *data, u32 len, u32 seed)
1042{
1043 const struct nft_object *obj = data;
1044
1045 return nft_objname_hash(&obj->key, 0, seed);
1046}
1047
1048static int nft_objname_hash_cmp(struct rhashtable_compare_arg *arg,
1049 const void *ptr)
1050{
1051 const struct nft_object_hash_key *k = arg->key;
1052 const struct nft_object *obj = ptr;
1053
1054 if (obj->key.table != k->table)
1055 return -1;
1056
1057 return strcmp(obj->key.name, k->name);
1058}
1059
633c9a84
PNA
1060static int nf_tables_newtable(struct net *net, struct sock *nlsk,
1061 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
1062 const struct nlattr * const nla[],
1063 struct netlink_ext_ack *extack)
96518518 1064{
0854db2a 1065 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
96518518 1066 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 1067 u8 genmask = nft_genmask_next(net);
96518518 1068 int family = nfmsg->nfgen_family;
36dd1bcc
PNA
1069 const struct nlattr *attr;
1070 struct nft_table *table;
e1aaca93 1071 struct nft_ctx ctx;
7a81575b 1072 u32 flags = 0;
55dd6f93 1073 int err;
96518518 1074
0854db2a 1075 lockdep_assert_held(&nft_net->commit_mutex);
36dd1bcc 1076 attr = nla[NFTA_TABLE_NAME];
6001a930
PNA
1077 table = nft_table_lookup(net, attr, family, genmask,
1078 NETLINK_CB(skb).portid);
96518518
PM
1079 if (IS_ERR(table)) {
1080 if (PTR_ERR(table) != -ENOENT)
1081 return PTR_ERR(table);
1a28ad74 1082 } else {
36dd1bcc
PNA
1083 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1084 NL_SET_BAD_ATTR(extack, attr);
96518518 1085 return -EEXIST;
36dd1bcc 1086 }
96518518
PM
1087 if (nlh->nlmsg_flags & NLM_F_REPLACE)
1088 return -EOPNOTSUPP;
e1aaca93 1089
98319cb9 1090 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
e1aaca93 1091 return nf_tables_updtable(&ctx);
96518518
PM
1092 }
1093
c5c1f975
PM
1094 if (nla[NFTA_TABLE_FLAGS]) {
1095 flags = ntohl(nla_get_be32(nla[NFTA_TABLE_FLAGS]));
6001a930
PNA
1096 if (flags & ~NFT_TABLE_F_MASK)
1097 return -EOPNOTSUPP;
c5c1f975
PM
1098 }
1099
ffdb210e 1100 err = -ENOMEM;
1cae565e 1101 table = kzalloc(sizeof(*table), GFP_KERNEL);
ffdb210e 1102 if (table == NULL)
98319cb9 1103 goto err_kzalloc;
96518518 1104
36dd1bcc 1105 table->name = nla_strdup(attr, GFP_KERNEL);
e46abbcc 1106 if (table->name == NULL)
98319cb9 1107 goto err_strdup;
e46abbcc 1108
7a81575b 1109 if (nla[NFTA_TABLE_USERDATA]) {
85db827a 1110 table->udata = nla_memdup(nla[NFTA_TABLE_USERDATA], GFP_KERNEL);
7a81575b
JGG
1111 if (table->udata == NULL)
1112 goto err_table_udata;
1113
85db827a 1114 table->udlen = nla_len(nla[NFTA_TABLE_USERDATA]);
7a81575b
JGG
1115 }
1116
1b2470e5
FW
1117 err = rhltable_init(&table->chains_ht, &nft_chain_ht_params);
1118 if (err)
1119 goto err_chain_ht;
1120
96518518 1121 INIT_LIST_HEAD(&table->chains);
20a69341 1122 INIT_LIST_HEAD(&table->sets);
e5009240 1123 INIT_LIST_HEAD(&table->objects);
3b49e2e9 1124 INIT_LIST_HEAD(&table->flowtables);
98319cb9 1125 table->family = family;
c5c1f975 1126 table->flags = flags;
3ecbfd65 1127 table->handle = ++table_handle;
6001a930
PNA
1128 if (table->flags & NFT_TABLE_F_OWNER)
1129 table->nlpid = NETLINK_CB(skb).portid;
9ddf6323 1130
98319cb9 1131 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
55dd6f93 1132 err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE);
ffdb210e 1133 if (err < 0)
98319cb9 1134 goto err_trans;
ffdb210e 1135
0854db2a 1136 list_add_tail_rcu(&table->list, &nft_net->tables);
96518518 1137 return 0;
98319cb9 1138err_trans:
1b2470e5
FW
1139 rhltable_destroy(&table->chains_ht);
1140err_chain_ht:
7a81575b
JGG
1141 kfree(table->udata);
1142err_table_udata:
e46abbcc 1143 kfree(table->name);
98319cb9 1144err_strdup:
ffdb210e 1145 kfree(table);
98319cb9 1146err_kzalloc:
ffdb210e 1147 return err;
96518518
PM
1148}
1149
b9ac12ef
AB
1150static int nft_flush_table(struct nft_ctx *ctx)
1151{
3b49e2e9 1152 struct nft_flowtable *flowtable, *nft;
b9ac12ef 1153 struct nft_chain *chain, *nc;
e5009240 1154 struct nft_object *obj, *ne;
b9ac12ef 1155 struct nft_set *set, *ns;
3b49e2e9 1156 int err;
b9ac12ef 1157
a2f18db0 1158 list_for_each_entry(chain, &ctx->table->chains, list) {
664b0f8c
PNA
1159 if (!nft_is_active_next(ctx->net, chain))
1160 continue;
1161
d0e2c7de
PNA
1162 if (nft_chain_is_bound(chain))
1163 continue;
1164
b9ac12ef
AB
1165 ctx->chain = chain;
1166
1167 err = nft_delrule_by_chain(ctx);
1168 if (err < 0)
1169 goto out;
b9ac12ef
AB
1170 }
1171
1172 list_for_each_entry_safe(set, ns, &ctx->table->sets, list) {
37a9cc52
PNA
1173 if (!nft_is_active_next(ctx->net, set))
1174 continue;
1175
408070d6 1176 if (nft_set_is_anonymous(set) &&
b9ac12ef
AB
1177 !list_empty(&set->bindings))
1178 continue;
1179
1180 err = nft_delset(ctx, set);
1181 if (err < 0)
1182 goto out;
1183 }
1184
3b49e2e9 1185 list_for_each_entry_safe(flowtable, nft, &ctx->table->flowtables, list) {
335178d5
FW
1186 if (!nft_is_active_next(ctx->net, flowtable))
1187 continue;
1188
3b49e2e9
PNA
1189 err = nft_delflowtable(ctx, flowtable);
1190 if (err < 0)
1191 goto out;
1192 }
1193
e5009240 1194 list_for_each_entry_safe(obj, ne, &ctx->table->objects, list) {
335178d5
FW
1195 if (!nft_is_active_next(ctx->net, obj))
1196 continue;
1197
e5009240
PNA
1198 err = nft_delobj(ctx, obj);
1199 if (err < 0)
1200 goto out;
1201 }
1202
a2f18db0 1203 list_for_each_entry_safe(chain, nc, &ctx->table->chains, list) {
664b0f8c
PNA
1204 if (!nft_is_active_next(ctx->net, chain))
1205 continue;
1206
d0e2c7de
PNA
1207 if (nft_chain_is_bound(chain))
1208 continue;
1209
a2f18db0
PNA
1210 ctx->chain = chain;
1211
1212 err = nft_delchain(ctx);
1213 if (err < 0)
1214 goto out;
1215 }
1216
b9ac12ef
AB
1217 err = nft_deltable(ctx);
1218out:
1219 return err;
1220}
1221
1222static int nft_flush(struct nft_ctx *ctx, int family)
1223{
0854db2a 1224 struct nftables_pernet *nft_net = net_generic(ctx->net, nf_tables_net_id);
b9ac12ef
AB
1225 struct nft_table *table, *nt;
1226 const struct nlattr * const *nla = ctx->nla;
1227 int err = 0;
1228
0854db2a 1229 list_for_each_entry_safe(table, nt, &nft_net->tables, list) {
98319cb9 1230 if (family != AF_UNSPEC && table->family != family)
b9ac12ef
AB
1231 continue;
1232
98319cb9 1233 ctx->family = table->family;
f2a6d766 1234
36596dad
PNA
1235 if (!nft_is_active_next(ctx->net, table))
1236 continue;
b9ac12ef 1237
6001a930
PNA
1238 if (nft_table_has_owner(table) && table->nlpid != ctx->portid)
1239 continue;
1240
36596dad
PNA
1241 if (nla[NFTA_TABLE_NAME] &&
1242 nla_strcmp(nla[NFTA_TABLE_NAME], table->name) != 0)
1243 continue;
b9ac12ef 1244
36596dad
PNA
1245 ctx->table = table;
1246
1247 err = nft_flush_table(ctx);
1248 if (err < 0)
1249 goto out;
b9ac12ef
AB
1250 }
1251out:
1252 return err;
1253}
1254
633c9a84
PNA
1255static int nf_tables_deltable(struct net *net, struct sock *nlsk,
1256 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
1257 const struct nlattr * const nla[],
1258 struct netlink_ext_ack *extack)
96518518
PM
1259{
1260 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 1261 u8 genmask = nft_genmask_next(net);
ee01d542 1262 int family = nfmsg->nfgen_family;
36dd1bcc
PNA
1263 const struct nlattr *attr;
1264 struct nft_table *table;
55dd6f93 1265 struct nft_ctx ctx;
96518518 1266
36596dad 1267 nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla);
3ecbfd65
HS
1268 if (family == AF_UNSPEC ||
1269 (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE]))
b9ac12ef
AB
1270 return nft_flush(&ctx, family);
1271
36dd1bcc
PNA
1272 if (nla[NFTA_TABLE_HANDLE]) {
1273 attr = nla[NFTA_TABLE_HANDLE];
1274 table = nft_table_lookup_byhandle(net, attr, genmask);
1275 } else {
1276 attr = nla[NFTA_TABLE_NAME];
6001a930
PNA
1277 table = nft_table_lookup(net, attr, family, genmask,
1278 NETLINK_CB(skb).portid);
36dd1bcc 1279 }
3ecbfd65 1280
36dd1bcc
PNA
1281 if (IS_ERR(table)) {
1282 NL_SET_BAD_ATTR(extack, attr);
96518518 1283 return PTR_ERR(table);
36dd1bcc 1284 }
96518518 1285
a8278400
PNA
1286 if (nlh->nlmsg_flags & NLM_F_NONREC &&
1287 table->use > 0)
1288 return -EBUSY;
1289
98319cb9 1290 ctx.family = family;
b9ac12ef 1291 ctx.table = table;
55dd6f93 1292
b9ac12ef 1293 return nft_flush_table(&ctx);
96518518
PM
1294}
1295
55dd6f93
PNA
1296static void nf_tables_table_destroy(struct nft_ctx *ctx)
1297{
fa5950e4
FW
1298 if (WARN_ON(ctx->table->use > 0))
1299 return;
4fefee57 1300
1b2470e5 1301 rhltable_destroy(&ctx->table->chains_ht);
e46abbcc 1302 kfree(ctx->table->name);
bc7a7082 1303 kfree(ctx->table->udata);
55dd6f93 1304 kfree(ctx->table);
55dd6f93
PNA
1305}
1306
cc07eeb0 1307void nft_register_chain_type(const struct nft_chain_type *ctype)
96518518 1308{
96518518 1309 nfnl_lock(NFNL_SUBSYS_NFTABLES);
82603549 1310 if (WARN_ON(__nft_chain_type_get(ctype->family, ctype->type))) {
cc07eeb0
PNA
1311 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1312 return;
96518518 1313 }
9370761c 1314 chain_type[ctype->family][ctype->type] = ctype;
96518518 1315 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
96518518 1316}
9370761c 1317EXPORT_SYMBOL_GPL(nft_register_chain_type);
96518518 1318
32537e91 1319void nft_unregister_chain_type(const struct nft_chain_type *ctype)
96518518 1320{
96518518 1321 nfnl_lock(NFNL_SUBSYS_NFTABLES);
9370761c 1322 chain_type[ctype->family][ctype->type] = NULL;
96518518
PM
1323 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
1324}
9370761c 1325EXPORT_SYMBOL_GPL(nft_unregister_chain_type);
96518518
PM
1326
1327/*
1328 * Chains
1329 */
1330
1331static struct nft_chain *
cac20fcd 1332nft_chain_lookup_byhandle(const struct nft_table *table, u64 handle, u8 genmask)
96518518
PM
1333{
1334 struct nft_chain *chain;
1335
1336 list_for_each_entry(chain, &table->chains, list) {
664b0f8c
PNA
1337 if (chain->handle == handle &&
1338 nft_active_genmask(chain, genmask))
96518518
PM
1339 return chain;
1340 }
1341
1342 return ERR_PTR(-ENOENT);
1343}
1344
4d44175a 1345static bool lockdep_commit_lock_is_held(const struct net *net)
f102d66b
FW
1346{
1347#ifdef CONFIG_PROVE_LOCKING
0854db2a
FW
1348 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
1349
1350 return lockdep_is_held(&nft_net->commit_mutex);
f102d66b
FW
1351#else
1352 return true;
1353#endif
1354}
1355
1356static struct nft_chain *nft_chain_lookup(struct net *net,
1357 struct nft_table *table,
cac20fcd 1358 const struct nlattr *nla, u8 genmask)
96518518 1359{
1b2470e5
FW
1360 char search[NFT_CHAIN_MAXNAMELEN + 1];
1361 struct rhlist_head *tmp, *list;
96518518
PM
1362 struct nft_chain *chain;
1363
1364 if (nla == NULL)
1365 return ERR_PTR(-EINVAL);
1366
872f6903 1367 nla_strscpy(search, nla, sizeof(search));
96518518 1368
1b2470e5 1369 WARN_ON(!rcu_read_lock_held() &&
f102d66b 1370 !lockdep_commit_lock_is_held(net));
1b2470e5
FW
1371
1372 chain = ERR_PTR(-ENOENT);
1373 rcu_read_lock();
1374 list = rhltable_lookup(&table->chains_ht, search, nft_chain_ht_params);
1375 if (!list)
1376 goto out_unlock;
1377
1378 rhl_for_each_entry_rcu(chain, tmp, list, rhlhead) {
1379 if (nft_active_genmask(chain, genmask))
1380 goto out_unlock;
1381 }
1382 chain = ERR_PTR(-ENOENT);
1383out_unlock:
1384 rcu_read_unlock();
1385 return chain;
96518518
PM
1386}
1387
1388static const struct nla_policy nft_chain_policy[NFTA_CHAIN_MAX + 1] = {
b2fbd044
LZ
1389 [NFTA_CHAIN_TABLE] = { .type = NLA_STRING,
1390 .len = NFT_TABLE_MAXNAMELEN - 1 },
96518518
PM
1391 [NFTA_CHAIN_HANDLE] = { .type = NLA_U64 },
1392 [NFTA_CHAIN_NAME] = { .type = NLA_STRING,
1393 .len = NFT_CHAIN_MAXNAMELEN - 1 },
1394 [NFTA_CHAIN_HOOK] = { .type = NLA_NESTED },
0ca743a5 1395 [NFTA_CHAIN_POLICY] = { .type = NLA_U32 },
9332d27d
FW
1396 [NFTA_CHAIN_TYPE] = { .type = NLA_STRING,
1397 .len = NFT_MODULE_AUTOLOAD_LIMIT },
0ca743a5 1398 [NFTA_CHAIN_COUNTERS] = { .type = NLA_NESTED },
c9626a2c 1399 [NFTA_CHAIN_FLAGS] = { .type = NLA_U32 },
74cccc3d 1400 [NFTA_CHAIN_ID] = { .type = NLA_U32 },
002f2176
JGG
1401 [NFTA_CHAIN_USERDATA] = { .type = NLA_BINARY,
1402 .len = NFT_USERDATA_MAXLEN },
96518518
PM
1403};
1404
1405static const struct nla_policy nft_hook_policy[NFTA_HOOK_MAX + 1] = {
1406 [NFTA_HOOK_HOOKNUM] = { .type = NLA_U32 },
1407 [NFTA_HOOK_PRIORITY] = { .type = NLA_U32 },
2cbce139
PNA
1408 [NFTA_HOOK_DEV] = { .type = NLA_STRING,
1409 .len = IFNAMSIZ - 1 },
96518518
PM
1410};
1411
0ca743a5
PNA
1412static int nft_dump_stats(struct sk_buff *skb, struct nft_stats __percpu *stats)
1413{
1414 struct nft_stats *cpu_stats, total;
1415 struct nlattr *nest;
ce355e20
ED
1416 unsigned int seq;
1417 u64 pkts, bytes;
0ca743a5
PNA
1418 int cpu;
1419
edbd82c5
FW
1420 if (!stats)
1421 return 0;
1422
0ca743a5
PNA
1423 memset(&total, 0, sizeof(total));
1424 for_each_possible_cpu(cpu) {
1425 cpu_stats = per_cpu_ptr(stats, cpu);
ce355e20
ED
1426 do {
1427 seq = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
1428 pkts = cpu_stats->pkts;
1429 bytes = cpu_stats->bytes;
1430 } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, seq));
1431 total.pkts += pkts;
1432 total.bytes += bytes;
0ca743a5 1433 }
ae0be8de 1434 nest = nla_nest_start_noflag(skb, NFTA_CHAIN_COUNTERS);
0ca743a5
PNA
1435 if (nest == NULL)
1436 goto nla_put_failure;
1437
b46f6ded
ND
1438 if (nla_put_be64(skb, NFTA_COUNTER_PACKETS, cpu_to_be64(total.pkts),
1439 NFTA_COUNTER_PAD) ||
1440 nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes),
1441 NFTA_COUNTER_PAD))
0ca743a5
PNA
1442 goto nla_put_failure;
1443
1444 nla_nest_end(skb, nest);
1445 return 0;
1446
1447nla_put_failure:
1448 return -ENOSPC;
1449}
1450
d54725cd
PNA
1451static int nft_dump_basechain_hook(struct sk_buff *skb, int family,
1452 const struct nft_base_chain *basechain)
1453{
1454 const struct nf_hook_ops *ops = &basechain->ops;
1455 struct nft_hook *hook, *first = NULL;
1456 struct nlattr *nest, *nest_devs;
1457 int n = 0;
1458
1459 nest = nla_nest_start_noflag(skb, NFTA_CHAIN_HOOK);
1460 if (nest == NULL)
1461 goto nla_put_failure;
1462 if (nla_put_be32(skb, NFTA_HOOK_HOOKNUM, htonl(ops->hooknum)))
1463 goto nla_put_failure;
1464 if (nla_put_be32(skb, NFTA_HOOK_PRIORITY, htonl(ops->priority)))
1465 goto nla_put_failure;
1466
d3519cb8 1467 if (nft_base_chain_netdev(family, ops->hooknum)) {
d54725cd
PNA
1468 nest_devs = nla_nest_start_noflag(skb, NFTA_HOOK_DEVS);
1469 list_for_each_entry(hook, &basechain->hook_list, list) {
1470 if (!first)
1471 first = hook;
1472
1473 if (nla_put_string(skb, NFTA_DEVICE_NAME,
1474 hook->ops.dev->name))
1475 goto nla_put_failure;
1476 n++;
1477 }
1478 nla_nest_end(skb, nest_devs);
1479
1480 if (n == 1 &&
1481 nla_put_string(skb, NFTA_HOOK_DEV, first->ops.dev->name))
1482 goto nla_put_failure;
1483 }
1484 nla_nest_end(skb, nest);
1485
1486 return 0;
1487nla_put_failure:
1488 return -1;
1489}
1490
84d7fce6
PNA
1491static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
1492 u32 portid, u32 seq, int event, u32 flags,
1493 int family, const struct nft_table *table,
96518518
PM
1494 const struct nft_chain *chain)
1495{
1496 struct nlmsghdr *nlh;
96518518 1497
dedb67c4 1498 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
19c28b13
PNA
1499 nlh = nfnl_msg_put(skb, portid, seq, event, flags, family,
1500 NFNETLINK_V0, nft_base_seq(net));
1501 if (!nlh)
96518518
PM
1502 goto nla_put_failure;
1503
96518518
PM
1504 if (nla_put_string(skb, NFTA_CHAIN_TABLE, table->name))
1505 goto nla_put_failure;
b46f6ded
ND
1506 if (nla_put_be64(skb, NFTA_CHAIN_HANDLE, cpu_to_be64(chain->handle),
1507 NFTA_CHAIN_PAD))
96518518
PM
1508 goto nla_put_failure;
1509 if (nla_put_string(skb, NFTA_CHAIN_NAME, chain->name))
1510 goto nla_put_failure;
1511
f323d954 1512 if (nft_is_base_chain(chain)) {
0ca743a5 1513 const struct nft_base_chain *basechain = nft_base_chain(chain);
edbd82c5 1514 struct nft_stats __percpu *stats;
0ca743a5 1515
d54725cd 1516 if (nft_dump_basechain_hook(skb, family, basechain))
2cbce139 1517 goto nla_put_failure;
9370761c 1518
0ca743a5
PNA
1519 if (nla_put_be32(skb, NFTA_CHAIN_POLICY,
1520 htonl(basechain->policy)))
1521 goto nla_put_failure;
1522
baae3e62
PM
1523 if (nla_put_string(skb, NFTA_CHAIN_TYPE, basechain->type->name))
1524 goto nla_put_failure;
0ca743a5 1525
edbd82c5
FW
1526 stats = rcu_dereference_check(basechain->stats,
1527 lockdep_commit_lock_is_held(net));
1528 if (nft_dump_stats(skb, stats))
0ca743a5 1529 goto nla_put_failure;
96518518
PM
1530 }
1531
d0e2c7de
PNA
1532 if (chain->flags &&
1533 nla_put_be32(skb, NFTA_CHAIN_FLAGS, htonl(chain->flags)))
1534 goto nla_put_failure;
1535
0ca743a5
PNA
1536 if (nla_put_be32(skb, NFTA_CHAIN_USE, htonl(chain->use)))
1537 goto nla_put_failure;
1538
002f2176
JGG
1539 if (chain->udata &&
1540 nla_put(skb, NFTA_CHAIN_USERDATA, chain->udlen, chain->udata))
1541 goto nla_put_failure;
1542
053c095a
JB
1543 nlmsg_end(skb, nlh);
1544 return 0;
96518518
PM
1545
1546nla_put_failure:
1547 nlmsg_trim(skb, nlh);
1548 return -1;
1549}
1550
25e94a99 1551static void nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
96518518 1552{
0854db2a 1553 struct nftables_pernet *nft_net;
96518518 1554 struct sk_buff *skb;
96518518
PM
1555 int err;
1556
128ad332
PNA
1557 if (!ctx->report &&
1558 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
25e94a99 1559 return;
96518518 1560
96518518
PM
1561 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
1562 if (skb == NULL)
1563 goto err;
1564
84d7fce6 1565 err = nf_tables_fill_chain_info(skb, ctx->net, ctx->portid, ctx->seq,
36596dad 1566 event, 0, ctx->family, ctx->table,
35151d84 1567 ctx->chain);
96518518
PM
1568 if (err < 0) {
1569 kfree_skb(skb);
1570 goto err;
1571 }
1572
0854db2a
FW
1573 nft_net = net_generic(ctx->net, nf_tables_net_id);
1574 nft_notify_enqueue(skb, ctx->report, &nft_net->notify_list);
25e94a99 1575 return;
96518518 1576err:
25e94a99 1577 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
96518518
PM
1578}
1579
1580static int nf_tables_dump_chains(struct sk_buff *skb,
1581 struct netlink_callback *cb)
1582{
1583 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
96518518
PM
1584 const struct nft_table *table;
1585 const struct nft_chain *chain;
1586 unsigned int idx = 0, s_idx = cb->args[0];
99633ab2 1587 struct net *net = sock_net(skb->sk);
96518518 1588 int family = nfmsg->nfgen_family;
0854db2a 1589 struct nftables_pernet *nft_net;
96518518 1590
e688a7f8 1591 rcu_read_lock();
0854db2a
FW
1592 nft_net = net_generic(net, nf_tables_net_id);
1593 cb->seq = nft_net->base_seq;
38e029f1 1594
0854db2a 1595 list_for_each_entry_rcu(table, &nft_net->tables, list) {
98319cb9 1596 if (family != NFPROTO_UNSPEC && family != table->family)
96518518
PM
1597 continue;
1598
36596dad
PNA
1599 list_for_each_entry_rcu(chain, &table->chains, list) {
1600 if (idx < s_idx)
1601 goto cont;
1602 if (idx > s_idx)
1603 memset(&cb->args[1], 0,
1604 sizeof(cb->args) - sizeof(cb->args[0]));
1605 if (!nft_is_active(net, chain))
1606 continue;
1607 if (nf_tables_fill_chain_info(skb, net,
1608 NETLINK_CB(cb->skb).portid,
1609 cb->nlh->nlmsg_seq,
1610 NFT_MSG_NEWCHAIN,
1611 NLM_F_MULTI,
98319cb9 1612 table->family, table,
36596dad
PNA
1613 chain) < 0)
1614 goto done;
38e029f1 1615
36596dad 1616 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
96518518 1617cont:
36596dad 1618 idx++;
96518518
PM
1619 }
1620 }
1621done:
e688a7f8 1622 rcu_read_unlock();
96518518
PM
1623 cb->args[0] = idx;
1624 return skb->len;
1625}
1626
d9adf22a 1627/* called with rcu_read_lock held */
7b8002a1
PNA
1628static int nf_tables_getchain(struct net *net, struct sock *nlsk,
1629 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
1630 const struct nlattr * const nla[],
1631 struct netlink_ext_ack *extack)
96518518
PM
1632{
1633 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 1634 u8 genmask = nft_genmask_cur(net);
96518518 1635 const struct nft_chain *chain;
1b2470e5 1636 struct nft_table *table;
96518518
PM
1637 struct sk_buff *skb2;
1638 int family = nfmsg->nfgen_family;
1639 int err;
1640
1641 if (nlh->nlmsg_flags & NLM_F_DUMP) {
1642 struct netlink_dump_control c = {
1643 .dump = nf_tables_dump_chains,
d9adf22a 1644 .module = THIS_MODULE,
96518518 1645 };
d9adf22a
FW
1646
1647 return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
96518518
PM
1648 }
1649
6001a930 1650 table = nft_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, genmask, 0);
36dd1bcc
PNA
1651 if (IS_ERR(table)) {
1652 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_TABLE]);
96518518 1653 return PTR_ERR(table);
36dd1bcc 1654 }
96518518 1655
f102d66b 1656 chain = nft_chain_lookup(net, table, nla[NFTA_CHAIN_NAME], genmask);
36dd1bcc
PNA
1657 if (IS_ERR(chain)) {
1658 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_NAME]);
96518518 1659 return PTR_ERR(chain);
36dd1bcc 1660 }
96518518 1661
d9adf22a 1662 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
96518518
PM
1663 if (!skb2)
1664 return -ENOMEM;
1665
84d7fce6 1666 err = nf_tables_fill_chain_info(skb2, net, NETLINK_CB(skb).portid,
96518518
PM
1667 nlh->nlmsg_seq, NFT_MSG_NEWCHAIN, 0,
1668 family, table, chain);
1669 if (err < 0)
ee921183 1670 goto err_fill_chain_info;
96518518 1671
ee921183 1672 return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
96518518 1673
ee921183 1674err_fill_chain_info:
96518518
PM
1675 kfree_skb(skb2);
1676 return err;
1677}
1678
0ca743a5
PNA
1679static const struct nla_policy nft_counter_policy[NFTA_COUNTER_MAX + 1] = {
1680 [NFTA_COUNTER_PACKETS] = { .type = NLA_U64 },
1681 [NFTA_COUNTER_BYTES] = { .type = NLA_U64 },
1682};
1683
ff3cd7b3 1684static struct nft_stats __percpu *nft_stats_alloc(const struct nlattr *attr)
0ca743a5
PNA
1685{
1686 struct nlattr *tb[NFTA_COUNTER_MAX+1];
1687 struct nft_stats __percpu *newstats;
1688 struct nft_stats *stats;
1689 int err;
1690
8cb08174
JB
1691 err = nla_parse_nested_deprecated(tb, NFTA_COUNTER_MAX, attr,
1692 nft_counter_policy, NULL);
0ca743a5 1693 if (err < 0)
ff3cd7b3 1694 return ERR_PTR(err);
0ca743a5
PNA
1695
1696 if (!tb[NFTA_COUNTER_BYTES] || !tb[NFTA_COUNTER_PACKETS])
ff3cd7b3 1697 return ERR_PTR(-EINVAL);
0ca743a5 1698
ce355e20 1699 newstats = netdev_alloc_pcpu_stats(struct nft_stats);
0ca743a5 1700 if (newstats == NULL)
ff3cd7b3 1701 return ERR_PTR(-ENOMEM);
0ca743a5
PNA
1702
1703 /* Restore old counters on this cpu, no problem. Per-cpu statistics
1704 * are not exposed to userspace.
1705 */
e8781f70 1706 preempt_disable();
0ca743a5
PNA
1707 stats = this_cpu_ptr(newstats);
1708 stats->bytes = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES]));
1709 stats->pkts = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS]));
e8781f70 1710 preempt_enable();
0ca743a5 1711
ff3cd7b3
PNA
1712 return newstats;
1713}
1714
53315ac6 1715static void nft_chain_stats_replace(struct nft_trans *trans)
ff3cd7b3 1716{
53315ac6 1717 struct nft_base_chain *chain = nft_base_chain(trans->ctx.chain);
0befd061 1718
53315ac6 1719 if (!nft_trans_chain_stats(trans))
b88825de
PNA
1720 return;
1721
b685b534
PM
1722 nft_trans_chain_stats(trans) =
1723 rcu_replace_pointer(chain->stats, nft_trans_chain_stats(trans),
1724 lockdep_commit_lock_is_held(trans->ctx.net));
53315ac6
FW
1725
1726 if (!nft_trans_chain_stats(trans))
bbb8c61f 1727 static_branch_inc(&nft_counters_enabled);
0ca743a5
PNA
1728}
1729
0cbc06b3
FW
1730static void nf_tables_chain_free_chain_rules(struct nft_chain *chain)
1731{
1732 struct nft_rule **g0 = rcu_dereference_raw(chain->rules_gen_0);
1733 struct nft_rule **g1 = rcu_dereference_raw(chain->rules_gen_1);
1734
1735 if (g0 != g1)
1736 kvfree(g1);
1737 kvfree(g0);
1738
1739 /* should be NULL either via abort or via successful commit */
1740 WARN_ON_ONCE(chain->rules_next);
1741 kvfree(chain->rules_next);
1742}
1743
d0e2c7de 1744void nf_tables_chain_destroy(struct nft_ctx *ctx)
91c7b38d 1745{
43a605f2 1746 struct nft_chain *chain = ctx->chain;
d54725cd 1747 struct nft_hook *hook, *next;
43a605f2 1748
fa5950e4
FW
1749 if (WARN_ON(chain->use > 0))
1750 return;
91c7b38d 1751
0cbc06b3
FW
1752 /* no concurrent access possible anymore */
1753 nf_tables_chain_free_chain_rules(chain);
1754
f323d954 1755 if (nft_is_base_chain(chain)) {
2cbce139
PNA
1756 struct nft_base_chain *basechain = nft_base_chain(chain);
1757
d3519cb8 1758 if (nft_base_chain_netdev(ctx->family, basechain->ops.hooknum)) {
d54725cd
PNA
1759 list_for_each_entry_safe(hook, next,
1760 &basechain->hook_list, list) {
1761 list_del_rcu(&hook->list);
1762 kfree_rcu(hook, rcu);
1763 }
1764 }
2cbce139 1765 module_put(basechain->type->owner);
4c05ec47 1766 if (rcu_access_pointer(basechain->stats)) {
9f08ea84 1767 static_branch_dec(&nft_counters_enabled);
4c05ec47
TY
1768 free_percpu(rcu_dereference_raw(basechain->stats));
1769 }
b7263e07 1770 kfree(chain->name);
002f2176 1771 kfree(chain->udata);
2cbce139 1772 kfree(basechain);
91c7b38d 1773 } else {
b7263e07 1774 kfree(chain->name);
002f2176 1775 kfree(chain->udata);
91c7b38d
PNA
1776 kfree(chain);
1777 }
1778}
1779
3f0465a9
PNA
1780static struct nft_hook *nft_netdev_hook_alloc(struct net *net,
1781 const struct nlattr *attr)
1782{
1783 struct net_device *dev;
1784 char ifname[IFNAMSIZ];
1785 struct nft_hook *hook;
1786 int err;
1787
1788 hook = kmalloc(sizeof(struct nft_hook), GFP_KERNEL);
1789 if (!hook) {
1790 err = -ENOMEM;
1791 goto err_hook_alloc;
1792 }
1793
872f6903 1794 nla_strscpy(ifname, attr, IFNAMSIZ);
42f1c271
PNA
1795 /* nf_tables_netdev_event() is called under rtnl_mutex, this is
1796 * indirectly serializing all the other holders of the commit_mutex with
1797 * the rtnl_mutex.
1798 */
3f0465a9
PNA
1799 dev = __dev_get_by_name(net, ifname);
1800 if (!dev) {
1801 err = -ENOENT;
1802 goto err_hook_dev;
1803 }
1804 hook->ops.dev = dev;
abadb2f8 1805 hook->inactive = false;
3f0465a9
PNA
1806
1807 return hook;
1808
1809err_hook_dev:
1810 kfree(hook);
1811err_hook_alloc:
1812 return ERR_PTR(err);
1813}
1814
abadb2f8
PNA
1815static struct nft_hook *nft_hook_list_find(struct list_head *hook_list,
1816 const struct nft_hook *this)
b75a3e83
PNA
1817{
1818 struct nft_hook *hook;
1819
1820 list_for_each_entry(hook, hook_list, list) {
1821 if (this->ops.dev == hook->ops.dev)
abadb2f8 1822 return hook;
b75a3e83
PNA
1823 }
1824
abadb2f8 1825 return NULL;
b75a3e83
PNA
1826}
1827
3f0465a9
PNA
1828static int nf_tables_parse_netdev_hooks(struct net *net,
1829 const struct nlattr *attr,
1830 struct list_head *hook_list)
1831{
1832 struct nft_hook *hook, *next;
1833 const struct nlattr *tmp;
1834 int rem, n = 0, err;
1835
1836 nla_for_each_nested(tmp, attr, rem) {
1837 if (nla_type(tmp) != NFTA_DEVICE_NAME) {
1838 err = -EINVAL;
1839 goto err_hook;
1840 }
1841
1842 hook = nft_netdev_hook_alloc(net, tmp);
1843 if (IS_ERR(hook)) {
1844 err = PTR_ERR(hook);
1845 goto err_hook;
1846 }
b75a3e83 1847 if (nft_hook_list_find(hook_list, hook)) {
cd77e75b 1848 kfree(hook);
b75a3e83
PNA
1849 err = -EEXIST;
1850 goto err_hook;
1851 }
3f0465a9
PNA
1852 list_add_tail(&hook->list, hook_list);
1853 n++;
1854
cb662ac6 1855 if (n == NFT_NETDEVICE_MAX) {
3f0465a9
PNA
1856 err = -EFBIG;
1857 goto err_hook;
1858 }
1859 }
3f0465a9
PNA
1860
1861 return 0;
1862
1863err_hook:
1864 list_for_each_entry_safe(hook, next, hook_list, list) {
1865 list_del(&hook->list);
1866 kfree(hook);
1867 }
1868 return err;
1869}
1870
508f8ccd
PNA
1871struct nft_chain_hook {
1872 u32 num;
84ba7dd7 1873 s32 priority;
32537e91 1874 const struct nft_chain_type *type;
d54725cd 1875 struct list_head list;
508f8ccd
PNA
1876};
1877
d54725cd
PNA
1878static int nft_chain_parse_netdev(struct net *net,
1879 struct nlattr *tb[],
1880 struct list_head *hook_list)
1881{
1882 struct nft_hook *hook;
1883 int err;
1884
1885 if (tb[NFTA_HOOK_DEV]) {
1886 hook = nft_netdev_hook_alloc(net, tb[NFTA_HOOK_DEV]);
1887 if (IS_ERR(hook))
1888 return PTR_ERR(hook);
1889
1890 list_add_tail(&hook->list, hook_list);
1891 } else if (tb[NFTA_HOOK_DEVS]) {
1892 err = nf_tables_parse_netdev_hooks(net, tb[NFTA_HOOK_DEVS],
1893 hook_list);
1894 if (err < 0)
1895 return err;
05abe445
PNA
1896
1897 if (list_empty(hook_list))
1898 return -EINVAL;
d54725cd
PNA
1899 } else {
1900 return -EINVAL;
1901 }
1902
1903 return 0;
1904}
1905
508f8ccd
PNA
1906static int nft_chain_parse_hook(struct net *net,
1907 const struct nlattr * const nla[],
36596dad 1908 struct nft_chain_hook *hook, u8 family,
445509eb 1909 bool autoload)
508f8ccd 1910{
0854db2a 1911 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
508f8ccd 1912 struct nlattr *ha[NFTA_HOOK_MAX + 1];
32537e91 1913 const struct nft_chain_type *type;
508f8ccd
PNA
1914 int err;
1915
0854db2a 1916 lockdep_assert_held(&nft_net->commit_mutex);
f102d66b
FW
1917 lockdep_nfnl_nft_mutex_not_held();
1918
8cb08174
JB
1919 err = nla_parse_nested_deprecated(ha, NFTA_HOOK_MAX,
1920 nla[NFTA_CHAIN_HOOK],
1921 nft_hook_policy, NULL);
508f8ccd
PNA
1922 if (err < 0)
1923 return err;
1924
1925 if (ha[NFTA_HOOK_HOOKNUM] == NULL ||
1926 ha[NFTA_HOOK_PRIORITY] == NULL)
1927 return -EINVAL;
1928
1929 hook->num = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
508f8ccd
PNA
1930 hook->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
1931
82603549
PNA
1932 type = __nft_chain_type_get(family, NFT_CHAIN_T_DEFAULT);
1933 if (!type)
1934 return -EOPNOTSUPP;
1935
508f8ccd 1936 if (nla[NFTA_CHAIN_TYPE]) {
452238e8 1937 type = nf_tables_chain_type_lookup(net, nla[NFTA_CHAIN_TYPE],
445509eb 1938 family, autoload);
508f8ccd
PNA
1939 if (IS_ERR(type))
1940 return PTR_ERR(type);
1941 }
d25e2e93 1942 if (hook->num >= NFT_MAX_HOOKS || !(type->hook_mask & (1 << hook->num)))
508f8ccd 1943 return -EOPNOTSUPP;
84ba7dd7
FW
1944
1945 if (type->type == NFT_CHAIN_T_NAT &&
1946 hook->priority <= NF_IP_PRI_CONNTRACK)
1947 return -EOPNOTSUPP;
1948
508f8ccd
PNA
1949 if (!try_module_get(type->owner))
1950 return -ENOENT;
1951
1952 hook->type = type;
1953
d54725cd 1954 INIT_LIST_HEAD(&hook->list);
d3519cb8 1955 if (nft_base_chain_netdev(family, hook->num)) {
d54725cd
PNA
1956 err = nft_chain_parse_netdev(net, ha, &hook->list);
1957 if (err < 0) {
508f8ccd 1958 module_put(type->owner);
d54725cd 1959 return err;
508f8ccd 1960 }
d54725cd 1961 } else if (ha[NFTA_HOOK_DEV] || ha[NFTA_HOOK_DEVS]) {
508f8ccd
PNA
1962 module_put(type->owner);
1963 return -EOPNOTSUPP;
1964 }
1965
1966 return 0;
1967}
1968
1969static void nft_chain_release_hook(struct nft_chain_hook *hook)
1970{
d54725cd
PNA
1971 struct nft_hook *h, *next;
1972
1973 list_for_each_entry_safe(h, next, &hook->list, list) {
1974 list_del(&h->list);
1975 kfree(h);
1976 }
508f8ccd 1977 module_put(hook->type->owner);
508f8ccd
PNA
1978}
1979
0cbc06b3
FW
1980struct nft_rules_old {
1981 struct rcu_head h;
1982 struct nft_rule **start;
1983};
1984
1985static struct nft_rule **nf_tables_chain_alloc_rules(const struct nft_chain *chain,
1986 unsigned int alloc)
1987{
1988 if (alloc > INT_MAX)
1989 return NULL;
1990
1991 alloc += 1; /* NULL, ends rules */
1992 if (sizeof(struct nft_rule *) > INT_MAX / alloc)
1993 return NULL;
1994
1995 alloc *= sizeof(struct nft_rule *);
1996 alloc += sizeof(struct nft_rules_old);
1997
1998 return kvmalloc(alloc, GFP_KERNEL);
1999}
2000
d54725cd
PNA
2001static void nft_basechain_hook_init(struct nf_hook_ops *ops, u8 family,
2002 const struct nft_chain_hook *hook,
2003 struct nft_chain *chain)
2004{
2005 ops->pf = family;
2006 ops->hooknum = hook->num;
2007 ops->priority = hook->priority;
2008 ops->priv = chain;
2009 ops->hook = hook->type->hooks[ops->hooknum];
2010}
2011
2012static int nft_basechain_init(struct nft_base_chain *basechain, u8 family,
2013 struct nft_chain_hook *hook, u32 flags)
2014{
2015 struct nft_chain *chain;
2016 struct nft_hook *h;
2017
2018 basechain->type = hook->type;
2019 INIT_LIST_HEAD(&basechain->hook_list);
2020 chain = &basechain->chain;
2021
d3519cb8 2022 if (nft_base_chain_netdev(family, hook->num)) {
d54725cd
PNA
2023 list_splice_init(&hook->list, &basechain->hook_list);
2024 list_for_each_entry(h, &basechain->hook_list, list)
2025 nft_basechain_hook_init(&h->ops, family, hook, chain);
2026
2027 basechain->ops.hooknum = hook->num;
2028 basechain->ops.priority = hook->priority;
2029 } else {
2030 nft_basechain_hook_init(&basechain->ops, family, hook, chain);
2031 }
2032
67c49de4 2033 chain->flags |= NFT_CHAIN_BASE | flags;
d54725cd
PNA
2034 basechain->policy = NF_ACCEPT;
2035 if (chain->flags & NFT_CHAIN_HW_OFFLOAD &&
2036 nft_chain_offload_priority(basechain) < 0)
2037 return -EOPNOTSUPP;
2038
2039 flow_block_init(&basechain->flow_block);
2040
2041 return 0;
2042}
2043
04b7db41
PNA
2044static int nft_chain_add(struct nft_table *table, struct nft_chain *chain)
2045{
2046 int err;
2047
2048 err = rhltable_insert_key(&table->chains_ht, chain->name,
2049 &chain->rhlhead, nft_chain_ht_params);
2050 if (err)
2051 return err;
2052
2053 list_add_tail_rcu(&chain->list, &table->chains);
2054
2055 return 0;
2056}
2057
d0e2c7de
PNA
2058static u64 chain_id;
2059
4035285f 2060static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
c9626a2c 2061 u8 policy, u32 flags)
4035285f
PNA
2062{
2063 const struct nlattr * const *nla = ctx->nla;
2064 struct nft_table *table = ctx->table;
4035285f
PNA
2065 struct nft_base_chain *basechain;
2066 struct nft_stats __percpu *stats;
2067 struct net *net = ctx->net;
d0e2c7de 2068 char name[NFT_NAME_MAXLEN];
66293c46 2069 struct nft_trans *trans;
4035285f 2070 struct nft_chain *chain;
0cbc06b3 2071 struct nft_rule **rules;
4035285f
PNA
2072 int err;
2073
2074 if (table->use == UINT_MAX)
2075 return -EOVERFLOW;
2076
2077 if (nla[NFTA_CHAIN_HOOK]) {
2078 struct nft_chain_hook hook;
4035285f 2079
d0e2c7de
PNA
2080 if (flags & NFT_CHAIN_BINDING)
2081 return -EOPNOTSUPP;
2082
445509eb 2083 err = nft_chain_parse_hook(net, nla, &hook, family, true);
4035285f
PNA
2084 if (err < 0)
2085 return err;
2086
2087 basechain = kzalloc(sizeof(*basechain), GFP_KERNEL);
2088 if (basechain == NULL) {
2089 nft_chain_release_hook(&hook);
2090 return -ENOMEM;
2091 }
d54725cd 2092 chain = &basechain->chain;
4035285f
PNA
2093
2094 if (nla[NFTA_CHAIN_COUNTERS]) {
2095 stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
2096 if (IS_ERR(stats)) {
2097 nft_chain_release_hook(&hook);
2098 kfree(basechain);
2099 return PTR_ERR(stats);
2100 }
4c05ec47 2101 rcu_assign_pointer(basechain->stats, stats);
4035285f
PNA
2102 static_branch_inc(&nft_counters_enabled);
2103 }
2104
d54725cd
PNA
2105 err = nft_basechain_init(basechain, family, &hook, flags);
2106 if (err < 0) {
2107 nft_chain_release_hook(&hook);
2108 kfree(basechain);
2109 return err;
2110 }
4035285f 2111 } else {
d0e2c7de
PNA
2112 if (flags & NFT_CHAIN_BASE)
2113 return -EINVAL;
2114 if (flags & NFT_CHAIN_HW_OFFLOAD)
2115 return -EOPNOTSUPP;
2116
4035285f
PNA
2117 chain = kzalloc(sizeof(*chain), GFP_KERNEL);
2118 if (chain == NULL)
2119 return -ENOMEM;
d0e2c7de
PNA
2120
2121 chain->flags = flags;
4035285f 2122 }
43a605f2
PNA
2123 ctx->chain = chain;
2124
4035285f
PNA
2125 INIT_LIST_HEAD(&chain->rules);
2126 chain->handle = nf_tables_alloc_handle(table);
2127 chain->table = table;
d0e2c7de
PNA
2128
2129 if (nla[NFTA_CHAIN_NAME]) {
2130 chain->name = nla_strdup(nla[NFTA_CHAIN_NAME], GFP_KERNEL);
2131 } else {
59136aa3
FW
2132 if (!(flags & NFT_CHAIN_BINDING)) {
2133 err = -EINVAL;
002f2176 2134 goto err_destroy_chain;
59136aa3 2135 }
d0e2c7de
PNA
2136
2137 snprintf(name, sizeof(name), "__chain%llu", ++chain_id);
2138 chain->name = kstrdup(name, GFP_KERNEL);
2139 }
2140
4035285f
PNA
2141 if (!chain->name) {
2142 err = -ENOMEM;
002f2176
JGG
2143 goto err_destroy_chain;
2144 }
2145
2146 if (nla[NFTA_CHAIN_USERDATA]) {
2147 chain->udata = nla_memdup(nla[NFTA_CHAIN_USERDATA], GFP_KERNEL);
2148 if (chain->udata == NULL) {
2149 err = -ENOMEM;
2150 goto err_destroy_chain;
2151 }
2152 chain->udlen = nla_len(nla[NFTA_CHAIN_USERDATA]);
4035285f
PNA
2153 }
2154
0cbc06b3
FW
2155 rules = nf_tables_chain_alloc_rules(chain, 0);
2156 if (!rules) {
2157 err = -ENOMEM;
002f2176 2158 goto err_destroy_chain;
0cbc06b3
FW
2159 }
2160
2161 *rules = NULL;
2162 rcu_assign_pointer(chain->rules_gen_0, rules);
2163 rcu_assign_pointer(chain->rules_gen_1, rules);
2164
c974a3a3 2165 err = nf_tables_register_hook(net, table, chain);
4035285f 2166 if (err < 0)
002f2176 2167 goto err_destroy_chain;
4035285f 2168
66293c46
FW
2169 trans = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);
2170 if (IS_ERR(trans)) {
2171 err = PTR_ERR(trans);
002f2176 2172 goto err_unregister_hook;
1b2470e5 2173 }
4035285f 2174
ad652f38 2175 nft_trans_chain_policy(trans) = NFT_CHAIN_POLICY_UNSET;
66293c46
FW
2176 if (nft_is_base_chain(chain))
2177 nft_trans_chain_policy(trans) = policy;
2178
04b7db41
PNA
2179 err = nft_chain_add(table, chain);
2180 if (err < 0) {
2181 nft_trans_destroy(trans);
002f2176 2182 goto err_unregister_hook;
04b7db41
PNA
2183 }
2184
4035285f 2185 table->use++;
4035285f
PNA
2186
2187 return 0;
002f2176 2188err_unregister_hook:
c974a3a3 2189 nf_tables_unregister_hook(net, table, chain);
002f2176 2190err_destroy_chain:
43a605f2 2191 nf_tables_chain_destroy(ctx);
4035285f
PNA
2192
2193 return err;
2194}
2195
d54725cd
PNA
2196static bool nft_hook_list_equal(struct list_head *hook_list1,
2197 struct list_head *hook_list2)
2198{
2199 struct nft_hook *hook;
2200 int n = 0, m = 0;
2201
2202 n = 0;
2203 list_for_each_entry(hook, hook_list2, list) {
2204 if (!nft_hook_list_find(hook_list1, hook))
2205 return false;
2206
2207 n++;
2208 }
2209 list_for_each_entry(hook, hook_list1, list)
2210 m++;
2211
2212 return n == m;
2213}
2214
c9626a2c 2215static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
98a381a7
PNA
2216 u32 flags, const struct nlattr *attr,
2217 struct netlink_ext_ack *extack)
2c4a488a
PNA
2218{
2219 const struct nlattr * const *nla = ctx->nla;
2220 struct nft_table *table = ctx->table;
2221 struct nft_chain *chain = ctx->chain;
2c4a488a
PNA
2222 struct nft_base_chain *basechain;
2223 struct nft_stats *stats = NULL;
2224 struct nft_chain_hook hook;
2c4a488a
PNA
2225 struct nf_hook_ops *ops;
2226 struct nft_trans *trans;
c974a3a3 2227 int err;
2c4a488a 2228
c9626a2c
PNA
2229 if (chain->flags ^ flags)
2230 return -EOPNOTSUPP;
2231
2c4a488a 2232 if (nla[NFTA_CHAIN_HOOK]) {
98a381a7
PNA
2233 if (!nft_is_base_chain(chain)) {
2234 NL_SET_BAD_ATTR(extack, attr);
77a92189 2235 return -EEXIST;
98a381a7 2236 }
36596dad 2237 err = nft_chain_parse_hook(ctx->net, nla, &hook, ctx->family,
445509eb 2238 false);
2c4a488a
PNA
2239 if (err < 0)
2240 return err;
2241
2242 basechain = nft_base_chain(chain);
2243 if (basechain->type != hook.type) {
2244 nft_chain_release_hook(&hook);
98a381a7 2245 NL_SET_BAD_ATTR(extack, attr);
77a92189 2246 return -EEXIST;
2c4a488a
PNA
2247 }
2248
d3519cb8 2249 if (nft_base_chain_netdev(ctx->family, hook.num)) {
d54725cd
PNA
2250 if (!nft_hook_list_equal(&basechain->hook_list,
2251 &hook.list)) {
2252 nft_chain_release_hook(&hook);
98a381a7 2253 NL_SET_BAD_ATTR(extack, attr);
77a92189 2254 return -EEXIST;
d54725cd
PNA
2255 }
2256 } else {
2257 ops = &basechain->ops;
2258 if (ops->hooknum != hook.num ||
2259 ops->priority != hook.priority) {
2260 nft_chain_release_hook(&hook);
98a381a7 2261 NL_SET_BAD_ATTR(extack, attr);
77a92189 2262 return -EEXIST;
d54725cd 2263 }
2c4a488a
PNA
2264 }
2265 nft_chain_release_hook(&hook);
2266 }
2267
2268 if (nla[NFTA_CHAIN_HANDLE] &&
2269 nla[NFTA_CHAIN_NAME]) {
2270 struct nft_chain *chain2;
2271
f102d66b
FW
2272 chain2 = nft_chain_lookup(ctx->net, table,
2273 nla[NFTA_CHAIN_NAME], genmask);
98a381a7
PNA
2274 if (!IS_ERR(chain2)) {
2275 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_NAME]);
0d18779b 2276 return -EEXIST;
98a381a7 2277 }
2c4a488a
PNA
2278 }
2279
2280 if (nla[NFTA_CHAIN_COUNTERS]) {
2281 if (!nft_is_base_chain(chain))
2282 return -EOPNOTSUPP;
2283
2284 stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
2285 if (IS_ERR(stats))
2286 return PTR_ERR(stats);
2287 }
2288
c6cc94df 2289 err = -ENOMEM;
2c4a488a
PNA
2290 trans = nft_trans_alloc(ctx, NFT_MSG_NEWCHAIN,
2291 sizeof(struct nft_trans_chain));
c6cc94df
FW
2292 if (trans == NULL)
2293 goto err;
2c4a488a
PNA
2294
2295 nft_trans_chain_stats(trans) = stats;
2296 nft_trans_chain_update(trans) = true;
2297
2298 if (nla[NFTA_CHAIN_POLICY])
2299 nft_trans_chain_policy(trans) = policy;
2300 else
2301 nft_trans_chain_policy(trans) = -1;
2302
c6cc94df
FW
2303 if (nla[NFTA_CHAIN_HANDLE] &&
2304 nla[NFTA_CHAIN_NAME]) {
0854db2a 2305 struct nftables_pernet *nft_net = net_generic(ctx->net, nf_tables_net_id);
c6cc94df
FW
2306 struct nft_trans *tmp;
2307 char *name;
2308
2309 err = -ENOMEM;
2310 name = nla_strdup(nla[NFTA_CHAIN_NAME], GFP_KERNEL);
2311 if (!name)
2312 goto err;
2313
2314 err = -EEXIST;
0854db2a 2315 list_for_each_entry(tmp, &nft_net->commit_list, list) {
c6cc94df
FW
2316 if (tmp->msg_type == NFT_MSG_NEWCHAIN &&
2317 tmp->ctx.table == table &&
2318 nft_trans_chain_update(tmp) &&
2319 nft_trans_chain_name(tmp) &&
2320 strcmp(name, nft_trans_chain_name(tmp)) == 0) {
98a381a7 2321 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_NAME]);
c6cc94df
FW
2322 kfree(name);
2323 goto err;
2324 }
2c4a488a 2325 }
c6cc94df
FW
2326
2327 nft_trans_chain_name(trans) = name;
2c4a488a 2328 }
0854db2a 2329 nft_trans_commit_list_add_tail(ctx->net, trans);
2c4a488a
PNA
2330
2331 return 0;
c6cc94df
FW
2332err:
2333 free_percpu(stats);
2334 kfree(trans);
2335 return err;
2c4a488a
PNA
2336}
2337
837830a4
PNA
2338static struct nft_chain *nft_chain_lookup_byid(const struct net *net,
2339 const struct nlattr *nla)
2340{
0854db2a 2341 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
837830a4
PNA
2342 u32 id = ntohl(nla_get_be32(nla));
2343 struct nft_trans *trans;
2344
0854db2a 2345 list_for_each_entry(trans, &nft_net->commit_list, list) {
837830a4
PNA
2346 struct nft_chain *chain = trans->ctx.chain;
2347
2348 if (trans->msg_type == NFT_MSG_NEWCHAIN &&
2349 id == nft_trans_chain_id(trans))
2350 return chain;
2351 }
2352 return ERR_PTR(-ENOENT);
2353}
2354
633c9a84
PNA
2355static int nf_tables_newchain(struct net *net, struct sock *nlsk,
2356 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
2357 const struct nlattr * const nla[],
2358 struct netlink_ext_ack *extack)
96518518 2359{
0854db2a 2360 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
96518518 2361 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
4035285f
PNA
2362 u8 genmask = nft_genmask_next(net);
2363 int family = nfmsg->nfgen_family;
74cccc3d 2364 struct nft_chain *chain = NULL;
36dd1bcc 2365 const struct nlattr *attr;
96518518 2366 struct nft_table *table;
57de2a0c 2367 u8 policy = NF_ACCEPT;
4035285f 2368 struct nft_ctx ctx;
96518518 2369 u64 handle = 0;
c9626a2c 2370 u32 flags = 0;
96518518 2371
0854db2a 2372 lockdep_assert_held(&nft_net->commit_mutex);
f102d66b 2373
6001a930
PNA
2374 table = nft_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, genmask,
2375 NETLINK_CB(skb).portid);
36dd1bcc
PNA
2376 if (IS_ERR(table)) {
2377 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_TABLE]);
96518518 2378 return PTR_ERR(table);
36dd1bcc 2379 }
96518518 2380
96518518 2381 chain = NULL;
36dd1bcc 2382 attr = nla[NFTA_CHAIN_NAME];
96518518
PM
2383
2384 if (nla[NFTA_CHAIN_HANDLE]) {
2385 handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE]));
cac20fcd 2386 chain = nft_chain_lookup_byhandle(table, handle, genmask);
36dd1bcc
PNA
2387 if (IS_ERR(chain)) {
2388 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_HANDLE]);
96518518 2389 return PTR_ERR(chain);
36dd1bcc
PNA
2390 }
2391 attr = nla[NFTA_CHAIN_HANDLE];
74cccc3d 2392 } else if (nla[NFTA_CHAIN_NAME]) {
f102d66b 2393 chain = nft_chain_lookup(net, table, attr, genmask);
96518518 2394 if (IS_ERR(chain)) {
36dd1bcc
PNA
2395 if (PTR_ERR(chain) != -ENOENT) {
2396 NL_SET_BAD_ATTR(extack, attr);
96518518 2397 return PTR_ERR(chain);
36dd1bcc 2398 }
96518518
PM
2399 chain = NULL;
2400 }
74cccc3d
PNA
2401 } else if (!nla[NFTA_CHAIN_ID]) {
2402 return -EINVAL;
96518518
PM
2403 }
2404
57de2a0c 2405 if (nla[NFTA_CHAIN_POLICY]) {
f323d954 2406 if (chain != NULL &&
36dd1bcc
PNA
2407 !nft_is_base_chain(chain)) {
2408 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_POLICY]);
d6b6cb1d 2409 return -EOPNOTSUPP;
36dd1bcc 2410 }
d6b6cb1d
PNA
2411
2412 if (chain == NULL &&
36dd1bcc
PNA
2413 nla[NFTA_CHAIN_HOOK] == NULL) {
2414 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_POLICY]);
57de2a0c 2415 return -EOPNOTSUPP;
36dd1bcc 2416 }
57de2a0c 2417
8f46df18 2418 policy = ntohl(nla_get_be32(nla[NFTA_CHAIN_POLICY]));
57de2a0c
PM
2419 switch (policy) {
2420 case NF_DROP:
2421 case NF_ACCEPT:
2422 break;
2423 default:
2424 return -EINVAL;
2425 }
2426 }
2427
c9626a2c
PNA
2428 if (nla[NFTA_CHAIN_FLAGS])
2429 flags = ntohl(nla_get_be32(nla[NFTA_CHAIN_FLAGS]));
b717273d
FW
2430 else if (chain)
2431 flags = chain->flags;
c9626a2c 2432
c1f79a2e
PNA
2433 if (flags & ~NFT_CHAIN_FLAGS)
2434 return -EOPNOTSUPP;
2435
98319cb9 2436 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
4035285f 2437
96518518 2438 if (chain != NULL) {
36dd1bcc
PNA
2439 if (nlh->nlmsg_flags & NLM_F_EXCL) {
2440 NL_SET_BAD_ATTR(extack, attr);
96518518 2441 return -EEXIST;
36dd1bcc 2442 }
96518518
PM
2443 if (nlh->nlmsg_flags & NLM_F_REPLACE)
2444 return -EOPNOTSUPP;
2445
67c49de4 2446 flags |= chain->flags & NFT_CHAIN_BASE;
98a381a7
PNA
2447 return nf_tables_updchain(&ctx, genmask, policy, flags, attr,
2448 extack);
96518518
PM
2449 }
2450
c9626a2c 2451 return nf_tables_addchain(&ctx, family, genmask, policy, flags);
96518518
PM
2452}
2453
633c9a84
PNA
2454static int nf_tables_delchain(struct net *net, struct sock *nlsk,
2455 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
2456 const struct nlattr * const nla[],
2457 struct netlink_ext_ack *extack)
96518518
PM
2458{
2459 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 2460 u8 genmask = nft_genmask_next(net);
36dd1bcc
PNA
2461 int family = nfmsg->nfgen_family;
2462 const struct nlattr *attr;
96518518
PM
2463 struct nft_table *table;
2464 struct nft_chain *chain;
9dee1474 2465 struct nft_rule *rule;
91c7b38d 2466 struct nft_ctx ctx;
3ecbfd65 2467 u64 handle;
9dee1474
PNA
2468 u32 use;
2469 int err;
96518518 2470
6001a930
PNA
2471 table = nft_table_lookup(net, nla[NFTA_CHAIN_TABLE], family, genmask,
2472 NETLINK_CB(skb).portid);
36dd1bcc
PNA
2473 if (IS_ERR(table)) {
2474 NL_SET_BAD_ATTR(extack, nla[NFTA_CHAIN_TABLE]);
96518518 2475 return PTR_ERR(table);
36dd1bcc 2476 }
96518518 2477
3ecbfd65 2478 if (nla[NFTA_CHAIN_HANDLE]) {
36dd1bcc
PNA
2479 attr = nla[NFTA_CHAIN_HANDLE];
2480 handle = be64_to_cpu(nla_get_be64(attr));
cac20fcd 2481 chain = nft_chain_lookup_byhandle(table, handle, genmask);
3ecbfd65 2482 } else {
36dd1bcc 2483 attr = nla[NFTA_CHAIN_NAME];
f102d66b 2484 chain = nft_chain_lookup(net, table, attr, genmask);
3ecbfd65 2485 }
36dd1bcc
PNA
2486 if (IS_ERR(chain)) {
2487 NL_SET_BAD_ATTR(extack, attr);
96518518 2488 return PTR_ERR(chain);
36dd1bcc 2489 }
9dee1474
PNA
2490
2491 if (nlh->nlmsg_flags & NLM_F_NONREC &&
2492 chain->use > 0)
96518518
PM
2493 return -EBUSY;
2494
98319cb9 2495 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
0165d932 2496
9dee1474
PNA
2497 use = chain->use;
2498 list_for_each_entry(rule, &chain->rules, list) {
2499 if (!nft_is_active_next(net, rule))
2500 continue;
2501 use--;
2502
2503 err = nft_delrule(&ctx, rule);
2504 if (err < 0)
2505 return err;
2506 }
2507
2508 /* There are rules and elements that are still holding references to us,
2509 * we cannot do a recursive removal in this case.
2510 */
36dd1bcc
PNA
2511 if (use > 0) {
2512 NL_SET_BAD_ATTR(extack, attr);
9dee1474 2513 return -EBUSY;
36dd1bcc 2514 }
9dee1474 2515
ee01d542 2516 return nft_delchain(&ctx);
96518518
PM
2517}
2518
96518518
PM
2519/*
2520 * Expressions
2521 */
2522
2523/**
ef1f7df9 2524 * nft_register_expr - register nf_tables expr type
3db86c39 2525 * @type: expr type
96518518 2526 *
ef1f7df9 2527 * Registers the expr type for use with nf_tables. Returns zero on
96518518
PM
2528 * success or a negative errno code otherwise.
2529 */
ef1f7df9 2530int nft_register_expr(struct nft_expr_type *type)
96518518
PM
2531{
2532 nfnl_lock(NFNL_SUBSYS_NFTABLES);
758dbcec 2533 if (type->family == NFPROTO_UNSPEC)
e688a7f8 2534 list_add_tail_rcu(&type->list, &nf_tables_expressions);
758dbcec 2535 else
e688a7f8 2536 list_add_rcu(&type->list, &nf_tables_expressions);
96518518
PM
2537 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
2538 return 0;
2539}
2540EXPORT_SYMBOL_GPL(nft_register_expr);
2541
2542/**
ef1f7df9 2543 * nft_unregister_expr - unregister nf_tables expr type
3db86c39 2544 * @type: expr type
96518518 2545 *
ef1f7df9 2546 * Unregisters the expr typefor use with nf_tables.
96518518 2547 */
ef1f7df9 2548void nft_unregister_expr(struct nft_expr_type *type)
96518518
PM
2549{
2550 nfnl_lock(NFNL_SUBSYS_NFTABLES);
e688a7f8 2551 list_del_rcu(&type->list);
96518518
PM
2552 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
2553}
2554EXPORT_SYMBOL_GPL(nft_unregister_expr);
2555
64d46806
PM
2556static const struct nft_expr_type *__nft_expr_type_get(u8 family,
2557 struct nlattr *nla)
96518518 2558{
9cff126f 2559 const struct nft_expr_type *type, *candidate = NULL;
96518518 2560
ef1f7df9 2561 list_for_each_entry(type, &nf_tables_expressions, list) {
9cff126f
PNA
2562 if (!nla_strcmp(nla, type->name)) {
2563 if (!type->family && !candidate)
2564 candidate = type;
2565 else if (type->family == family)
2566 candidate = type;
2567 }
96518518 2568 }
9cff126f 2569 return candidate;
96518518
PM
2570}
2571
b9c04ae7
PNA
2572#ifdef CONFIG_MODULES
2573static int nft_expr_type_request_module(struct net *net, u8 family,
2574 struct nlattr *nla)
2575{
eb014de4
PNA
2576 if (nft_request_module(net, "nft-expr-%u-%.*s", family,
2577 nla_len(nla), (char *)nla_data(nla)) == -EAGAIN)
b9c04ae7
PNA
2578 return -EAGAIN;
2579
2580 return 0;
2581}
2582#endif
2583
452238e8
FW
2584static const struct nft_expr_type *nft_expr_type_get(struct net *net,
2585 u8 family,
64d46806 2586 struct nlattr *nla)
96518518 2587{
ef1f7df9 2588 const struct nft_expr_type *type;
96518518
PM
2589
2590 if (nla == NULL)
2591 return ERR_PTR(-EINVAL);
2592
64d46806 2593 type = __nft_expr_type_get(family, nla);
ef1f7df9
PM
2594 if (type != NULL && try_module_get(type->owner))
2595 return type;
96518518 2596
f102d66b 2597 lockdep_nfnl_nft_mutex_not_held();
96518518 2598#ifdef CONFIG_MODULES
ef1f7df9 2599 if (type == NULL) {
b9c04ae7 2600 if (nft_expr_type_request_module(net, family, nla) == -EAGAIN)
64d46806
PM
2601 return ERR_PTR(-EAGAIN);
2602
eb014de4
PNA
2603 if (nft_request_module(net, "nft-expr-%.*s",
2604 nla_len(nla),
2605 (char *)nla_data(nla)) == -EAGAIN)
96518518
PM
2606 return ERR_PTR(-EAGAIN);
2607 }
2608#endif
2609 return ERR_PTR(-ENOENT);
2610}
2611
2612static const struct nla_policy nft_expr_policy[NFTA_EXPR_MAX + 1] = {
9332d27d
FW
2613 [NFTA_EXPR_NAME] = { .type = NLA_STRING,
2614 .len = NFT_MODULE_AUTOLOAD_LIMIT },
96518518
PM
2615 [NFTA_EXPR_DATA] = { .type = NLA_NESTED },
2616};
2617
2618static int nf_tables_fill_expr_info(struct sk_buff *skb,
2619 const struct nft_expr *expr)
2620{
ef1f7df9 2621 if (nla_put_string(skb, NFTA_EXPR_NAME, expr->ops->type->name))
96518518
PM
2622 goto nla_put_failure;
2623
2624 if (expr->ops->dump) {
ae0be8de
MK
2625 struct nlattr *data = nla_nest_start_noflag(skb,
2626 NFTA_EXPR_DATA);
96518518
PM
2627 if (data == NULL)
2628 goto nla_put_failure;
2629 if (expr->ops->dump(skb, expr) < 0)
2630 goto nla_put_failure;
2631 nla_nest_end(skb, data);
2632 }
2633
2634 return skb->len;
2635
2636nla_put_failure:
2637 return -1;
2638};
2639
0b2d8a7b
PM
2640int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
2641 const struct nft_expr *expr)
2642{
2643 struct nlattr *nest;
2644
ae0be8de 2645 nest = nla_nest_start_noflag(skb, attr);
0b2d8a7b
PM
2646 if (!nest)
2647 goto nla_put_failure;
2648 if (nf_tables_fill_expr_info(skb, expr) < 0)
2649 goto nla_put_failure;
2650 nla_nest_end(skb, nest);
2651 return 0;
2652
2653nla_put_failure:
2654 return -1;
2655}
2656
96518518
PM
2657struct nft_expr_info {
2658 const struct nft_expr_ops *ops;
83d9dcba 2659 const struct nlattr *attr;
ef1f7df9 2660 struct nlattr *tb[NFT_EXPR_MAXATTR + 1];
96518518
PM
2661};
2662
0ca743a5
PNA
2663static int nf_tables_expr_parse(const struct nft_ctx *ctx,
2664 const struct nlattr *nla,
96518518
PM
2665 struct nft_expr_info *info)
2666{
ef1f7df9 2667 const struct nft_expr_type *type;
96518518 2668 const struct nft_expr_ops *ops;
ef1f7df9 2669 struct nlattr *tb[NFTA_EXPR_MAX + 1];
96518518
PM
2670 int err;
2671
8cb08174
JB
2672 err = nla_parse_nested_deprecated(tb, NFTA_EXPR_MAX, nla,
2673 nft_expr_policy, NULL);
96518518
PM
2674 if (err < 0)
2675 return err;
2676
452238e8 2677 type = nft_expr_type_get(ctx->net, ctx->family, tb[NFTA_EXPR_NAME]);
ef1f7df9
PM
2678 if (IS_ERR(type))
2679 return PTR_ERR(type);
2680
2681 if (tb[NFTA_EXPR_DATA]) {
8cb08174
JB
2682 err = nla_parse_nested_deprecated(info->tb, type->maxattr,
2683 tb[NFTA_EXPR_DATA],
2684 type->policy, NULL);
ef1f7df9
PM
2685 if (err < 0)
2686 goto err1;
2687 } else
2688 memset(info->tb, 0, sizeof(info->tb[0]) * (type->maxattr + 1));
2689
2690 if (type->select_ops != NULL) {
0ca743a5
PNA
2691 ops = type->select_ops(ctx,
2692 (const struct nlattr * const *)info->tb);
ef1f7df9
PM
2693 if (IS_ERR(ops)) {
2694 err = PTR_ERR(ops);
0ef1efd1
PNA
2695#ifdef CONFIG_MODULES
2696 if (err == -EAGAIN)
eb014de4
PNA
2697 if (nft_expr_type_request_module(ctx->net,
2698 ctx->family,
2699 tb[NFTA_EXPR_NAME]) != -EAGAIN)
2700 err = -ENOENT;
0ef1efd1 2701#endif
ef1f7df9
PM
2702 goto err1;
2703 }
2704 } else
2705 ops = type->ops;
2706
83d9dcba 2707 info->attr = nla;
96518518 2708 info->ops = ops;
83d9dcba 2709
96518518 2710 return 0;
ef1f7df9
PM
2711
2712err1:
2713 module_put(type->owner);
2714 return err;
96518518
PM
2715}
2716
2717static int nf_tables_newexpr(const struct nft_ctx *ctx,
ef1f7df9 2718 const struct nft_expr_info *info,
96518518
PM
2719 struct nft_expr *expr)
2720{
2721 const struct nft_expr_ops *ops = info->ops;
2722 int err;
2723
2724 expr->ops = ops;
2725 if (ops->init) {
ef1f7df9 2726 err = ops->init(ctx, expr, (const struct nlattr **)info->tb);
96518518
PM
2727 if (err < 0)
2728 goto err1;
2729 }
2730
96518518 2731 return 0;
96518518
PM
2732err1:
2733 expr->ops = NULL;
2734 return err;
2735}
2736
62472bce
PM
2737static void nf_tables_expr_destroy(const struct nft_ctx *ctx,
2738 struct nft_expr *expr)
96518518 2739{
3f3a390d
PNA
2740 const struct nft_expr_type *type = expr->ops->type;
2741
96518518 2742 if (expr->ops->destroy)
62472bce 2743 expr->ops->destroy(ctx, expr);
3f3a390d 2744 module_put(type->owner);
96518518
PM
2745}
2746
795a6d6b
PNA
2747static struct nft_expr *nft_expr_init(const struct nft_ctx *ctx,
2748 const struct nlattr *nla)
0b2d8a7b
PM
2749{
2750 struct nft_expr_info info;
2751 struct nft_expr *expr;
b8e20400 2752 struct module *owner;
0b2d8a7b
PM
2753 int err;
2754
2755 err = nf_tables_expr_parse(ctx, nla, &info);
2756 if (err < 0)
2757 goto err1;
2758
2759 err = -ENOMEM;
2760 expr = kzalloc(info.ops->size, GFP_KERNEL);
2761 if (expr == NULL)
2762 goto err2;
2763
2764 err = nf_tables_newexpr(ctx, &info, expr);
2765 if (err < 0)
6cafaf47 2766 goto err3;
0b2d8a7b
PM
2767
2768 return expr;
6cafaf47
LZ
2769err3:
2770 kfree(expr);
0b2d8a7b 2771err2:
b8e20400
PNA
2772 owner = info.ops->type->owner;
2773 if (info.ops->type->release_ops)
2774 info.ops->type->release_ops(info.ops);
2775
2776 module_put(owner);
0b2d8a7b
PM
2777err1:
2778 return ERR_PTR(err);
2779}
2780
c604cc69
PNA
2781int nft_expr_clone(struct nft_expr *dst, struct nft_expr *src)
2782{
2783 int err;
2784
2785 if (src->ops->clone) {
2786 dst->ops = src->ops;
2787 err = src->ops->clone(dst, src);
2788 if (err < 0)
2789 return err;
2790 } else {
2791 memcpy(dst, src, src->ops->size);
2792 }
2793
2794 __module_get(src->ops->type->owner);
2795
2796 return 0;
2797}
2798
0b2d8a7b
PM
2799void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr)
2800{
2801 nf_tables_expr_destroy(ctx, expr);
2802 kfree(expr);
2803}
2804
96518518
PM
2805/*
2806 * Rules
2807 */
2808
cac20fcd
PNA
2809static struct nft_rule *__nft_rule_lookup(const struct nft_chain *chain,
2810 u64 handle)
96518518
PM
2811{
2812 struct nft_rule *rule;
2813
2814 // FIXME: this sucks
d9adf22a 2815 list_for_each_entry_rcu(rule, &chain->rules, list) {
96518518
PM
2816 if (handle == rule->handle)
2817 return rule;
2818 }
2819
2820 return ERR_PTR(-ENOENT);
2821}
2822
cac20fcd
PNA
2823static struct nft_rule *nft_rule_lookup(const struct nft_chain *chain,
2824 const struct nlattr *nla)
96518518
PM
2825{
2826 if (nla == NULL)
2827 return ERR_PTR(-EINVAL);
2828
cac20fcd 2829 return __nft_rule_lookup(chain, be64_to_cpu(nla_get_be64(nla)));
96518518
PM
2830}
2831
2832static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
b2fbd044
LZ
2833 [NFTA_RULE_TABLE] = { .type = NLA_STRING,
2834 .len = NFT_TABLE_MAXNAMELEN - 1 },
96518518
PM
2835 [NFTA_RULE_CHAIN] = { .type = NLA_STRING,
2836 .len = NFT_CHAIN_MAXNAMELEN - 1 },
2837 [NFTA_RULE_HANDLE] = { .type = NLA_U64 },
2838 [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED },
0ca743a5 2839 [NFTA_RULE_COMPAT] = { .type = NLA_NESTED },
5e948466 2840 [NFTA_RULE_POSITION] = { .type = NLA_U64 },
0768b3b3
PNA
2841 [NFTA_RULE_USERDATA] = { .type = NLA_BINARY,
2842 .len = NFT_USERDATA_MAXLEN },
467697d2 2843 [NFTA_RULE_ID] = { .type = NLA_U32 },
0604628b 2844 [NFTA_RULE_POSITION_ID] = { .type = NLA_U32 },
837830a4 2845 [NFTA_RULE_CHAIN_ID] = { .type = NLA_U32 },
96518518
PM
2846};
2847
84d7fce6
PNA
2848static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
2849 u32 portid, u32 seq, int event,
2850 u32 flags, int family,
96518518
PM
2851 const struct nft_table *table,
2852 const struct nft_chain *chain,
2c82c7e7
FW
2853 const struct nft_rule *rule,
2854 const struct nft_rule *prule)
96518518
PM
2855{
2856 struct nlmsghdr *nlh;
96518518
PM
2857 const struct nft_expr *expr, *next;
2858 struct nlattr *list;
dedb67c4 2859 u16 type = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
96518518 2860
19c28b13
PNA
2861 nlh = nfnl_msg_put(skb, portid, seq, type, flags, family, NFNETLINK_V0,
2862 nft_base_seq(net));
2863 if (!nlh)
96518518
PM
2864 goto nla_put_failure;
2865
96518518
PM
2866 if (nla_put_string(skb, NFTA_RULE_TABLE, table->name))
2867 goto nla_put_failure;
2868 if (nla_put_string(skb, NFTA_RULE_CHAIN, chain->name))
2869 goto nla_put_failure;
b46f6ded
ND
2870 if (nla_put_be64(skb, NFTA_RULE_HANDLE, cpu_to_be64(rule->handle),
2871 NFTA_RULE_PAD))
96518518
PM
2872 goto nla_put_failure;
2873
2c82c7e7 2874 if (event != NFT_MSG_DELRULE && prule) {
5e948466 2875 if (nla_put_be64(skb, NFTA_RULE_POSITION,
b46f6ded
ND
2876 cpu_to_be64(prule->handle),
2877 NFTA_RULE_PAD))
5e948466
EL
2878 goto nla_put_failure;
2879 }
2880
b72920f6
PNA
2881 if (chain->flags & NFT_CHAIN_HW_OFFLOAD)
2882 nft_flow_rule_stats(chain, rule);
2883
ae0be8de 2884 list = nla_nest_start_noflag(skb, NFTA_RULE_EXPRESSIONS);
96518518
PM
2885 if (list == NULL)
2886 goto nla_put_failure;
2887 nft_rule_for_each_expr(expr, next, rule) {
0b2d8a7b 2888 if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr) < 0)
96518518 2889 goto nla_put_failure;
96518518
PM
2890 }
2891 nla_nest_end(skb, list);
2892
86f1ec32
PM
2893 if (rule->udata) {
2894 struct nft_userdata *udata = nft_userdata(rule);
2895 if (nla_put(skb, NFTA_RULE_USERDATA, udata->len + 1,
2896 udata->data) < 0)
2897 goto nla_put_failure;
2898 }
0768b3b3 2899
053c095a
JB
2900 nlmsg_end(skb, nlh);
2901 return 0;
96518518
PM
2902
2903nla_put_failure:
2904 nlmsg_trim(skb, nlh);
2905 return -1;
2906}
2907
25e94a99
PNA
2908static void nf_tables_rule_notify(const struct nft_ctx *ctx,
2909 const struct nft_rule *rule, int event)
96518518 2910{
0854db2a 2911 struct nftables_pernet *nft_net = net_generic(ctx->net, nf_tables_net_id);
96518518 2912 struct sk_buff *skb;
96518518
PM
2913 int err;
2914
128ad332
PNA
2915 if (!ctx->report &&
2916 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
25e94a99 2917 return;
96518518 2918
96518518
PM
2919 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
2920 if (skb == NULL)
2921 goto err;
2922
84d7fce6 2923 err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq,
36596dad 2924 event, 0, ctx->family, ctx->table,
2c82c7e7 2925 ctx->chain, rule, NULL);
96518518
PM
2926 if (err < 0) {
2927 kfree_skb(skb);
2928 goto err;
2929 }
2930
0854db2a 2931 nft_notify_enqueue(skb, ctx->report, &nft_net->notify_list);
25e94a99 2932 return;
96518518 2933err:
25e94a99 2934 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
96518518
PM
2935}
2936
6e1f760e 2937struct nft_rule_dump_ctx {
e46abbcc 2938 char *table;
b7263e07 2939 char *chain;
6e1f760e
PNA
2940};
2941
241faece
PS
2942static int __nf_tables_dump_rules(struct sk_buff *skb,
2943 unsigned int *idx,
2944 struct netlink_callback *cb,
2945 const struct nft_table *table,
2946 const struct nft_chain *chain)
2947{
2948 struct net *net = sock_net(skb->sk);
2c82c7e7 2949 const struct nft_rule *rule, *prule;
241faece 2950 unsigned int s_idx = cb->args[0];
241faece 2951
2c82c7e7 2952 prule = NULL;
241faece
PS
2953 list_for_each_entry_rcu(rule, &chain->rules, list) {
2954 if (!nft_is_active(net, rule))
2c82c7e7 2955 goto cont_skip;
241faece
PS
2956 if (*idx < s_idx)
2957 goto cont;
2958 if (*idx > s_idx) {
2959 memset(&cb->args[1], 0,
2960 sizeof(cb->args) - sizeof(cb->args[0]));
2961 }
2962 if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid,
2963 cb->nlh->nlmsg_seq,
2964 NFT_MSG_NEWRULE,
2965 NLM_F_MULTI | NLM_F_APPEND,
2966 table->family,
2c82c7e7 2967 table, chain, rule, prule) < 0)
310529e6 2968 return 1;
241faece
PS
2969
2970 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
2971cont:
2c82c7e7
FW
2972 prule = rule;
2973cont_skip:
241faece
PS
2974 (*idx)++;
2975 }
310529e6 2976 return 0;
241faece
PS
2977}
2978
96518518
PM
2979static int nf_tables_dump_rules(struct sk_buff *skb,
2980 struct netlink_callback *cb)
2981{
2982 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
6e1f760e 2983 const struct nft_rule_dump_ctx *ctx = cb->data;
241faece 2984 struct nft_table *table;
96518518 2985 const struct nft_chain *chain;
241faece 2986 unsigned int idx = 0;
99633ab2 2987 struct net *net = sock_net(skb->sk);
96518518 2988 int family = nfmsg->nfgen_family;
0854db2a 2989 struct nftables_pernet *nft_net;
96518518 2990
e688a7f8 2991 rcu_read_lock();
0854db2a
FW
2992 nft_net = net_generic(net, nf_tables_net_id);
2993 cb->seq = nft_net->base_seq;
38e029f1 2994
0854db2a 2995 list_for_each_entry_rcu(table, &nft_net->tables, list) {
98319cb9 2996 if (family != NFPROTO_UNSPEC && family != table->family)
36596dad
PNA
2997 continue;
2998
2999 if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0)
96518518
PM
3000 continue;
3001
715849ab 3002 if (ctx && ctx->table && ctx->chain) {
241faece 3003 struct rhlist_head *list, *tmp;
6e1f760e 3004
241faece
PS
3005 list = rhltable_lookup(&table->chains_ht, ctx->chain,
3006 nft_chain_ht_params);
3007 if (!list)
3008 goto done;
3009
3010 rhl_for_each_entry_rcu(chain, tmp, list, rhlhead) {
3011 if (!nft_is_active(net, chain))
3012 continue;
3013 __nf_tables_dump_rules(skb, &idx,
3014 cb, table, chain);
3015 break;
96518518 3016 }
241faece 3017 goto done;
96518518 3018 }
241faece
PS
3019
3020 list_for_each_entry_rcu(chain, &table->chains, list) {
3021 if (__nf_tables_dump_rules(skb, &idx, cb, table, chain))
3022 goto done;
3023 }
3024
3025 if (ctx && ctx->table)
3026 break;
96518518
PM
3027 }
3028done:
e688a7f8 3029 rcu_read_unlock();
310529e6
PS
3030
3031 cb->args[0] = idx;
96518518
PM
3032 return skb->len;
3033}
3034
90fd131a
FW
3035static int nf_tables_dump_rules_start(struct netlink_callback *cb)
3036{
3037 const struct nlattr * const *nla = cb->data;
3038 struct nft_rule_dump_ctx *ctx = NULL;
3039
3040 if (nla[NFTA_RULE_TABLE] || nla[NFTA_RULE_CHAIN]) {
3041 ctx = kzalloc(sizeof(*ctx), GFP_ATOMIC);
3042 if (!ctx)
3043 return -ENOMEM;
3044
3045 if (nla[NFTA_RULE_TABLE]) {
3046 ctx->table = nla_strdup(nla[NFTA_RULE_TABLE],
3047 GFP_ATOMIC);
3048 if (!ctx->table) {
3049 kfree(ctx);
3050 return -ENOMEM;
3051 }
3052 }
3053 if (nla[NFTA_RULE_CHAIN]) {
3054 ctx->chain = nla_strdup(nla[NFTA_RULE_CHAIN],
3055 GFP_ATOMIC);
3056 if (!ctx->chain) {
3057 kfree(ctx->table);
3058 kfree(ctx);
3059 return -ENOMEM;
3060 }
3061 }
3062 }
3063
3064 cb->data = ctx;
3065 return 0;
3066}
3067
6e1f760e
PNA
3068static int nf_tables_dump_rules_done(struct netlink_callback *cb)
3069{
e46abbcc
PS
3070 struct nft_rule_dump_ctx *ctx = cb->data;
3071
3072 if (ctx) {
3073 kfree(ctx->table);
b7263e07 3074 kfree(ctx->chain);
e46abbcc
PS
3075 kfree(ctx);
3076 }
6e1f760e
PNA
3077 return 0;
3078}
3079
d9adf22a 3080/* called with rcu_read_lock held */
7b8002a1
PNA
3081static int nf_tables_getrule(struct net *net, struct sock *nlsk,
3082 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
3083 const struct nlattr * const nla[],
3084 struct netlink_ext_ack *extack)
96518518
PM
3085{
3086 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 3087 u8 genmask = nft_genmask_cur(net);
96518518
PM
3088 const struct nft_chain *chain;
3089 const struct nft_rule *rule;
1b2470e5 3090 struct nft_table *table;
96518518
PM
3091 struct sk_buff *skb2;
3092 int family = nfmsg->nfgen_family;
3093 int err;
3094
3095 if (nlh->nlmsg_flags & NLM_F_DUMP) {
3096 struct netlink_dump_control c = {
90fd131a 3097 .start= nf_tables_dump_rules_start,
96518518 3098 .dump = nf_tables_dump_rules,
6e1f760e 3099 .done = nf_tables_dump_rules_done,
d9adf22a 3100 .module = THIS_MODULE,
90fd131a 3101 .data = (void *)nla,
96518518 3102 };
6e1f760e 3103
d9adf22a 3104 return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
96518518
PM
3105 }
3106
6001a930 3107 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask, 0);
36dd1bcc
PNA
3108 if (IS_ERR(table)) {
3109 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]);
96518518 3110 return PTR_ERR(table);
36dd1bcc 3111 }
96518518 3112
f102d66b 3113 chain = nft_chain_lookup(net, table, nla[NFTA_RULE_CHAIN], genmask);
36dd1bcc
PNA
3114 if (IS_ERR(chain)) {
3115 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
96518518 3116 return PTR_ERR(chain);
36dd1bcc 3117 }
96518518 3118
cac20fcd 3119 rule = nft_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
36dd1bcc
PNA
3120 if (IS_ERR(rule)) {
3121 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]);
96518518 3122 return PTR_ERR(rule);
36dd1bcc 3123 }
96518518 3124
d9adf22a 3125 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
96518518
PM
3126 if (!skb2)
3127 return -ENOMEM;
3128
84d7fce6 3129 err = nf_tables_fill_rule_info(skb2, net, NETLINK_CB(skb).portid,
96518518 3130 nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
2c82c7e7 3131 family, table, chain, rule, NULL);
96518518 3132 if (err < 0)
ee921183 3133 goto err_fill_rule_info;
96518518 3134
ee921183 3135 return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
96518518 3136
ee921183 3137err_fill_rule_info:
96518518
PM
3138 kfree_skb(skb2);
3139 return err;
3140}
3141
62472bce
PM
3142static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
3143 struct nft_rule *rule)
96518518 3144{
29e38801 3145 struct nft_expr *expr, *next;
96518518
PM
3146
3147 /*
3148 * Careful: some expressions might not be initialized in case this
3149 * is called on error from nf_tables_newrule().
3150 */
3151 expr = nft_expr_first(rule);
31cc578a 3152 while (nft_expr_more(rule, expr)) {
29e38801 3153 next = nft_expr_next(expr);
62472bce 3154 nf_tables_expr_destroy(ctx, expr);
29e38801 3155 expr = next;
96518518
PM
3156 }
3157 kfree(rule);
3158}
3159
d0e2c7de 3160void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
bb7b40ae 3161{
f6ac8585 3162 nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
bb7b40ae
PNA
3163 nf_tables_rule_destroy(ctx, rule);
3164}
3165
a654de8f
PNA
3166int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
3167{
3168 struct nft_expr *expr, *last;
3169 const struct nft_data *data;
3170 struct nft_rule *rule;
3171 int err;
3172
26b2f552
TY
3173 if (ctx->level == NFT_JUMP_STACK_SIZE)
3174 return -EMLINK;
3175
a654de8f
PNA
3176 list_for_each_entry(rule, &chain->rules, list) {
3177 if (!nft_is_active_next(ctx->net, rule))
3178 continue;
3179
3180 nft_rule_for_each_expr(expr, last, rule) {
3181 if (!expr->ops->validate)
3182 continue;
3183
3184 err = expr->ops->validate(ctx, expr, &data);
3185 if (err < 0)
3186 return err;
3187 }
3188 }
3189
3190 return 0;
3191}
3192EXPORT_SYMBOL_GPL(nft_chain_validate);
3193
3194static int nft_table_validate(struct net *net, const struct nft_table *table)
3195{
3196 struct nft_chain *chain;
3197 struct nft_ctx ctx = {
3198 .net = net,
3199 .family = table->family,
3200 };
3201 int err;
3202
3203 list_for_each_entry(chain, &table->chains, list) {
3204 if (!nft_is_base_chain(chain))
3205 continue;
3206
3207 ctx.chain = chain;
3208 err = nft_chain_validate(&ctx, chain);
3209 if (err < 0)
3210 return err;
3211 }
3212
3213 return 0;
3214}
3215
75dd48e2
PS
3216static struct nft_rule *nft_rule_lookup_byid(const struct net *net,
3217 const struct nlattr *nla);
3218
1081d11b
PNA
3219#define NFT_RULE_MAXEXPRS 128
3220
633c9a84
PNA
3221static int nf_tables_newrule(struct net *net, struct sock *nlsk,
3222 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
3223 const struct nlattr * const nla[],
3224 struct netlink_ext_ack *extack)
96518518 3225{
0854db2a 3226 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
96518518 3227 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 3228 u8 genmask = nft_genmask_next(net);
2a43ecf9 3229 struct nft_expr_info *info = NULL;
98319cb9 3230 int family = nfmsg->nfgen_family;
c9626a2c 3231 struct nft_flow_rule *flow;
96518518
PM
3232 struct nft_table *table;
3233 struct nft_chain *chain;
3234 struct nft_rule *rule, *old_rule = NULL;
86f1ec32 3235 struct nft_userdata *udata;
1081d11b 3236 struct nft_trans *trans = NULL;
96518518
PM
3237 struct nft_expr *expr;
3238 struct nft_ctx ctx;
3239 struct nlattr *tmp;
86f1ec32 3240 unsigned int size, i, n, ulen = 0, usize = 0;
96518518 3241 int err, rem;
5e948466 3242 u64 handle, pos_handle;
96518518 3243
0854db2a 3244 lockdep_assert_held(&nft_net->commit_mutex);
f102d66b 3245
6001a930
PNA
3246 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask,
3247 NETLINK_CB(skb).portid);
36dd1bcc
PNA
3248 if (IS_ERR(table)) {
3249 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]);
96518518 3250 return PTR_ERR(table);
36dd1bcc 3251 }
96518518 3252
837830a4
PNA
3253 if (nla[NFTA_RULE_CHAIN]) {
3254 chain = nft_chain_lookup(net, table, nla[NFTA_RULE_CHAIN],
3255 genmask);
3256 if (IS_ERR(chain)) {
3257 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
3258 return PTR_ERR(chain);
3259 }
d0e2c7de
PNA
3260 if (nft_chain_is_bound(chain))
3261 return -EOPNOTSUPP;
3262
837830a4
PNA
3263 } else if (nla[NFTA_RULE_CHAIN_ID]) {
3264 chain = nft_chain_lookup_byid(net, nla[NFTA_RULE_CHAIN_ID]);
3265 if (IS_ERR(chain)) {
3266 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN_ID]);
3267 return PTR_ERR(chain);
3268 }
3269 } else {
3270 return -EINVAL;
36dd1bcc 3271 }
96518518
PM
3272
3273 if (nla[NFTA_RULE_HANDLE]) {
3274 handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_HANDLE]));
cac20fcd 3275 rule = __nft_rule_lookup(chain, handle);
36dd1bcc
PNA
3276 if (IS_ERR(rule)) {
3277 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]);
96518518 3278 return PTR_ERR(rule);
36dd1bcc 3279 }
96518518 3280
36dd1bcc
PNA
3281 if (nlh->nlmsg_flags & NLM_F_EXCL) {
3282 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]);
96518518 3283 return -EEXIST;
36dd1bcc 3284 }
96518518
PM
3285 if (nlh->nlmsg_flags & NLM_F_REPLACE)
3286 old_rule = rule;
3287 else
3288 return -EOPNOTSUPP;
3289 } else {
445509eb
PNA
3290 if (!(nlh->nlmsg_flags & NLM_F_CREATE) ||
3291 nlh->nlmsg_flags & NLM_F_REPLACE)
96518518
PM
3292 return -EINVAL;
3293 handle = nf_tables_alloc_handle(table);
a0a7379e
PNA
3294
3295 if (chain->use == UINT_MAX)
3296 return -EOVERFLOW;
5e948466 3297
447750f2
FW
3298 if (nla[NFTA_RULE_POSITION]) {
3299 pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION]));
3300 old_rule = __nft_rule_lookup(chain, pos_handle);
3301 if (IS_ERR(old_rule)) {
3302 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_POSITION]);
3303 return PTR_ERR(old_rule);
3304 }
75dd48e2
PS
3305 } else if (nla[NFTA_RULE_POSITION_ID]) {
3306 old_rule = nft_rule_lookup_byid(net, nla[NFTA_RULE_POSITION_ID]);
3307 if (IS_ERR(old_rule)) {
3308 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_POSITION_ID]);
3309 return PTR_ERR(old_rule);
3310 }
36dd1bcc 3311 }
5e948466
EL
3312 }
3313
98319cb9 3314 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
0ca743a5 3315
96518518
PM
3316 n = 0;
3317 size = 0;
3318 if (nla[NFTA_RULE_EXPRESSIONS]) {
2a43ecf9
FW
3319 info = kvmalloc_array(NFT_RULE_MAXEXPRS,
3320 sizeof(struct nft_expr_info),
3321 GFP_KERNEL);
3322 if (!info)
3323 return -ENOMEM;
3324
96518518
PM
3325 nla_for_each_nested(tmp, nla[NFTA_RULE_EXPRESSIONS], rem) {
3326 err = -EINVAL;
3327 if (nla_type(tmp) != NFTA_LIST_ELEM)
3328 goto err1;
3329 if (n == NFT_RULE_MAXEXPRS)
3330 goto err1;
0ca743a5 3331 err = nf_tables_expr_parse(&ctx, tmp, &info[n]);
96518518
PM
3332 if (err < 0)
3333 goto err1;
3334 size += info[n].ops->size;
3335 n++;
3336 }
3337 }
9889840f
PM
3338 /* Check for overflow of dlen field */
3339 err = -EFBIG;
3340 if (size >= 1 << 12)
3341 goto err1;
96518518 3342
86f1ec32 3343 if (nla[NFTA_RULE_USERDATA]) {
0768b3b3 3344 ulen = nla_len(nla[NFTA_RULE_USERDATA]);
86f1ec32
PM
3345 if (ulen > 0)
3346 usize = sizeof(struct nft_userdata) + ulen;
3347 }
0768b3b3 3348
96518518 3349 err = -ENOMEM;
86f1ec32 3350 rule = kzalloc(sizeof(*rule) + size + usize, GFP_KERNEL);
96518518
PM
3351 if (rule == NULL)
3352 goto err1;
3353
889f7ee7 3354 nft_activate_next(net, rule);
0628b123 3355
96518518
PM
3356 rule->handle = handle;
3357 rule->dlen = size;
86f1ec32 3358 rule->udata = ulen ? 1 : 0;
0768b3b3 3359
86f1ec32
PM
3360 if (ulen) {
3361 udata = nft_userdata(rule);
3362 udata->len = ulen - 1;
3363 nla_memcpy(udata->data, nla[NFTA_RULE_USERDATA], ulen);
3364 }
96518518 3365
96518518
PM
3366 expr = nft_expr_first(rule);
3367 for (i = 0; i < n; i++) {
3368 err = nf_tables_newexpr(&ctx, &info[i], expr);
83d9dcba
PNA
3369 if (err < 0) {
3370 NL_SET_BAD_ATTR(extack, info[i].attr);
96518518 3371 goto err2;
83d9dcba 3372 }
a654de8f
PNA
3373
3374 if (info[i].ops->validate)
3375 nft_validate_state_update(net, NFT_VALIDATE_NEED);
3376
ef1f7df9 3377 info[i].ops = NULL;
96518518
PM
3378 expr = nft_expr_next(expr);
3379 }
3380
96518518 3381 if (nlh->nlmsg_flags & NLM_F_REPLACE) {
ca089878 3382 trans = nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule);
569ccae6
FW
3383 if (trans == NULL) {
3384 err = -ENOMEM;
3385 goto err2;
3386 }
ca089878
TY
3387 err = nft_delrule(&ctx, old_rule);
3388 if (err < 0) {
3389 nft_trans_destroy(trans);
569ccae6
FW
3390 goto err2;
3391 }
3392
3393 list_add_tail_rcu(&rule->list, &old_rule->list);
3394 } else {
c9626a2c
PNA
3395 trans = nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule);
3396 if (!trans) {
569ccae6
FW
3397 err = -ENOMEM;
3398 goto err2;
3399 }
3400
3401 if (nlh->nlmsg_flags & NLM_F_APPEND) {
3402 if (old_rule)
3403 list_add_rcu(&rule->list, &old_rule->list);
3404 else
3405 list_add_tail_rcu(&rule->list, &chain->rules);
3406 } else {
3407 if (old_rule)
3408 list_add_tail_rcu(&rule->list, &old_rule->list);
3409 else
3410 list_add_rcu(&rule->list, &chain->rules);
3411 }
0628b123 3412 }
2a43ecf9 3413 kvfree(info);
4fefee57 3414 chain->use++;
96518518 3415
0854db2a 3416 if (nft_net->validate_state == NFT_VALIDATE_DO)
a654de8f
PNA
3417 return nft_table_validate(net, table);
3418
c9626a2c 3419 if (chain->flags & NFT_CHAIN_HW_OFFLOAD) {
be2861dc 3420 flow = nft_flow_rule_create(net, rule);
c9626a2c
PNA
3421 if (IS_ERR(flow))
3422 return PTR_ERR(flow);
3423
3424 nft_trans_flow_rule(trans) = flow;
3425 }
3426
a654de8f 3427 return 0;
96518518 3428err2:
bb7b40ae 3429 nf_tables_rule_release(&ctx, rule);
96518518
PM
3430err1:
3431 for (i = 0; i < n; i++) {
b25a31bf 3432 if (info[i].ops) {
ef1f7df9 3433 module_put(info[i].ops->type->owner);
b25a31bf
TY
3434 if (info[i].ops->type->release_ops)
3435 info[i].ops->type->release_ops(info[i].ops);
3436 }
96518518 3437 }
2a43ecf9 3438 kvfree(info);
96518518
PM
3439 return err;
3440}
3441
1a94e38d
PNA
3442static struct nft_rule *nft_rule_lookup_byid(const struct net *net,
3443 const struct nlattr *nla)
3444{
0854db2a 3445 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
1a94e38d
PNA
3446 u32 id = ntohl(nla_get_be32(nla));
3447 struct nft_trans *trans;
3448
0854db2a 3449 list_for_each_entry(trans, &nft_net->commit_list, list) {
1a94e38d
PNA
3450 struct nft_rule *rule = nft_trans_rule(trans);
3451
3452 if (trans->msg_type == NFT_MSG_NEWRULE &&
3453 id == nft_trans_rule_id(trans))
3454 return rule;
3455 }
3456 return ERR_PTR(-ENOENT);
3457}
3458
633c9a84
PNA
3459static int nf_tables_delrule(struct net *net, struct sock *nlsk,
3460 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
3461 const struct nlattr * const nla[],
3462 struct netlink_ext_ack *extack)
96518518
PM
3463{
3464 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 3465 u8 genmask = nft_genmask_next(net);
7c95f6d8 3466 struct nft_table *table;
cf9dc09d
PNA
3467 struct nft_chain *chain = NULL;
3468 struct nft_rule *rule;
0628b123
PNA
3469 int family = nfmsg->nfgen_family, err = 0;
3470 struct nft_ctx ctx;
96518518 3471
6001a930
PNA
3472 table = nft_table_lookup(net, nla[NFTA_RULE_TABLE], family, genmask,
3473 NETLINK_CB(skb).portid);
36dd1bcc
PNA
3474 if (IS_ERR(table)) {
3475 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_TABLE]);
96518518 3476 return PTR_ERR(table);
36dd1bcc 3477 }
96518518 3478
cf9dc09d 3479 if (nla[NFTA_RULE_CHAIN]) {
f102d66b
FW
3480 chain = nft_chain_lookup(net, table, nla[NFTA_RULE_CHAIN],
3481 genmask);
36dd1bcc
PNA
3482 if (IS_ERR(chain)) {
3483 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
cf9dc09d 3484 return PTR_ERR(chain);
36dd1bcc 3485 }
d0e2c7de
PNA
3486 if (nft_chain_is_bound(chain))
3487 return -EOPNOTSUPP;
cf9dc09d 3488 }
96518518 3489
98319cb9 3490 nft_ctx_init(&ctx, net, skb, nlh, family, table, chain, nla);
0628b123 3491
cf9dc09d
PNA
3492 if (chain) {
3493 if (nla[NFTA_RULE_HANDLE]) {
cac20fcd 3494 rule = nft_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
36dd1bcc
PNA
3495 if (IS_ERR(rule)) {
3496 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]);
cf9dc09d 3497 return PTR_ERR(rule);
36dd1bcc 3498 }
96518518 3499
1a94e38d
PNA
3500 err = nft_delrule(&ctx, rule);
3501 } else if (nla[NFTA_RULE_ID]) {
3502 rule = nft_rule_lookup_byid(net, nla[NFTA_RULE_ID]);
36dd1bcc
PNA
3503 if (IS_ERR(rule)) {
3504 NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_ID]);
1a94e38d 3505 return PTR_ERR(rule);
36dd1bcc 3506 }
1a94e38d 3507
5e266fe7 3508 err = nft_delrule(&ctx, rule);
cf9dc09d 3509 } else {
ce24b721 3510 err = nft_delrule_by_chain(&ctx);
cf9dc09d
PNA
3511 }
3512 } else {
3513 list_for_each_entry(chain, &table->chains, list) {
664b0f8c
PNA
3514 if (!nft_is_active_next(net, chain))
3515 continue;
3516
cf9dc09d 3517 ctx.chain = chain;
ce24b721 3518 err = nft_delrule_by_chain(&ctx);
0628b123
PNA
3519 if (err < 0)
3520 break;
3521 }
3522 }
3523
3524 return err;
3525}
3526
20a69341
PM
3527/*
3528 * Sets
3529 */
e32a4dc6
FW
3530static const struct nft_set_type *nft_set_types[] = {
3531 &nft_set_hash_fast_type,
3532 &nft_set_hash_type,
3533 &nft_set_rhash_type,
3534 &nft_set_bitmap_type,
3535 &nft_set_rbtree_type,
e6abef61 3536#if defined(CONFIG_X86_64) && !defined(CONFIG_UML)
7400b063
SB
3537 &nft_set_pipapo_avx2_type,
3538#endif
e32a4dc6
FW
3539 &nft_set_pipapo_type,
3540};
20a69341 3541
2b664957 3542#define NFT_SET_FEATURES (NFT_SET_INTERVAL | NFT_SET_MAP | \
71cc0873
PS
3543 NFT_SET_TIMEOUT | NFT_SET_OBJECT | \
3544 NFT_SET_EVAL)
2b664957 3545
71cc0873 3546static bool nft_set_ops_candidate(const struct nft_set_type *type, u32 flags)
2b664957 3547{
71cc0873 3548 return (flags & type->features) == (flags & NFT_SET_FEATURES);
2b664957
PNA
3549}
3550
c50b960c
PM
3551/*
3552 * Select a set implementation based on the data characteristics and the
3553 * given policy. The total memory use might not be known if no size is
3554 * given, in that case the amount of memory per element is used.
3555 */
3556static const struct nft_set_ops *
2b664957
PNA
3557nft_select_set_ops(const struct nft_ctx *ctx,
3558 const struct nlattr * const nla[],
c50b960c
PM
3559 const struct nft_set_desc *desc,
3560 enum nft_set_policies policy)
20a69341 3561{
0854db2a 3562 struct nftables_pernet *nft_net = net_generic(ctx->net, nf_tables_net_id);
c50b960c
PM
3563 const struct nft_set_ops *ops, *bops;
3564 struct nft_set_estimate est, best;
2b664957
PNA
3565 const struct nft_set_type *type;
3566 u32 flags = 0;
e32a4dc6 3567 int i;
20a69341 3568
0854db2a 3569 lockdep_assert_held(&nft_net->commit_mutex);
f102d66b 3570 lockdep_nfnl_nft_mutex_not_held();
e32a4dc6 3571
2b664957
PNA
3572 if (nla[NFTA_SET_FLAGS] != NULL)
3573 flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
20a69341 3574
55af753c
PNA
3575 bops = NULL;
3576 best.size = ~0;
3577 best.lookup = ~0;
0b5a7874 3578 best.space = ~0;
c50b960c 3579
e32a4dc6
FW
3580 for (i = 0; i < ARRAY_SIZE(nft_set_types); i++) {
3581 type = nft_set_types[i];
71cc0873 3582 ops = &type->ops;
2b664957 3583
71cc0873 3584 if (!nft_set_ops_candidate(type, flags))
20a69341 3585 continue;
2b664957 3586 if (!ops->estimate(desc, flags, &est))
c50b960c
PM
3587 continue;
3588
3589 switch (policy) {
3590 case NFT_SET_POL_PERFORMANCE:
55af753c 3591 if (est.lookup < best.lookup)
c50b960c 3592 break;
644e334e
PNA
3593 if (est.lookup == best.lookup &&
3594 est.space < best.space)
3595 break;
c50b960c
PM
3596 continue;
3597 case NFT_SET_POL_MEMORY:
0b5a7874
PNA
3598 if (!desc->size) {
3599 if (est.space < best.space)
3600 break;
3601 if (est.space == best.space &&
3602 est.lookup < best.lookup)
3603 break;
4f2921ca 3604 } else if (est.size < best.size || !bops) {
c50b960c 3605 break;
0b5a7874 3606 }
c50b960c
PM
3607 continue;
3608 default:
3609 break;
3610 }
3611
c50b960c
PM
3612 bops = ops;
3613 best = est;
20a69341
PM
3614 }
3615
c50b960c
PM
3616 if (bops != NULL)
3617 return bops;
3618
20a69341
PM
3619 return ERR_PTR(-EOPNOTSUPP);
3620}
3621
3622static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
b2fbd044
LZ
3623 [NFTA_SET_TABLE] = { .type = NLA_STRING,
3624 .len = NFT_TABLE_MAXNAMELEN - 1 },
a9bdd836 3625 [NFTA_SET_NAME] = { .type = NLA_STRING,
cb39ad8b 3626 .len = NFT_SET_MAXNAMELEN - 1 },
20a69341
PM
3627 [NFTA_SET_FLAGS] = { .type = NLA_U32 },
3628 [NFTA_SET_KEY_TYPE] = { .type = NLA_U32 },
3629 [NFTA_SET_KEY_LEN] = { .type = NLA_U32 },
3630 [NFTA_SET_DATA_TYPE] = { .type = NLA_U32 },
3631 [NFTA_SET_DATA_LEN] = { .type = NLA_U32 },
c50b960c
PM
3632 [NFTA_SET_POLICY] = { .type = NLA_U32 },
3633 [NFTA_SET_DESC] = { .type = NLA_NESTED },
958bee14 3634 [NFTA_SET_ID] = { .type = NLA_U32 },
761da293
PM
3635 [NFTA_SET_TIMEOUT] = { .type = NLA_U64 },
3636 [NFTA_SET_GC_INTERVAL] = { .type = NLA_U32 },
e6d8ecac
CFG
3637 [NFTA_SET_USERDATA] = { .type = NLA_BINARY,
3638 .len = NFT_USERDATA_MAXLEN },
8aeff920 3639 [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 },
3ecbfd65 3640 [NFTA_SET_HANDLE] = { .type = NLA_U64 },
65038428 3641 [NFTA_SET_EXPR] = { .type = NLA_NESTED },
48b0ae04 3642 [NFTA_SET_EXPRESSIONS] = { .type = NLA_NESTED },
c50b960c
PM
3643};
3644
3645static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
3646 [NFTA_SET_DESC_SIZE] = { .type = NLA_U32 },
f3a2181e 3647 [NFTA_SET_DESC_CONCAT] = { .type = NLA_NESTED },
20a69341
PM
3648};
3649
633c9a84 3650static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
20a69341
PM
3651 const struct sk_buff *skb,
3652 const struct nlmsghdr *nlh,
f2a6d766 3653 const struct nlattr * const nla[],
36dd1bcc 3654 struct netlink_ext_ack *extack,
6001a930 3655 u8 genmask, u32 nlpid)
20a69341
PM
3656{
3657 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
98319cb9 3658 int family = nfmsg->nfgen_family;
7c95f6d8 3659 struct nft_table *table = NULL;
20a69341 3660
20a69341 3661 if (nla[NFTA_SET_TABLE] != NULL) {
cac20fcd 3662 table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family,
6001a930 3663 genmask, nlpid);
36dd1bcc
PNA
3664 if (IS_ERR(table)) {
3665 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_TABLE]);
20a69341 3666 return PTR_ERR(table);
36dd1bcc 3667 }
20a69341
PM
3668 }
3669
98319cb9 3670 nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla);
20a69341
PM
3671 return 0;
3672}
3673
cac20fcd
PNA
3674static struct nft_set *nft_set_lookup(const struct nft_table *table,
3675 const struct nlattr *nla, u8 genmask)
20a69341
PM
3676{
3677 struct nft_set *set;
3678
3679 if (nla == NULL)
3680 return ERR_PTR(-EINVAL);
3681
d9adf22a 3682 list_for_each_entry_rcu(set, &table->sets, list) {
37a9cc52
PNA
3683 if (!nla_strcmp(nla, set->name) &&
3684 nft_active_genmask(set, genmask))
20a69341
PM
3685 return set;
3686 }
3687 return ERR_PTR(-ENOENT);
3688}
3689
cac20fcd
PNA
3690static struct nft_set *nft_set_lookup_byhandle(const struct nft_table *table,
3691 const struct nlattr *nla,
3692 u8 genmask)
3ecbfd65
HS
3693{
3694 struct nft_set *set;
3695
3ecbfd65
HS
3696 list_for_each_entry(set, &table->sets, list) {
3697 if (be64_to_cpu(nla_get_be64(nla)) == set->handle &&
3698 nft_active_genmask(set, genmask))
3699 return set;
3700 }
3701 return ERR_PTR(-ENOENT);
3702}
3703
cac20fcd
PNA
3704static struct nft_set *nft_set_lookup_byid(const struct net *net,
3705 const struct nlattr *nla, u8 genmask)
958bee14 3706{
0854db2a 3707 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
958bee14
PNA
3708 struct nft_trans *trans;
3709 u32 id = ntohl(nla_get_be32(nla));
3710
0854db2a 3711 list_for_each_entry(trans, &nft_net->commit_list, list) {
9c7f96fd
AK
3712 if (trans->msg_type == NFT_MSG_NEWSET) {
3713 struct nft_set *set = nft_trans_set(trans);
37a9cc52 3714
9c7f96fd
AK
3715 if (id == nft_trans_set_id(trans) &&
3716 nft_active_genmask(set, genmask))
3717 return set;
3718 }
958bee14
PNA
3719 }
3720 return ERR_PTR(-ENOENT);
3721}
c7a72e3f 3722
10659cba
PNA
3723struct nft_set *nft_set_lookup_global(const struct net *net,
3724 const struct nft_table *table,
3725 const struct nlattr *nla_set_name,
3726 const struct nlattr *nla_set_id,
3727 u8 genmask)
c7a72e3f
PNA
3728{
3729 struct nft_set *set;
3730
cac20fcd 3731 set = nft_set_lookup(table, nla_set_name, genmask);
c7a72e3f
PNA
3732 if (IS_ERR(set)) {
3733 if (!nla_set_id)
3734 return set;
3735
cac20fcd 3736 set = nft_set_lookup_byid(net, nla_set_id, genmask);
c7a72e3f
PNA
3737 }
3738 return set;
3739}
10659cba 3740EXPORT_SYMBOL_GPL(nft_set_lookup_global);
958bee14 3741
20a69341
PM
3742static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
3743 const char *name)
3744{
3745 const struct nft_set *i;
3746 const char *p;
3747 unsigned long *inuse;
60eb1894 3748 unsigned int n = 0, min = 0;
20a69341 3749
38745490 3750 p = strchr(name, '%');
20a69341
PM
3751 if (p != NULL) {
3752 if (p[1] != 'd' || strchr(p + 2, '%'))
3753 return -EINVAL;
3754
3755 inuse = (unsigned long *)get_zeroed_page(GFP_KERNEL);
3756 if (inuse == NULL)
3757 return -ENOMEM;
60eb1894 3758cont:
20a69341 3759 list_for_each_entry(i, &ctx->table->sets, list) {
14662917
DB
3760 int tmp;
3761
37a9cc52
PNA
3762 if (!nft_is_active_next(ctx->net, set))
3763 continue;
14662917 3764 if (!sscanf(i->name, name, &tmp))
20a69341 3765 continue;
60eb1894 3766 if (tmp < min || tmp >= min + BITS_PER_BYTE * PAGE_SIZE)
20a69341 3767 continue;
14662917 3768
60eb1894 3769 set_bit(tmp - min, inuse);
20a69341
PM
3770 }
3771
53b70287 3772 n = find_first_zero_bit(inuse, BITS_PER_BYTE * PAGE_SIZE);
60eb1894
PM
3773 if (n >= BITS_PER_BYTE * PAGE_SIZE) {
3774 min += BITS_PER_BYTE * PAGE_SIZE;
3775 memset(inuse, 0, PAGE_SIZE);
3776 goto cont;
3777 }
20a69341
PM
3778 free_page((unsigned long)inuse);
3779 }
3780
38745490
PS
3781 set->name = kasprintf(GFP_KERNEL, name, min + n);
3782 if (!set->name)
3783 return -ENOMEM;
3784
20a69341 3785 list_for_each_entry(i, &ctx->table->sets, list) {
37a9cc52
PNA
3786 if (!nft_is_active_next(ctx->net, i))
3787 continue;
e63aaaa6
AY
3788 if (!strcmp(set->name, i->name)) {
3789 kfree(set->name);
7fb6f78d 3790 set->name = NULL;
20a69341 3791 return -ENFILE;
e63aaaa6 3792 }
20a69341
PM
3793 }
3794 return 0;
3795}
3796
917d80d3 3797int nf_msecs_to_jiffies64(const struct nlattr *nla, u64 *result)
8e1102d5
FW
3798{
3799 u64 ms = be64_to_cpu(nla_get_be64(nla));
3800 u64 max = (u64)(~((u64)0));
3801
3802 max = div_u64(max, NSEC_PER_MSEC);
3803 if (ms >= max)
3804 return -ERANGE;
3805
3806 ms *= NSEC_PER_MSEC;
3807 *result = nsecs_to_jiffies64(ms);
3808 return 0;
3809}
3810
917d80d3 3811__be64 nf_jiffies64_to_msecs(u64 input)
8e1102d5 3812{
3b15d09f 3813 return cpu_to_be64(jiffies64_to_msecs(input));
8e1102d5
FW
3814}
3815
f3a2181e
SB
3816static int nf_tables_fill_set_concat(struct sk_buff *skb,
3817 const struct nft_set *set)
3818{
3819 struct nlattr *concat, *field;
3820 int i;
3821
3822 concat = nla_nest_start_noflag(skb, NFTA_SET_DESC_CONCAT);
3823 if (!concat)
3824 return -ENOMEM;
3825
3826 for (i = 0; i < set->field_count; i++) {
3827 field = nla_nest_start_noflag(skb, NFTA_LIST_ELEM);
3828 if (!field)
3829 return -ENOMEM;
3830
3831 if (nla_put_be32(skb, NFTA_SET_FIELD_LEN,
3832 htonl(set->field_len[i])))
3833 return -ENOMEM;
3834
3835 nla_nest_end(skb, field);
3836 }
3837
3838 nla_nest_end(skb, concat);
3839
3840 return 0;
3841}
3842
20a69341
PM
3843static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
3844 const struct nft_set *set, u16 event, u16 flags)
3845{
20a69341 3846 struct nlmsghdr *nlh;
128ad332 3847 u32 portid = ctx->portid;
65038428 3848 struct nlattr *nest;
128ad332 3849 u32 seq = ctx->seq;
48b0ae04 3850 int i;
20a69341 3851
dedb67c4 3852 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
19c28b13
PNA
3853 nlh = nfnl_msg_put(skb, portid, seq, event, flags, ctx->family,
3854 NFNETLINK_V0, nft_base_seq(ctx->net));
3855 if (!nlh)
20a69341
PM
3856 goto nla_put_failure;
3857
20a69341
PM
3858 if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name))
3859 goto nla_put_failure;
3860 if (nla_put_string(skb, NFTA_SET_NAME, set->name))
3861 goto nla_put_failure;
3ecbfd65
HS
3862 if (nla_put_be64(skb, NFTA_SET_HANDLE, cpu_to_be64(set->handle),
3863 NFTA_SET_PAD))
3864 goto nla_put_failure;
20a69341
PM
3865 if (set->flags != 0)
3866 if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags)))
3867 goto nla_put_failure;
3868
3869 if (nla_put_be32(skb, NFTA_SET_KEY_TYPE, htonl(set->ktype)))
3870 goto nla_put_failure;
3871 if (nla_put_be32(skb, NFTA_SET_KEY_LEN, htonl(set->klen)))
3872 goto nla_put_failure;
3873 if (set->flags & NFT_SET_MAP) {
3874 if (nla_put_be32(skb, NFTA_SET_DATA_TYPE, htonl(set->dtype)))
3875 goto nla_put_failure;
3876 if (nla_put_be32(skb, NFTA_SET_DATA_LEN, htonl(set->dlen)))
3877 goto nla_put_failure;
3878 }
8aeff920
PNA
3879 if (set->flags & NFT_SET_OBJECT &&
3880 nla_put_be32(skb, NFTA_SET_OBJ_TYPE, htonl(set->objtype)))
3881 goto nla_put_failure;
20a69341 3882
761da293 3883 if (set->timeout &&
d3e2a111 3884 nla_put_be64(skb, NFTA_SET_TIMEOUT,
8e1102d5 3885 nf_jiffies64_to_msecs(set->timeout),
b46f6ded 3886 NFTA_SET_PAD))
761da293
PM
3887 goto nla_put_failure;
3888 if (set->gc_int &&
3889 nla_put_be32(skb, NFTA_SET_GC_INTERVAL, htonl(set->gc_int)))
3890 goto nla_put_failure;
3891
9363dc4b
AB
3892 if (set->policy != NFT_SET_POL_PERFORMANCE) {
3893 if (nla_put_be32(skb, NFTA_SET_POLICY, htonl(set->policy)))
3894 goto nla_put_failure;
3895 }
3896
6f03bf43
PNA
3897 if (set->udata &&
3898 nla_put(skb, NFTA_SET_USERDATA, set->udlen, set->udata))
e6d8ecac
CFG
3899 goto nla_put_failure;
3900
65038428
PNA
3901 nest = nla_nest_start_noflag(skb, NFTA_SET_DESC);
3902 if (!nest)
c50b960c
PM
3903 goto nla_put_failure;
3904 if (set->size &&
3905 nla_put_be32(skb, NFTA_SET_DESC_SIZE, htonl(set->size)))
3906 goto nla_put_failure;
f3a2181e
SB
3907
3908 if (set->field_count > 1 &&
3909 nf_tables_fill_set_concat(skb, set))
3910 goto nla_put_failure;
3911
65038428
PNA
3912 nla_nest_end(skb, nest);
3913
8cfd9b0f 3914 if (set->num_exprs == 1) {
65038428 3915 nest = nla_nest_start_noflag(skb, NFTA_SET_EXPR);
8cfd9b0f 3916 if (nf_tables_fill_expr_info(skb, set->exprs[0]) < 0)
65038428
PNA
3917 goto nla_put_failure;
3918
3919 nla_nest_end(skb, nest);
48b0ae04
PNA
3920 } else if (set->num_exprs > 1) {
3921 nest = nla_nest_start_noflag(skb, NFTA_SET_EXPRESSIONS);
3922 if (nest == NULL)
65038428
PNA
3923 goto nla_put_failure;
3924
48b0ae04
PNA
3925 for (i = 0; i < set->num_exprs; i++) {
3926 if (nft_expr_dump(skb, NFTA_LIST_ELEM,
3927 set->exprs[i]) < 0)
3928 goto nla_put_failure;
3929 }
65038428
PNA
3930 nla_nest_end(skb, nest);
3931 }
c50b960c 3932
053c095a
JB
3933 nlmsg_end(skb, nlh);
3934 return 0;
20a69341
PM
3935
3936nla_put_failure:
3937 nlmsg_trim(skb, nlh);
3938 return -1;
3939}
3940
25e94a99
PNA
3941static void nf_tables_set_notify(const struct nft_ctx *ctx,
3942 const struct nft_set *set, int event,
3943 gfp_t gfp_flags)
20a69341 3944{
0854db2a 3945 struct nftables_pernet *nft_net = net_generic(ctx->net, nf_tables_net_id);
20a69341 3946 struct sk_buff *skb;
128ad332 3947 u32 portid = ctx->portid;
20a69341
PM
3948 int err;
3949
128ad332
PNA
3950 if (!ctx->report &&
3951 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
25e94a99 3952 return;
20a69341 3953
31f8441c 3954 skb = nlmsg_new(NLMSG_GOODSIZE, gfp_flags);
20a69341
PM
3955 if (skb == NULL)
3956 goto err;
3957
3958 err = nf_tables_fill_set(skb, ctx, set, event, 0);
3959 if (err < 0) {
3960 kfree_skb(skb);
3961 goto err;
3962 }
3963
0854db2a 3964 nft_notify_enqueue(skb, ctx->report, &nft_net->notify_list);
25e94a99 3965 return;
20a69341 3966err:
25e94a99 3967 nfnetlink_set_err(ctx->net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
20a69341
PM
3968}
3969
5b96af77 3970static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
c9c8e485
PNA
3971{
3972 const struct nft_set *set;
3973 unsigned int idx, s_idx = cb->args[0];
c9c8e485
PNA
3974 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
3975 struct net *net = sock_net(skb->sk);
5b96af77 3976 struct nft_ctx *ctx = cb->data, ctx_set;
0854db2a 3977 struct nftables_pernet *nft_net;
c9c8e485
PNA
3978
3979 if (cb->args[1])
3980 return skb->len;
3981
e688a7f8 3982 rcu_read_lock();
0854db2a
FW
3983 nft_net = net_generic(net, nf_tables_net_id);
3984 cb->seq = nft_net->base_seq;
38e029f1 3985
0854db2a 3986 list_for_each_entry_rcu(table, &nft_net->tables, list) {
36596dad 3987 if (ctx->family != NFPROTO_UNSPEC &&
98319cb9 3988 ctx->family != table->family)
36596dad
PNA
3989 continue;
3990
3991 if (ctx->table && ctx->table != table)
5b96af77
PNA
3992 continue;
3993
36596dad
PNA
3994 if (cur_table) {
3995 if (cur_table != table)
c9c8e485
PNA
3996 continue;
3997
36596dad 3998 cur_table = NULL;
c9c8e485 3999 }
36596dad
PNA
4000 idx = 0;
4001 list_for_each_entry_rcu(set, &table->sets, list) {
4002 if (idx < s_idx)
4003 goto cont;
4004 if (!nft_is_active(net, set))
4005 goto cont;
5b96af77 4006
36596dad
PNA
4007 ctx_set = *ctx;
4008 ctx_set.table = table;
98319cb9 4009 ctx_set.family = table->family;
c9c8e485 4010
36596dad
PNA
4011 if (nf_tables_fill_set(skb, &ctx_set, set,
4012 NFT_MSG_NEWSET,
4013 NLM_F_MULTI) < 0) {
4014 cb->args[0] = idx;
4015 cb->args[2] = (unsigned long) table;
4016 goto done;
c9c8e485 4017 }
36596dad 4018 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
c9c8e485 4019cont:
36596dad 4020 idx++;
c9c8e485 4021 }
36596dad
PNA
4022 if (s_idx)
4023 s_idx = 0;
c9c8e485
PNA
4024 }
4025 cb->args[1] = 1;
4026done:
e688a7f8 4027 rcu_read_unlock();
c9c8e485
PNA
4028 return skb->len;
4029}
4030
90fd131a
FW
4031static int nf_tables_dump_sets_start(struct netlink_callback *cb)
4032{
4033 struct nft_ctx *ctx_dump = NULL;
4034
4035 ctx_dump = kmemdup(cb->data, sizeof(*ctx_dump), GFP_ATOMIC);
4036 if (ctx_dump == NULL)
4037 return -ENOMEM;
4038
4039 cb->data = ctx_dump;
4040 return 0;
4041}
4042
5b96af77 4043static int nf_tables_dump_sets_done(struct netlink_callback *cb)
20a69341 4044{
5b96af77
PNA
4045 kfree(cb->data);
4046 return 0;
20a69341
PM
4047}
4048
d9adf22a 4049/* called with rcu_read_lock held */
7b8002a1
PNA
4050static int nf_tables_getset(struct net *net, struct sock *nlsk,
4051 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
4052 const struct nlattr * const nla[],
4053 struct netlink_ext_ack *extack)
20a69341 4054{
f2a6d766 4055 u8 genmask = nft_genmask_cur(net);
20a69341
PM
4056 const struct nft_set *set;
4057 struct nft_ctx ctx;
4058 struct sk_buff *skb2;
c9c8e485 4059 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
20a69341
PM
4060 int err;
4061
01cfa0a4 4062 /* Verify existence before starting dump */
36dd1bcc 4063 err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, extack,
6001a930 4064 genmask, 0);
20a69341
PM
4065 if (err < 0)
4066 return err;
4067
4068 if (nlh->nlmsg_flags & NLM_F_DUMP) {
4069 struct netlink_dump_control c = {
90fd131a 4070 .start = nf_tables_dump_sets_start,
20a69341 4071 .dump = nf_tables_dump_sets,
5b96af77 4072 .done = nf_tables_dump_sets_done,
90fd131a 4073 .data = &ctx,
d9adf22a 4074 .module = THIS_MODULE,
20a69341 4075 };
5b96af77 4076
d9adf22a 4077 return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
20a69341
PM
4078 }
4079
c9c8e485
PNA
4080 /* Only accept unspec with dump */
4081 if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
4082 return -EAFNOSUPPORT;
eaa2bcd6
PT
4083 if (!nla[NFTA_SET_TABLE])
4084 return -EINVAL;
c9c8e485 4085
cac20fcd 4086 set = nft_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask);
20a69341
PM
4087 if (IS_ERR(set))
4088 return PTR_ERR(set);
4089
d9adf22a 4090 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
20a69341
PM
4091 if (skb2 == NULL)
4092 return -ENOMEM;
4093
4094 err = nf_tables_fill_set(skb2, &ctx, set, NFT_MSG_NEWSET, 0);
4095 if (err < 0)
ee921183 4096 goto err_fill_set_info;
20a69341 4097
ee921183 4098 return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
20a69341 4099
ee921183 4100err_fill_set_info:
20a69341
PM
4101 kfree_skb(skb2);
4102 return err;
4103}
4104
f3a2181e
SB
4105static const struct nla_policy nft_concat_policy[NFTA_SET_FIELD_MAX + 1] = {
4106 [NFTA_SET_FIELD_LEN] = { .type = NLA_U32 },
4107};
4108
4109static int nft_set_desc_concat_parse(const struct nlattr *attr,
4110 struct nft_set_desc *desc)
4111{
4112 struct nlattr *tb[NFTA_SET_FIELD_MAX + 1];
4113 u32 len;
4114 int err;
4115
4116 err = nla_parse_nested_deprecated(tb, NFTA_SET_FIELD_MAX, attr,
4117 nft_concat_policy, NULL);
4118 if (err < 0)
4119 return err;
4120
4121 if (!tb[NFTA_SET_FIELD_LEN])
4122 return -EINVAL;
4123
4124 len = ntohl(nla_get_be32(tb[NFTA_SET_FIELD_LEN]));
4125
4126 if (len * BITS_PER_BYTE / 32 > NFT_REG32_COUNT)
4127 return -E2BIG;
4128
4129 desc->field_len[desc->field_count++] = len;
4130
4131 return 0;
4132}
4133
4134static int nft_set_desc_concat(struct nft_set_desc *desc,
4135 const struct nlattr *nla)
4136{
4137 struct nlattr *attr;
4138 int rem, err;
4139
4140 nla_for_each_nested(attr, nla, rem) {
4141 if (nla_type(attr) != NFTA_LIST_ELEM)
4142 return -EINVAL;
4143
4144 err = nft_set_desc_concat_parse(attr, desc);
4145 if (err < 0)
4146 return err;
4147 }
4148
4149 return 0;
4150}
4151
f7e840ee 4152static int nf_tables_set_desc_parse(struct nft_set_desc *desc,
c50b960c
PM
4153 const struct nlattr *nla)
4154{
4155 struct nlattr *da[NFTA_SET_DESC_MAX + 1];
4156 int err;
4157
8cb08174
JB
4158 err = nla_parse_nested_deprecated(da, NFTA_SET_DESC_MAX, nla,
4159 nft_set_desc_policy, NULL);
c50b960c
PM
4160 if (err < 0)
4161 return err;
4162
4163 if (da[NFTA_SET_DESC_SIZE] != NULL)
4164 desc->size = ntohl(nla_get_be32(da[NFTA_SET_DESC_SIZE]));
f3a2181e
SB
4165 if (da[NFTA_SET_DESC_CONCAT])
4166 err = nft_set_desc_concat(desc, da[NFTA_SET_DESC_CONCAT]);
c50b960c 4167
f3a2181e 4168 return err;
c50b960c
PM
4169}
4170
633c9a84
PNA
4171static int nf_tables_newset(struct net *net, struct sock *nlsk,
4172 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
4173 const struct nlattr * const nla[],
4174 struct netlink_ext_ack *extack)
20a69341
PM
4175{
4176 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 4177 u8 genmask = nft_genmask_next(net);
98319cb9 4178 int family = nfmsg->nfgen_family;
20a69341 4179 const struct nft_set_ops *ops;
65038428 4180 struct nft_expr *expr = NULL;
20a69341
PM
4181 struct nft_table *table;
4182 struct nft_set *set;
4183 struct nft_ctx ctx;
38745490 4184 char *name;
4ef360dd 4185 u64 size;
761da293 4186 u64 timeout;
8aeff920 4187 u32 ktype, dtype, flags, policy, gc_int, objtype;
c50b960c 4188 struct nft_set_desc desc;
e6d8ecac
CFG
4189 unsigned char *udata;
4190 u16 udlen;
20a69341 4191 int err;
f3a2181e 4192 int i;
20a69341
PM
4193
4194 if (nla[NFTA_SET_TABLE] == NULL ||
4195 nla[NFTA_SET_NAME] == NULL ||
958bee14
PNA
4196 nla[NFTA_SET_KEY_LEN] == NULL ||
4197 nla[NFTA_SET_ID] == NULL)
20a69341
PM
4198 return -EINVAL;
4199
c50b960c
PM
4200 memset(&desc, 0, sizeof(desc));
4201
20a69341
PM
4202 ktype = NFT_DATA_VALUE;
4203 if (nla[NFTA_SET_KEY_TYPE] != NULL) {
4204 ktype = ntohl(nla_get_be32(nla[NFTA_SET_KEY_TYPE]));
4205 if ((ktype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK)
4206 return -EINVAL;
4207 }
4208
c50b960c 4209 desc.klen = ntohl(nla_get_be32(nla[NFTA_SET_KEY_LEN]));
7d740264 4210 if (desc.klen == 0 || desc.klen > NFT_DATA_VALUE_MAXLEN)
20a69341
PM
4211 return -EINVAL;
4212
4213 flags = 0;
4214 if (nla[NFTA_SET_FLAGS] != NULL) {
4215 flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));
4216 if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
7c6c6e95 4217 NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
8aeff920 4218 NFT_SET_MAP | NFT_SET_EVAL |
b4e70d8d 4219 NFT_SET_OBJECT | NFT_SET_CONCAT | NFT_SET_EXPR))
d9583cdf 4220 return -EOPNOTSUPP;
8aeff920 4221 /* Only one of these operations is supported */
acab7131
FW
4222 if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) ==
4223 (NFT_SET_MAP | NFT_SET_OBJECT))
4224 return -EOPNOTSUPP;
4225 if ((flags & (NFT_SET_EVAL | NFT_SET_OBJECT)) ==
4226 (NFT_SET_EVAL | NFT_SET_OBJECT))
7c6c6e95 4227 return -EOPNOTSUPP;
20a69341
PM
4228 }
4229
4230 dtype = 0;
20a69341
PM
4231 if (nla[NFTA_SET_DATA_TYPE] != NULL) {
4232 if (!(flags & NFT_SET_MAP))
4233 return -EINVAL;
4234
4235 dtype = ntohl(nla_get_be32(nla[NFTA_SET_DATA_TYPE]));
4236 if ((dtype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK &&
4237 dtype != NFT_DATA_VERDICT)
4238 return -EINVAL;
4239
4240 if (dtype != NFT_DATA_VERDICT) {
4241 if (nla[NFTA_SET_DATA_LEN] == NULL)
4242 return -EINVAL;
c50b960c 4243 desc.dlen = ntohl(nla_get_be32(nla[NFTA_SET_DATA_LEN]));
7d740264 4244 if (desc.dlen == 0 || desc.dlen > NFT_DATA_VALUE_MAXLEN)
20a69341
PM
4245 return -EINVAL;
4246 } else
7d740264 4247 desc.dlen = sizeof(struct nft_verdict);
20a69341
PM
4248 } else if (flags & NFT_SET_MAP)
4249 return -EINVAL;
4250
8aeff920
PNA
4251 if (nla[NFTA_SET_OBJ_TYPE] != NULL) {
4252 if (!(flags & NFT_SET_OBJECT))
4253 return -EINVAL;
4254
4255 objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE]));
4256 if (objtype == NFT_OBJECT_UNSPEC ||
4257 objtype > NFT_OBJECT_MAX)
d9583cdf 4258 return -EOPNOTSUPP;
8aeff920
PNA
4259 } else if (flags & NFT_SET_OBJECT)
4260 return -EINVAL;
4261 else
4262 objtype = NFT_OBJECT_UNSPEC;
4263
761da293
PM
4264 timeout = 0;
4265 if (nla[NFTA_SET_TIMEOUT] != NULL) {
4266 if (!(flags & NFT_SET_TIMEOUT))
4267 return -EINVAL;
8e1102d5
FW
4268
4269 err = nf_msecs_to_jiffies64(nla[NFTA_SET_TIMEOUT], &timeout);
4270 if (err)
4271 return err;
761da293
PM
4272 }
4273 gc_int = 0;
4274 if (nla[NFTA_SET_GC_INTERVAL] != NULL) {
4275 if (!(flags & NFT_SET_TIMEOUT))
4276 return -EINVAL;
4277 gc_int = ntohl(nla_get_be32(nla[NFTA_SET_GC_INTERVAL]));
4278 }
4279
c50b960c
PM
4280 policy = NFT_SET_POL_PERFORMANCE;
4281 if (nla[NFTA_SET_POLICY] != NULL)
4282 policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY]));
4283
4284 if (nla[NFTA_SET_DESC] != NULL) {
f7e840ee 4285 err = nf_tables_set_desc_parse(&desc, nla[NFTA_SET_DESC]);
c50b960c
PM
4286 if (err < 0)
4287 return err;
4288 }
4289
48b0ae04 4290 if (nla[NFTA_SET_EXPR] || nla[NFTA_SET_EXPRESSIONS])
d56aab26
PNA
4291 desc.expr = true;
4292
6001a930
PNA
4293 table = nft_table_lookup(net, nla[NFTA_SET_TABLE], family, genmask,
4294 NETLINK_CB(skb).portid);
36dd1bcc
PNA
4295 if (IS_ERR(table)) {
4296 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_TABLE]);
20a69341 4297 return PTR_ERR(table);
36dd1bcc 4298 }
20a69341 4299
98319cb9 4300 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
20a69341 4301
cac20fcd 4302 set = nft_set_lookup(table, nla[NFTA_SET_NAME], genmask);
20a69341 4303 if (IS_ERR(set)) {
36dd1bcc
PNA
4304 if (PTR_ERR(set) != -ENOENT) {
4305 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]);
20a69341 4306 return PTR_ERR(set);
36dd1bcc 4307 }
1a28ad74 4308 } else {
36dd1bcc
PNA
4309 if (nlh->nlmsg_flags & NLM_F_EXCL) {
4310 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]);
20a69341 4311 return -EEXIST;
36dd1bcc 4312 }
20a69341
PM
4313 if (nlh->nlmsg_flags & NLM_F_REPLACE)
4314 return -EOPNOTSUPP;
36dd1bcc 4315
20a69341
PM
4316 return 0;
4317 }
4318
4319 if (!(nlh->nlmsg_flags & NLM_F_CREATE))
4320 return -ENOENT;
4321
2b664957 4322 ops = nft_select_set_ops(&ctx, nla, &desc, policy);
20a69341
PM
4323 if (IS_ERR(ops))
4324 return PTR_ERR(ops);
4325
e6d8ecac
CFG
4326 udlen = 0;
4327 if (nla[NFTA_SET_USERDATA])
4328 udlen = nla_len(nla[NFTA_SET_USERDATA]);
4329
20a69341
PM
4330 size = 0;
4331 if (ops->privsize != NULL)
347b408d 4332 size = ops->privsize(nla, &desc);
20a69341 4333
1ff75a3e 4334 set = kvzalloc(sizeof(*set) + size + udlen, GFP_KERNEL);
24d19826
FW
4335 if (!set)
4336 return -ENOMEM;
20a69341 4337
38745490
PS
4338 name = nla_strdup(nla[NFTA_SET_NAME], GFP_KERNEL);
4339 if (!name) {
4340 err = -ENOMEM;
65038428 4341 goto err_set_name;
38745490
PS
4342 }
4343
20a69341 4344 err = nf_tables_set_alloc_name(&ctx, set, name);
38745490 4345 kfree(name);
20a69341 4346 if (err < 0)
65038428
PNA
4347 goto err_set_alloc_name;
4348
4349 if (nla[NFTA_SET_EXPR]) {
4350 expr = nft_set_elem_expr_alloc(&ctx, set, nla[NFTA_SET_EXPR]);
4351 if (IS_ERR(expr)) {
4352 err = PTR_ERR(expr);
4353 goto err_set_alloc_name;
4354 }
8cfd9b0f
PNA
4355 set->exprs[0] = expr;
4356 set->num_exprs++;
48b0ae04
PNA
4357 } else if (nla[NFTA_SET_EXPRESSIONS]) {
4358 struct nft_expr *expr;
4359 struct nlattr *tmp;
4360 int left;
4361
b4e70d8d
PNA
4362 if (!(flags & NFT_SET_EXPR)) {
4363 err = -EINVAL;
4364 goto err_set_alloc_name;
4365 }
48b0ae04
PNA
4366 i = 0;
4367 nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) {
4368 if (i == NFT_SET_EXPR_MAX) {
4369 err = -E2BIG;
4370 goto err_set_init;
4371 }
4372 if (nla_type(tmp) != NFTA_LIST_ELEM) {
4373 err = -EINVAL;
4374 goto err_set_init;
4375 }
4376 expr = nft_set_elem_expr_alloc(&ctx, set, tmp);
4377 if (IS_ERR(expr)) {
4378 err = PTR_ERR(expr);
4379 goto err_set_init;
4380 }
4381 set->exprs[i++] = expr;
4382 set->num_exprs++;
4383 }
65038428 4384 }
20a69341 4385
e6d8ecac
CFG
4386 udata = NULL;
4387 if (udlen) {
4388 udata = set->data + size;
4389 nla_memcpy(udata, nla[NFTA_SET_USERDATA], udlen);
4390 }
4391
20a69341 4392 INIT_LIST_HEAD(&set->bindings);
3453c927
PNA
4393 set->table = table;
4394 write_pnet(&set->net, net);
20a69341
PM
4395 set->ops = ops;
4396 set->ktype = ktype;
c50b960c 4397 set->klen = desc.klen;
20a69341 4398 set->dtype = dtype;
8aeff920 4399 set->objtype = objtype;
c50b960c 4400 set->dlen = desc.dlen;
20a69341 4401 set->flags = flags;
c50b960c 4402 set->size = desc.size;
9363dc4b 4403 set->policy = policy;
e6d8ecac
CFG
4404 set->udlen = udlen;
4405 set->udata = udata;
761da293
PM
4406 set->timeout = timeout;
4407 set->gc_int = gc_int;
3ecbfd65 4408 set->handle = nf_tables_alloc_handle(table);
20a69341 4409
f3a2181e
SB
4410 set->field_count = desc.field_count;
4411 for (i = 0; i < desc.field_count; i++)
4412 set->field_len[i] = desc.field_len[i];
4413
c50b960c 4414 err = ops->init(set, &desc, nla);
20a69341 4415 if (err < 0)
65038428 4416 goto err_set_init;
20a69341 4417
958bee14 4418 err = nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set);
20a69341 4419 if (err < 0)
65038428 4420 goto err_set_trans;
20a69341 4421
e688a7f8 4422 list_add_tail_rcu(&set->list, &table->sets);
4fefee57 4423 table->use++;
20a69341
PM
4424 return 0;
4425
65038428 4426err_set_trans:
c17c3cdf 4427 ops->destroy(set);
65038428 4428err_set_init:
8cfd9b0f
PNA
4429 for (i = 0; i < set->num_exprs; i++)
4430 nft_expr_destroy(&ctx, set->exprs[i]);
65038428 4431err_set_alloc_name:
2f6adf48 4432 kfree(set->name);
65038428 4433err_set_name:
1ff75a3e 4434 kvfree(set);
20a69341
PM
4435 return err;
4436}
4437
0c2a85ed 4438static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
20a69341 4439{
8cfd9b0f
PNA
4440 int i;
4441
273fe3f1
PNA
4442 if (WARN_ON(set->use > 0))
4443 return;
4444
8cfd9b0f
PNA
4445 for (i = 0; i < set->num_exprs; i++)
4446 nft_expr_destroy(ctx, set->exprs[i]);
65038428 4447
20a69341 4448 set->ops->destroy(set);
38745490 4449 kfree(set->name);
1ff75a3e 4450 kvfree(set);
20a69341
PM
4451}
4452
633c9a84
PNA
4453static int nf_tables_delset(struct net *net, struct sock *nlsk,
4454 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
4455 const struct nlattr * const nla[],
4456 struct netlink_ext_ack *extack)
20a69341 4457{
c9c8e485 4458 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
f2a6d766 4459 u8 genmask = nft_genmask_next(net);
36dd1bcc 4460 const struct nlattr *attr;
20a69341
PM
4461 struct nft_set *set;
4462 struct nft_ctx ctx;
4463 int err;
4464
ec2c9935
PM
4465 if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
4466 return -EAFNOSUPPORT;
20a69341
PM
4467 if (nla[NFTA_SET_TABLE] == NULL)
4468 return -EINVAL;
4469
36dd1bcc 4470 err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla, extack,
6001a930 4471 genmask, NETLINK_CB(skb).portid);
20a69341
PM
4472 if (err < 0)
4473 return err;
4474
36dd1bcc
PNA
4475 if (nla[NFTA_SET_HANDLE]) {
4476 attr = nla[NFTA_SET_HANDLE];
4477 set = nft_set_lookup_byhandle(ctx.table, attr, genmask);
4478 } else {
4479 attr = nla[NFTA_SET_NAME];
4480 set = nft_set_lookup(ctx.table, attr, genmask);
4481 }
a8278400 4482
36dd1bcc
PNA
4483 if (IS_ERR(set)) {
4484 NL_SET_BAD_ATTR(extack, attr);
4485 return PTR_ERR(set);
4486 }
273fe3f1 4487 if (set->use ||
36dd1bcc
PNA
4488 (nlh->nlmsg_flags & NLM_F_NONREC && atomic_read(&set->nelems) > 0)) {
4489 NL_SET_BAD_ATTR(extack, attr);
20a69341 4490 return -EBUSY;
36dd1bcc 4491 }
20a69341 4492
ee01d542 4493 return nft_delset(&ctx, set);
20a69341
PM
4494}
4495
345023b0
PNA
4496static int nft_validate_register_store(const struct nft_ctx *ctx,
4497 enum nft_registers reg,
4498 const struct nft_data *data,
4499 enum nft_data_types type,
4500 unsigned int len);
4501
20a69341 4502static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
de70185d 4503 struct nft_set *set,
20a69341 4504 const struct nft_set_iter *iter,
de70185d 4505 struct nft_set_elem *elem)
20a69341 4506{
fe2811eb 4507 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
20a69341
PM
4508 enum nft_registers dreg;
4509
4510 dreg = nft_type_to_reg(set->dtype);
1ec10212
PM
4511 return nft_validate_register_store(ctx, dreg, nft_set_ext_data(ext),
4512 set->dtype == NFT_DATA_VERDICT ?
4513 NFT_DATA_VERDICT : NFT_DATA_VALUE,
4514 set->dlen);
20a69341
PM
4515}
4516
4517int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
4518 struct nft_set_binding *binding)
4519{
4520 struct nft_set_binding *i;
4521 struct nft_set_iter iter;
4522
273fe3f1
PNA
4523 if (set->use == UINT_MAX)
4524 return -EOVERFLOW;
4525
408070d6 4526 if (!list_empty(&set->bindings) && nft_set_is_anonymous(set))
20a69341
PM
4527 return -EBUSY;
4528
11113e19 4529 if (binding->flags & NFT_SET_MAP) {
20a69341
PM
4530 /* If the set is already bound to the same chain all
4531 * jumps are already validated for that chain.
4532 */
4533 list_for_each_entry(i, &set->bindings, list) {
a4684402 4534 if (i->flags & NFT_SET_MAP &&
11113e19 4535 i->chain == binding->chain)
20a69341
PM
4536 goto bind;
4537 }
4538
8588ac09 4539 iter.genmask = nft_genmask_next(ctx->net);
20a69341
PM
4540 iter.skip = 0;
4541 iter.count = 0;
4542 iter.err = 0;
4543 iter.fn = nf_tables_bind_check_setelem;
4544
4545 set->ops->walk(ctx, set, &iter);
a02f4248 4546 if (iter.err < 0)
20a69341 4547 return iter.err;
20a69341
PM
4548 }
4549bind:
4550 binding->chain = ctx->chain;
e688a7f8 4551 list_add_tail_rcu(&binding->list, &set->bindings);
f6ac8585 4552 nft_set_trans_bind(ctx, set);
273fe3f1 4553 set->use++;
f6ac8585 4554
20a69341
PM
4555 return 0;
4556}
63aea290 4557EXPORT_SYMBOL_GPL(nf_tables_bind_set);
20a69341 4558
3b0a081d
FW
4559static void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
4560 struct nft_set_binding *binding, bool event)
20a69341 4561{
e688a7f8 4562 list_del_rcu(&binding->list);
20a69341 4563
f6ac8585 4564 if (list_empty(&set->bindings) && nft_set_is_anonymous(set)) {
cd5125d8 4565 list_del_rcu(&set->list);
f6ac8585
PNA
4566 if (event)
4567 nf_tables_set_notify(ctx, set, NFT_MSG_DELSET,
4568 GFP_KERNEL);
4569 }
20a69341
PM
4570}
4571
273fe3f1
PNA
4572void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
4573 struct nft_set_binding *binding,
4574 enum nft_trans_phase phase)
4575{
4576 switch (phase) {
4577 case NFT_TRANS_PREPARE:
4578 set->use--;
4579 return;
4580 case NFT_TRANS_ABORT:
4581 case NFT_TRANS_RELEASE:
4582 set->use--;
954d8297 4583 fallthrough;
273fe3f1
PNA
4584 default:
4585 nf_tables_unbind_set(ctx, set, binding,
4586 phase == NFT_TRANS_COMMIT);
4587 }
4588}
4589EXPORT_SYMBOL_GPL(nf_tables_deactivate_set);
4590
cd5125d8
FW
4591void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set)
4592{
f6ac8585 4593 if (list_empty(&set->bindings) && nft_set_is_anonymous(set))
0c2a85ed 4594 nft_set_destroy(ctx, set);
cd5125d8
FW
4595}
4596EXPORT_SYMBOL_GPL(nf_tables_destroy_set);
4597
3ac4c07a
PM
4598const struct nft_set_ext_type nft_set_ext_types[] = {
4599 [NFT_SET_EXT_KEY] = {
7d740264 4600 .align = __alignof__(u32),
3ac4c07a
PM
4601 },
4602 [NFT_SET_EXT_DATA] = {
7d740264 4603 .align = __alignof__(u32),
3ac4c07a 4604 },
563125a7
PNA
4605 [NFT_SET_EXT_EXPRESSIONS] = {
4606 .align = __alignof__(struct nft_set_elem_expr),
f25ad2e9 4607 },
8aeff920
PNA
4608 [NFT_SET_EXT_OBJREF] = {
4609 .len = sizeof(struct nft_object *),
4610 .align = __alignof__(struct nft_object *),
4611 },
3ac4c07a
PM
4612 [NFT_SET_EXT_FLAGS] = {
4613 .len = sizeof(u8),
4614 .align = __alignof__(u8),
4615 },
c3e1b005
PM
4616 [NFT_SET_EXT_TIMEOUT] = {
4617 .len = sizeof(u64),
4618 .align = __alignof__(u64),
4619 },
4620 [NFT_SET_EXT_EXPIRATION] = {
8e1102d5
FW
4621 .len = sizeof(u64),
4622 .align = __alignof__(u64),
c3e1b005 4623 },
68e942e8
PM
4624 [NFT_SET_EXT_USERDATA] = {
4625 .len = sizeof(struct nft_userdata),
4626 .align = __alignof__(struct nft_userdata),
4627 },
7b225d0b
PNA
4628 [NFT_SET_EXT_KEY_END] = {
4629 .align = __alignof__(u32),
4630 },
3ac4c07a 4631};
3ac4c07a 4632
20a69341
PM
4633/*
4634 * Set elements
4635 */
4636
4637static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
4638 [NFTA_SET_ELEM_KEY] = { .type = NLA_NESTED },
4639 [NFTA_SET_ELEM_DATA] = { .type = NLA_NESTED },
4640 [NFTA_SET_ELEM_FLAGS] = { .type = NLA_U32 },
c3e1b005 4641 [NFTA_SET_ELEM_TIMEOUT] = { .type = NLA_U64 },
79ebb5bb 4642 [NFTA_SET_ELEM_EXPIRATION] = { .type = NLA_U64 },
68e942e8
PM
4643 [NFTA_SET_ELEM_USERDATA] = { .type = NLA_BINARY,
4644 .len = NFT_USERDATA_MAXLEN },
467697d2 4645 [NFTA_SET_ELEM_EXPR] = { .type = NLA_NESTED },
9332d27d
FW
4646 [NFTA_SET_ELEM_OBJREF] = { .type = NLA_STRING,
4647 .len = NFT_OBJ_MAXNAMELEN - 1 },
7b225d0b 4648 [NFTA_SET_ELEM_KEY_END] = { .type = NLA_NESTED },
48b0ae04 4649 [NFTA_SET_ELEM_EXPRESSIONS] = { .type = NLA_NESTED },
20a69341
PM
4650};
4651
4652static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = {
b2fbd044
LZ
4653 [NFTA_SET_ELEM_LIST_TABLE] = { .type = NLA_STRING,
4654 .len = NFT_TABLE_MAXNAMELEN - 1 },
4655 [NFTA_SET_ELEM_LIST_SET] = { .type = NLA_STRING,
4656 .len = NFT_SET_MAXNAMELEN - 1 },
20a69341 4657 [NFTA_SET_ELEM_LIST_ELEMENTS] = { .type = NLA_NESTED },
958bee14 4658 [NFTA_SET_ELEM_LIST_SET_ID] = { .type = NLA_U32 },
20a69341
PM
4659};
4660
633c9a84 4661static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
20a69341
PM
4662 const struct sk_buff *skb,
4663 const struct nlmsghdr *nlh,
f2a6d766 4664 const struct nlattr * const nla[],
36dd1bcc 4665 struct netlink_ext_ack *extack,
6001a930 4666 u8 genmask, u32 nlpid)
20a69341
PM
4667{
4668 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
98319cb9 4669 int family = nfmsg->nfgen_family;
7c95f6d8 4670 struct nft_table *table;
20a69341 4671
cac20fcd 4672 table = nft_table_lookup(net, nla[NFTA_SET_ELEM_LIST_TABLE], family,
6001a930 4673 genmask, nlpid);
36dd1bcc
PNA
4674 if (IS_ERR(table)) {
4675 NL_SET_BAD_ATTR(extack, nla[NFTA_SET_ELEM_LIST_TABLE]);
20a69341 4676 return PTR_ERR(table);
36dd1bcc 4677 }
20a69341 4678
98319cb9 4679 nft_ctx_init(ctx, net, skb, nlh, family, table, NULL, nla);
20a69341
PM
4680 return 0;
4681}
4682
563125a7
PNA
4683static int nft_set_elem_expr_dump(struct sk_buff *skb,
4684 const struct nft_set *set,
4685 const struct nft_set_ext *ext)
4686{
4687 struct nft_set_elem_expr *elem_expr;
4688 u32 size, num_exprs = 0;
4689 struct nft_expr *expr;
48b0ae04 4690 struct nlattr *nest;
563125a7
PNA
4691
4692 elem_expr = nft_set_ext_expr(ext);
4693 nft_setelem_expr_foreach(expr, elem_expr, size)
4694 num_exprs++;
4695
4696 if (num_exprs == 1) {
4697 expr = nft_setelem_expr_at(elem_expr, 0);
4698 if (nft_expr_dump(skb, NFTA_SET_ELEM_EXPR, expr) < 0)
4699 return -1;
4700
4701 return 0;
48b0ae04
PNA
4702 } else if (num_exprs > 1) {
4703 nest = nla_nest_start_noflag(skb, NFTA_SET_ELEM_EXPRESSIONS);
4704 if (nest == NULL)
4705 goto nla_put_failure;
563125a7 4706
48b0ae04
PNA
4707 nft_setelem_expr_foreach(expr, elem_expr, size) {
4708 expr = nft_setelem_expr_at(elem_expr, size);
4709 if (nft_expr_dump(skb, NFTA_LIST_ELEM, expr) < 0)
4710 goto nla_put_failure;
4711 }
4712 nla_nest_end(skb, nest);
4713 }
563125a7 4714 return 0;
48b0ae04
PNA
4715
4716nla_put_failure:
4717 return -1;
563125a7
PNA
4718}
4719
20a69341
PM
4720static int nf_tables_fill_setelem(struct sk_buff *skb,
4721 const struct nft_set *set,
4722 const struct nft_set_elem *elem)
4723{
fe2811eb 4724 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
20a69341
PM
4725 unsigned char *b = skb_tail_pointer(skb);
4726 struct nlattr *nest;
4727
ae0be8de 4728 nest = nla_nest_start_noflag(skb, NFTA_LIST_ELEM);
20a69341
PM
4729 if (nest == NULL)
4730 goto nla_put_failure;
4731
fe2811eb
PM
4732 if (nft_data_dump(skb, NFTA_SET_ELEM_KEY, nft_set_ext_key(ext),
4733 NFT_DATA_VALUE, set->klen) < 0)
20a69341
PM
4734 goto nla_put_failure;
4735
7b225d0b
PNA
4736 if (nft_set_ext_exists(ext, NFT_SET_EXT_KEY_END) &&
4737 nft_data_dump(skb, NFTA_SET_ELEM_KEY_END, nft_set_ext_key_end(ext),
4738 NFT_DATA_VALUE, set->klen) < 0)
4739 goto nla_put_failure;
4740
fe2811eb
PM
4741 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
4742 nft_data_dump(skb, NFTA_SET_ELEM_DATA, nft_set_ext_data(ext),
20a69341
PM
4743 set->dtype == NFT_DATA_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE,
4744 set->dlen) < 0)
4745 goto nla_put_failure;
4746
563125a7
PNA
4747 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPRESSIONS) &&
4748 nft_set_elem_expr_dump(skb, set, ext))
f25ad2e9
PM
4749 goto nla_put_failure;
4750
8aeff920
PNA
4751 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
4752 nla_put_string(skb, NFTA_SET_ELEM_OBJREF,
d152159b 4753 (*nft_set_ext_obj(ext))->key.name) < 0)
8aeff920
PNA
4754 goto nla_put_failure;
4755
fe2811eb
PM
4756 if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
4757 nla_put_be32(skb, NFTA_SET_ELEM_FLAGS,
4758 htonl(*nft_set_ext_flags(ext))))
4759 goto nla_put_failure;
20a69341 4760
c3e1b005
PM
4761 if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) &&
4762 nla_put_be64(skb, NFTA_SET_ELEM_TIMEOUT,
8e1102d5 4763 nf_jiffies64_to_msecs(*nft_set_ext_timeout(ext)),
b46f6ded 4764 NFTA_SET_ELEM_PAD))
c3e1b005
PM
4765 goto nla_put_failure;
4766
4767 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) {
8e1102d5 4768 u64 expires, now = get_jiffies_64();
c3e1b005
PM
4769
4770 expires = *nft_set_ext_expiration(ext);
8e1102d5 4771 if (time_before64(now, expires))
c3e1b005
PM
4772 expires -= now;
4773 else
4774 expires = 0;
4775
4776 if (nla_put_be64(skb, NFTA_SET_ELEM_EXPIRATION,
8e1102d5 4777 nf_jiffies64_to_msecs(expires),
b46f6ded 4778 NFTA_SET_ELEM_PAD))
c3e1b005
PM
4779 goto nla_put_failure;
4780 }
4781
68e942e8
PM
4782 if (nft_set_ext_exists(ext, NFT_SET_EXT_USERDATA)) {
4783 struct nft_userdata *udata;
4784
4785 udata = nft_set_ext_userdata(ext);
4786 if (nla_put(skb, NFTA_SET_ELEM_USERDATA,
4787 udata->len + 1, udata->data))
4788 goto nla_put_failure;
4789 }
4790
20a69341
PM
4791 nla_nest_end(skb, nest);
4792 return 0;
4793
4794nla_put_failure:
4795 nlmsg_trim(skb, b);
4796 return -EMSGSIZE;
4797}
4798
4799struct nft_set_dump_args {
4800 const struct netlink_callback *cb;
4801 struct nft_set_iter iter;
4802 struct sk_buff *skb;
4803};
4804
4805static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
de70185d 4806 struct nft_set *set,
20a69341 4807 const struct nft_set_iter *iter,
de70185d 4808 struct nft_set_elem *elem)
20a69341
PM
4809{
4810 struct nft_set_dump_args *args;
4811
4812 args = container_of(iter, struct nft_set_dump_args, iter);
4813 return nf_tables_fill_setelem(args->skb, set, elem);
4814}
4815
fa803605
LZ
4816struct nft_set_dump_ctx {
4817 const struct nft_set *set;
4818 struct nft_ctx ctx;
4819};
4820
20a69341
PM
4821static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
4822{
fa803605 4823 struct nft_set_dump_ctx *dump_ctx = cb->data;
633c9a84 4824 struct net *net = sock_net(skb->sk);
0854db2a 4825 struct nftables_pernet *nft_net;
fa803605 4826 struct nft_table *table;
de70185d 4827 struct nft_set *set;
20a69341 4828 struct nft_set_dump_args args;
fa803605 4829 bool set_found = false;
20a69341
PM
4830 struct nlmsghdr *nlh;
4831 struct nlattr *nest;
4832 u32 portid, seq;
fa803605 4833 int event;
20a69341 4834
fa803605 4835 rcu_read_lock();
0854db2a
FW
4836 nft_net = net_generic(net, nf_tables_net_id);
4837 list_for_each_entry_rcu(table, &nft_net->tables, list) {
36596dad 4838 if (dump_ctx->ctx.family != NFPROTO_UNSPEC &&
98319cb9 4839 dump_ctx->ctx.family != table->family)
fa803605 4840 continue;
20a69341 4841
36596dad
PNA
4842 if (table != dump_ctx->ctx.table)
4843 continue;
20a69341 4844
36596dad
PNA
4845 list_for_each_entry_rcu(set, &table->sets, list) {
4846 if (set == dump_ctx->set) {
4847 set_found = true;
4848 break;
fa803605 4849 }
fa803605
LZ
4850 }
4851 break;
4852 }
4853
4854 if (!set_found) {
4855 rcu_read_unlock();
4856 return -ENOENT;
4857 }
20a69341 4858
dedb67c4 4859 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_NEWSETELEM);
20a69341
PM
4860 portid = NETLINK_CB(cb->skb).portid;
4861 seq = cb->nlh->nlmsg_seq;
4862
19c28b13
PNA
4863 nlh = nfnl_msg_put(skb, portid, seq, event, NLM_F_MULTI,
4864 table->family, NFNETLINK_V0, nft_base_seq(net));
4865 if (!nlh)
20a69341
PM
4866 goto nla_put_failure;
4867
fa803605 4868 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_TABLE, table->name))
20a69341
PM
4869 goto nla_put_failure;
4870 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_SET, set->name))
4871 goto nla_put_failure;
4872
ae0be8de 4873 nest = nla_nest_start_noflag(skb, NFTA_SET_ELEM_LIST_ELEMENTS);
20a69341
PM
4874 if (nest == NULL)
4875 goto nla_put_failure;
4876
8588ac09
PNA
4877 args.cb = cb;
4878 args.skb = skb;
fa803605 4879 args.iter.genmask = nft_genmask_cur(net);
8588ac09
PNA
4880 args.iter.skip = cb->args[0];
4881 args.iter.count = 0;
4882 args.iter.err = 0;
4883 args.iter.fn = nf_tables_dump_setelem;
fa803605
LZ
4884 set->ops->walk(&dump_ctx->ctx, set, &args.iter);
4885 rcu_read_unlock();
20a69341
PM
4886
4887 nla_nest_end(skb, nest);
4888 nlmsg_end(skb, nlh);
4889
4890 if (args.iter.err && args.iter.err != -EMSGSIZE)
4891 return args.iter.err;
4892 if (args.iter.count == cb->args[0])
4893 return 0;
4894
4895 cb->args[0] = args.iter.count;
4896 return skb->len;
4897
4898nla_put_failure:
fa803605 4899 rcu_read_unlock();
20a69341
PM
4900 return -ENOSPC;
4901}
4902
90fd131a
FW
4903static int nf_tables_dump_set_start(struct netlink_callback *cb)
4904{
4905 struct nft_set_dump_ctx *dump_ctx = cb->data;
4906
4907 cb->data = kmemdup(dump_ctx, sizeof(*dump_ctx), GFP_ATOMIC);
4908
4909 return cb->data ? 0 : -ENOMEM;
4910}
4911
fa803605
LZ
4912static int nf_tables_dump_set_done(struct netlink_callback *cb)
4913{
4914 kfree(cb->data);
4915 return 0;
4916}
4917
d60ce62f
AB
4918static int nf_tables_fill_setelem_info(struct sk_buff *skb,
4919 const struct nft_ctx *ctx, u32 seq,
4920 u32 portid, int event, u16 flags,
4921 const struct nft_set *set,
4922 const struct nft_set_elem *elem)
4923{
d60ce62f
AB
4924 struct nlmsghdr *nlh;
4925 struct nlattr *nest;
4926 int err;
4927
dedb67c4 4928 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
19c28b13
PNA
4929 nlh = nfnl_msg_put(skb, portid, seq, event, flags, ctx->family,
4930 NFNETLINK_V0, nft_base_seq(ctx->net));
4931 if (!nlh)
d60ce62f
AB
4932 goto nla_put_failure;
4933
d60ce62f
AB
4934 if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name))
4935 goto nla_put_failure;
4936 if (nla_put_string(skb, NFTA_SET_NAME, set->name))
4937 goto nla_put_failure;
4938
ae0be8de 4939 nest = nla_nest_start_noflag(skb, NFTA_SET_ELEM_LIST_ELEMENTS);
d60ce62f
AB
4940 if (nest == NULL)
4941 goto nla_put_failure;
4942
4943 err = nf_tables_fill_setelem(skb, set, elem);
4944 if (err < 0)
4945 goto nla_put_failure;
4946
4947 nla_nest_end(skb, nest);
4948
053c095a
JB
4949 nlmsg_end(skb, nlh);
4950 return 0;
d60ce62f
AB
4951
4952nla_put_failure:
4953 nlmsg_trim(skb, nlh);
4954 return -1;
4955}
4956
ba0e4d99
PNA
4957static int nft_setelem_parse_flags(const struct nft_set *set,
4958 const struct nlattr *attr, u32 *flags)
4959{
4960 if (attr == NULL)
4961 return 0;
4962
4963 *flags = ntohl(nla_get_be32(attr));
4964 if (*flags & ~NFT_SET_ELEM_INTERVAL_END)
4965 return -EINVAL;
4966 if (!(set->flags & NFT_SET_INTERVAL) &&
4967 *flags & NFT_SET_ELEM_INTERVAL_END)
4968 return -EINVAL;
4969
4970 return 0;
4971}
4972
20a1452c
PNA
4973static int nft_setelem_parse_key(struct nft_ctx *ctx, struct nft_set *set,
4974 struct nft_data *key, struct nlattr *attr)
4975{
4976 struct nft_data_desc desc;
4977 int err;
4978
4979 err = nft_data_init(ctx, key, NFT_DATA_VALUE_MAXLEN, &desc, attr);
4980 if (err < 0)
4981 return err;
4982
4983 if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) {
4984 nft_data_release(key, desc.type);
4985 return -EINVAL;
4986 }
4987
4988 return 0;
4989}
4990
fdb9c405
PNA
4991static int nft_setelem_parse_data(struct nft_ctx *ctx, struct nft_set *set,
4992 struct nft_data_desc *desc,
4993 struct nft_data *data,
4994 struct nlattr *attr)
4995{
4996 int err;
4997
4998 err = nft_data_init(ctx, data, NFT_DATA_VALUE_MAXLEN, desc, attr);
4999 if (err < 0)
5000 return err;
5001
5002 if (desc->type != NFT_DATA_VERDICT && desc->len != set->dlen) {
5003 nft_data_release(data, desc->type);
5004 return -EINVAL;
5005 }
5006
5007 return 0;
5008}
5009
ba0e4d99
PNA
5010static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
5011 const struct nlattr *attr)
5012{
5013 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
ba0e4d99
PNA
5014 struct nft_set_elem elem;
5015 struct sk_buff *skb;
5016 uint32_t flags = 0;
5017 void *priv;
5018 int err;
5019
8cb08174
JB
5020 err = nla_parse_nested_deprecated(nla, NFTA_SET_ELEM_MAX, attr,
5021 nft_set_elem_policy, NULL);
ba0e4d99
PNA
5022 if (err < 0)
5023 return err;
5024
5025 if (!nla[NFTA_SET_ELEM_KEY])
5026 return -EINVAL;
5027
5028 err = nft_setelem_parse_flags(set, nla[NFTA_SET_ELEM_FLAGS], &flags);
5029 if (err < 0)
5030 return err;
5031
20a1452c
PNA
5032 err = nft_setelem_parse_key(ctx, set, &elem.key.val,
5033 nla[NFTA_SET_ELEM_KEY]);
ba0e4d99
PNA
5034 if (err < 0)
5035 return err;
5036
7b225d0b
PNA
5037 if (nla[NFTA_SET_ELEM_KEY_END]) {
5038 err = nft_setelem_parse_key(ctx, set, &elem.key_end.val,
5039 nla[NFTA_SET_ELEM_KEY_END]);
5040 if (err < 0)
5041 return err;
5042 }
5043
ba0e4d99
PNA
5044 priv = set->ops->get(ctx->net, set, &elem, flags);
5045 if (IS_ERR(priv))
5046 return PTR_ERR(priv);
5047
5048 elem.priv = priv;
ba0e4d99
PNA
5049
5050 err = -ENOMEM;
d9adf22a 5051 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
ba0e4d99 5052 if (skb == NULL)
ee921183 5053 return err;
ba0e4d99
PNA
5054
5055 err = nf_tables_fill_setelem_info(skb, ctx, ctx->seq, ctx->portid,
5056 NFT_MSG_NEWSETELEM, 0, set, &elem);
5057 if (err < 0)
ee921183 5058 goto err_fill_setelem;
ba0e4d99 5059
ee921183 5060 return nfnetlink_unicast(skb, ctx->net, ctx->portid);
ba0e4d99 5061
ee921183 5062err_fill_setelem:
ba0e4d99 5063 kfree_skb(skb);
ee921183 5064 return err;
ba0e4d99
PNA
5065}
5066
d9adf22a 5067/* called with rcu_read_lock held */
ba0e4d99
PNA
5068static int nf_tables_getsetelem(struct net *net, struct sock *nlsk,
5069 struct sk_buff *skb, const struct nlmsghdr *nlh,
5070 const struct nlattr * const nla[],
5071 struct netlink_ext_ack *extack)
5072{
5073 u8 genmask = nft_genmask_cur(net);
5074 struct nft_set *set;
5075 struct nlattr *attr;
5076 struct nft_ctx ctx;
5077 int rem, err = 0;
5078
36dd1bcc 5079 err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, extack,
6001a930 5080 genmask, NETLINK_CB(skb).portid);
ba0e4d99
PNA
5081 if (err < 0)
5082 return err;
5083
cac20fcd 5084 set = nft_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
ba0e4d99
PNA
5085 if (IS_ERR(set))
5086 return PTR_ERR(set);
5087
5088 if (nlh->nlmsg_flags & NLM_F_DUMP) {
5089 struct netlink_dump_control c = {
90fd131a 5090 .start = nf_tables_dump_set_start,
ba0e4d99
PNA
5091 .dump = nf_tables_dump_set,
5092 .done = nf_tables_dump_set_done,
d9adf22a 5093 .module = THIS_MODULE,
ba0e4d99 5094 };
90fd131a
FW
5095 struct nft_set_dump_ctx dump_ctx = {
5096 .set = set,
5097 .ctx = ctx,
5098 };
ba0e4d99 5099
90fd131a 5100 c.data = &dump_ctx;
d9adf22a 5101 return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
ba0e4d99
PNA
5102 }
5103
5104 if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
5105 return -EINVAL;
5106
5107 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
5108 err = nft_get_set_elem(&ctx, set, attr);
5109 if (err < 0)
5110 break;
5111 }
5112
5113 return err;
5114}
5115
25e94a99
PNA
5116static void nf_tables_setelem_notify(const struct nft_ctx *ctx,
5117 const struct nft_set *set,
5118 const struct nft_set_elem *elem,
5119 int event, u16 flags)
d60ce62f 5120{
0854db2a 5121 struct nftables_pernet *nft_net;
128ad332
PNA
5122 struct net *net = ctx->net;
5123 u32 portid = ctx->portid;
d60ce62f
AB
5124 struct sk_buff *skb;
5125 int err;
5126
128ad332 5127 if (!ctx->report && !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
25e94a99 5128 return;
d60ce62f 5129
d60ce62f
AB
5130 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
5131 if (skb == NULL)
5132 goto err;
5133
5134 err = nf_tables_fill_setelem_info(skb, ctx, 0, portid, event, flags,
5135 set, elem);
5136 if (err < 0) {
5137 kfree_skb(skb);
5138 goto err;
5139 }
5140
0854db2a
FW
5141 nft_net = net_generic(net, nf_tables_net_id);
5142 nft_notify_enqueue(skb, ctx->report, &nft_net->notify_list);
25e94a99 5143 return;
d60ce62f 5144err:
25e94a99 5145 nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
d60ce62f
AB
5146}
5147
60319eb1
PNA
5148static struct nft_trans *nft_trans_elem_alloc(struct nft_ctx *ctx,
5149 int msg_type,
5150 struct nft_set *set)
5151{
5152 struct nft_trans *trans;
5153
5154 trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_elem));
5155 if (trans == NULL)
5156 return NULL;
5157
5158 nft_trans_elem_set(trans) = set;
5159 return trans;
5160}
5161
a7fc9368
PNA
5162struct nft_expr *nft_set_elem_expr_alloc(const struct nft_ctx *ctx,
5163 const struct nft_set *set,
5164 const struct nlattr *attr)
5165{
5166 struct nft_expr *expr;
5167 int err;
5168
5169 expr = nft_expr_init(ctx, attr);
5170 if (IS_ERR(expr))
5171 return expr;
5172
5173 err = -EOPNOTSUPP;
5174 if (!(expr->ops->type->flags & NFT_EXPR_STATEFUL))
5175 goto err_set_elem_expr;
5176
5177 if (expr->ops->type->flags & NFT_EXPR_GC) {
5178 if (set->flags & NFT_SET_TIMEOUT)
5179 goto err_set_elem_expr;
5180 if (!set->ops->gc_init)
5181 goto err_set_elem_expr;
5182 set->ops->gc_init(set);
5183 }
5184
5185 return expr;
5186
5187err_set_elem_expr:
5188 nft_expr_destroy(ctx, expr);
5189 return ERR_PTR(err);
5190}
5191
22fe54d5
PM
5192void *nft_set_elem_init(const struct nft_set *set,
5193 const struct nft_set_ext_tmpl *tmpl,
7b225d0b
PNA
5194 const u32 *key, const u32 *key_end,
5195 const u32 *data, u64 timeout, u64 expiration, gfp_t gfp)
fe2811eb
PM
5196{
5197 struct nft_set_ext *ext;
5198 void *elem;
5199
5200 elem = kzalloc(set->ops->elemsize + tmpl->len, gfp);
5201 if (elem == NULL)
5202 return NULL;
5203
5204 ext = nft_set_elem_ext(set, elem);
5205 nft_set_ext_init(ext, tmpl);
5206
5207 memcpy(nft_set_ext_key(ext), key, set->klen);
7b225d0b
PNA
5208 if (nft_set_ext_exists(ext, NFT_SET_EXT_KEY_END))
5209 memcpy(nft_set_ext_key_end(ext), key_end, set->klen);
fe2811eb
PM
5210 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
5211 memcpy(nft_set_ext_data(ext), data, set->dlen);
79ebb5bb
LGL
5212 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION)) {
5213 *nft_set_ext_expiration(ext) = get_jiffies_64() + expiration;
5214 if (expiration == 0)
5215 *nft_set_ext_expiration(ext) += timeout;
5216 }
c3e1b005
PM
5217 if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT))
5218 *nft_set_ext_timeout(ext) = timeout;
fe2811eb
PM
5219
5220 return elem;
5221}
5222
563125a7
PNA
5223static void __nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
5224 struct nft_expr *expr)
475beb9c
PNA
5225{
5226 if (expr->ops->destroy_clone) {
5227 expr->ops->destroy_clone(ctx, expr);
5228 module_put(expr->ops->type->owner);
5229 } else {
5230 nf_tables_expr_destroy(ctx, expr);
5231 }
5232}
5233
563125a7
PNA
5234static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
5235 struct nft_set_elem_expr *elem_expr)
5236{
5237 struct nft_expr *expr;
5238 u32 size;
5239
5240 nft_setelem_expr_foreach(expr, elem_expr, size)
5241 __nft_set_elem_expr_destroy(ctx, expr);
5242}
5243
61f9e292
LZ
5244void nft_set_elem_destroy(const struct nft_set *set, void *elem,
5245 bool destroy_expr)
61edafbb
PM
5246{
5247 struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
3453c927
PNA
5248 struct nft_ctx ctx = {
5249 .net = read_pnet(&set->net),
5250 .family = set->table->family,
5251 };
61edafbb 5252
59105446 5253 nft_data_release(nft_set_ext_key(ext), NFT_DATA_VALUE);
61edafbb 5254 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
59105446 5255 nft_data_release(nft_set_ext_data(ext), set->dtype);
563125a7 5256 if (destroy_expr && nft_set_ext_exists(ext, NFT_SET_EXT_EXPRESSIONS))
475beb9c 5257 nft_set_elem_expr_destroy(&ctx, nft_set_ext_expr(ext));
371ebcbb 5258
8aeff920
PNA
5259 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
5260 (*nft_set_ext_obj(ext))->use--;
61edafbb
PM
5261 kfree(elem);
5262}
5263EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
5264
59105446
PNA
5265/* Only called from commit path, nft_set_elem_deactivate() already deals with
5266 * the refcounting from the preparation phase.
5267 */
3453c927
PNA
5268static void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
5269 const struct nft_set *set, void *elem)
59105446
PNA
5270{
5271 struct nft_set_ext *ext = nft_set_elem_ext(set, elem);
5272
563125a7 5273 if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPRESSIONS))
475beb9c
PNA
5274 nft_set_elem_expr_destroy(ctx, nft_set_ext_expr(ext));
5275
59105446
PNA
5276 kfree(elem);
5277}
5278
fca05d4d
PNA
5279int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
5280 struct nft_expr *expr_array[])
8cfd9b0f
PNA
5281{
5282 struct nft_expr *expr;
5283 int err, i, k;
5284
5285 for (i = 0; i < set->num_exprs; i++) {
5286 expr = kzalloc(set->exprs[i]->ops->size, GFP_KERNEL);
5287 if (!expr)
5288 goto err_expr;
5289
5290 err = nft_expr_clone(expr, set->exprs[i]);
5291 if (err < 0) {
5292 nft_expr_destroy(ctx, expr);
5293 goto err_expr;
5294 }
5295 expr_array[i] = expr;
5296 }
5297
5298 return 0;
5299
5300err_expr:
161b838e
CIK
5301 for (k = i - 1; k >= 0; k--)
5302 nft_expr_destroy(ctx, expr_array[k]);
8cfd9b0f
PNA
5303
5304 return -ENOMEM;
5305}
5306
563125a7
PNA
5307static void nft_set_elem_expr_setup(const struct nft_set_ext *ext, int i,
5308 struct nft_expr *expr_array[])
5309{
5310 struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext);
5311 struct nft_expr *expr = nft_setelem_expr_at(elem_expr, elem_expr->size);
5312
5313 memcpy(expr, expr_array[i], expr_array[i]->ops->size);
5314 elem_expr->size += expr_array[i]->ops->size;
5315 kfree(expr_array[i]);
5316 expr_array[i] = NULL;
5317}
5318
60319eb1 5319static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
c016c7e4 5320 const struct nlattr *attr, u32 nlmsg_flags)
20a69341 5321{
8cfd9b0f 5322 struct nft_expr *expr_array[NFT_SET_EXPR_MAX] = {};
20a69341 5323 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
8aeff920 5324 u8 genmask = nft_genmask_next(ctx->net);
664899e8 5325 u32 flags = 0, size = 0, num_exprs = 0;
fe2811eb 5326 struct nft_set_ext_tmpl tmpl;
c016c7e4 5327 struct nft_set_ext *ext, *ext2;
20a69341
PM
5328 struct nft_set_elem elem;
5329 struct nft_set_binding *binding;
8aeff920 5330 struct nft_object *obj = NULL;
68e942e8 5331 struct nft_userdata *udata;
20a1452c 5332 struct nft_data_desc desc;
20a69341 5333 enum nft_registers dreg;
60319eb1 5334 struct nft_trans *trans;
c3e1b005 5335 u64 timeout;
79ebb5bb 5336 u64 expiration;
8cfd9b0f 5337 int err, i;
68e942e8 5338 u8 ulen;
20a69341 5339
8cb08174
JB
5340 err = nla_parse_nested_deprecated(nla, NFTA_SET_ELEM_MAX, attr,
5341 nft_set_elem_policy, NULL);
20a69341
PM
5342 if (err < 0)
5343 return err;
5344
5345 if (nla[NFTA_SET_ELEM_KEY] == NULL)
5346 return -EINVAL;
5347
fe2811eb
PM
5348 nft_set_ext_prepare(&tmpl);
5349
0e9091d6
PNA
5350 err = nft_setelem_parse_flags(set, nla[NFTA_SET_ELEM_FLAGS], &flags);
5351 if (err < 0)
5352 return err;
5353 if (flags != 0)
5354 nft_set_ext_add(&tmpl, NFT_SET_EXT_FLAGS);
20a69341
PM
5355
5356 if (set->flags & NFT_SET_MAP) {
5357 if (nla[NFTA_SET_ELEM_DATA] == NULL &&
fe2811eb 5358 !(flags & NFT_SET_ELEM_INTERVAL_END))
20a69341
PM
5359 return -EINVAL;
5360 } else {
5361 if (nla[NFTA_SET_ELEM_DATA] != NULL)
5362 return -EINVAL;
5363 }
5364
bffc124b
PNA
5365 if ((flags & NFT_SET_ELEM_INTERVAL_END) &&
5366 (nla[NFTA_SET_ELEM_DATA] ||
5367 nla[NFTA_SET_ELEM_OBJREF] ||
5368 nla[NFTA_SET_ELEM_TIMEOUT] ||
5369 nla[NFTA_SET_ELEM_EXPIRATION] ||
5370 nla[NFTA_SET_ELEM_USERDATA] ||
48b0ae04
PNA
5371 nla[NFTA_SET_ELEM_EXPR] ||
5372 nla[NFTA_SET_ELEM_EXPRESSIONS]))
bffc124b
PNA
5373 return -EINVAL;
5374
c3e1b005
PM
5375 timeout = 0;
5376 if (nla[NFTA_SET_ELEM_TIMEOUT] != NULL) {
5377 if (!(set->flags & NFT_SET_TIMEOUT))
5378 return -EINVAL;
8e1102d5
FW
5379 err = nf_msecs_to_jiffies64(nla[NFTA_SET_ELEM_TIMEOUT],
5380 &timeout);
5381 if (err)
5382 return err;
c3e1b005
PM
5383 } else if (set->flags & NFT_SET_TIMEOUT) {
5384 timeout = set->timeout;
5385 }
5386
79ebb5bb
LGL
5387 expiration = 0;
5388 if (nla[NFTA_SET_ELEM_EXPIRATION] != NULL) {
5389 if (!(set->flags & NFT_SET_TIMEOUT))
5390 return -EINVAL;
5391 err = nf_msecs_to_jiffies64(nla[NFTA_SET_ELEM_EXPIRATION],
5392 &expiration);
5393 if (err)
5394 return err;
5395 }
5396
8cfd9b0f
PNA
5397 if (nla[NFTA_SET_ELEM_EXPR]) {
5398 struct nft_expr *expr;
5399
664899e8 5400 if (set->num_exprs && set->num_exprs != 1)
8cfd9b0f
PNA
5401 return -EOPNOTSUPP;
5402
40944452
PNA
5403 expr = nft_set_elem_expr_alloc(ctx, set,
5404 nla[NFTA_SET_ELEM_EXPR]);
5405 if (IS_ERR(expr))
5406 return PTR_ERR(expr);
65038428 5407
8cfd9b0f 5408 expr_array[0] = expr;
664899e8 5409 num_exprs = 1;
65038428 5410
664899e8 5411 if (set->num_exprs && set->exprs[0]->ops != expr->ops) {
8cfd9b0f 5412 err = -EOPNOTSUPP;
65038428 5413 goto err_set_elem_expr;
8cfd9b0f 5414 }
48b0ae04
PNA
5415 } else if (nla[NFTA_SET_ELEM_EXPRESSIONS]) {
5416 struct nft_expr *expr;
5417 struct nlattr *tmp;
5418 int left;
65038428 5419
48b0ae04
PNA
5420 i = 0;
5421 nla_for_each_nested(tmp, nla[NFTA_SET_ELEM_EXPRESSIONS], left) {
664899e8
PNA
5422 if (i == NFT_SET_EXPR_MAX ||
5423 (set->num_exprs && set->num_exprs == i)) {
48b0ae04
PNA
5424 err = -E2BIG;
5425 goto err_set_elem_expr;
5426 }
5427 if (nla_type(tmp) != NFTA_LIST_ELEM) {
5428 err = -EINVAL;
5429 goto err_set_elem_expr;
5430 }
5431 expr = nft_set_elem_expr_alloc(ctx, set, tmp);
5432 if (IS_ERR(expr)) {
5433 err = PTR_ERR(expr);
5434 goto err_set_elem_expr;
5435 }
5436 expr_array[i] = expr;
664899e8 5437 num_exprs++;
48b0ae04 5438
664899e8 5439 if (set->num_exprs && expr->ops != set->exprs[i]->ops) {
48b0ae04
PNA
5440 err = -EOPNOTSUPP;
5441 goto err_set_elem_expr;
5442 }
5443 i++;
5444 }
664899e8 5445 if (set->num_exprs && set->num_exprs != i) {
48b0ae04 5446 err = -EOPNOTSUPP;
65038428 5447 goto err_set_elem_expr;
48b0ae04 5448 }
8cfd9b0f
PNA
5449 } else if (set->num_exprs > 0) {
5450 err = nft_set_elem_expr_clone(ctx, set, expr_array);
5451 if (err < 0)
5452 goto err_set_elem_expr_clone;
664899e8
PNA
5453
5454 num_exprs = set->num_exprs;
40944452
PNA
5455 }
5456
20a1452c
PNA
5457 err = nft_setelem_parse_key(ctx, set, &elem.key.val,
5458 nla[NFTA_SET_ELEM_KEY]);
20a69341 5459 if (err < 0)
40944452 5460 goto err_set_elem_expr;
20a69341 5461
20a1452c 5462 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen);
7b225d0b
PNA
5463
5464 if (nla[NFTA_SET_ELEM_KEY_END]) {
5465 err = nft_setelem_parse_key(ctx, set, &elem.key_end.val,
5466 nla[NFTA_SET_ELEM_KEY_END]);
5467 if (err < 0)
5468 goto err_parse_key;
5469
5470 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY_END, set->klen);
5471 }
5472
c3e1b005
PM
5473 if (timeout > 0) {
5474 nft_set_ext_add(&tmpl, NFT_SET_EXT_EXPIRATION);
5475 if (timeout != set->timeout)
5476 nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT);
5477 }
fe2811eb 5478
664899e8
PNA
5479 if (num_exprs) {
5480 for (i = 0; i < num_exprs; i++)
563125a7
PNA
5481 size += expr_array[i]->ops->size;
5482
5483 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_EXPRESSIONS,
5484 sizeof(struct nft_set_elem_expr) +
5485 size);
5486 }
40944452 5487
8aeff920
PNA
5488 if (nla[NFTA_SET_ELEM_OBJREF] != NULL) {
5489 if (!(set->flags & NFT_SET_OBJECT)) {
5490 err = -EINVAL;
7b225d0b 5491 goto err_parse_key_end;
8aeff920 5492 }
4d44175a
FW
5493 obj = nft_obj_lookup(ctx->net, ctx->table,
5494 nla[NFTA_SET_ELEM_OBJREF],
cac20fcd 5495 set->objtype, genmask);
8aeff920
PNA
5496 if (IS_ERR(obj)) {
5497 err = PTR_ERR(obj);
7b225d0b 5498 goto err_parse_key_end;
8aeff920
PNA
5499 }
5500 nft_set_ext_add(&tmpl, NFT_SET_EXT_OBJREF);
5501 }
5502
20a69341 5503 if (nla[NFTA_SET_ELEM_DATA] != NULL) {
fdb9c405
PNA
5504 err = nft_setelem_parse_data(ctx, set, &desc, &elem.data.val,
5505 nla[NFTA_SET_ELEM_DATA]);
20a69341 5506 if (err < 0)
7b225d0b 5507 goto err_parse_key_end;
20a69341 5508
20a69341
PM
5509 dreg = nft_type_to_reg(set->dtype);
5510 list_for_each_entry(binding, &set->bindings, list) {
5511 struct nft_ctx bind_ctx = {
58c78e10 5512 .net = ctx->net,
36596dad 5513 .family = ctx->family,
20a69341 5514 .table = ctx->table,
7c95f6d8 5515 .chain = (struct nft_chain *)binding->chain,
20a69341
PM
5516 };
5517
11113e19
PM
5518 if (!(binding->flags & NFT_SET_MAP))
5519 continue;
5520
1ec10212 5521 err = nft_validate_register_store(&bind_ctx, dreg,
fdb9c405 5522 &elem.data.val,
20a1452c 5523 desc.type, desc.len);
20a69341 5524 if (err < 0)
7b225d0b 5525 goto err_parse_data;
a654de8f 5526
20a1452c 5527 if (desc.type == NFT_DATA_VERDICT &&
fdb9c405
PNA
5528 (elem.data.val.verdict.code == NFT_GOTO ||
5529 elem.data.val.verdict.code == NFT_JUMP))
a654de8f
PNA
5530 nft_validate_state_update(ctx->net,
5531 NFT_VALIDATE_NEED);
20a69341 5532 }
fe2811eb 5533
20a1452c 5534 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_DATA, desc.len);
20a69341
PM
5535 }
5536
68e942e8
PM
5537 /* The full maximum length of userdata can exceed the maximum
5538 * offset value (U8_MAX) for following extensions, therefor it
5539 * must be the last extension added.
5540 */
5541 ulen = 0;
5542 if (nla[NFTA_SET_ELEM_USERDATA] != NULL) {
5543 ulen = nla_len(nla[NFTA_SET_ELEM_USERDATA]);
5544 if (ulen > 0)
5545 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_USERDATA,
5546 ulen);
5547 }
5548
fe2811eb 5549 err = -ENOMEM;
7b225d0b 5550 elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data,
fdb9c405 5551 elem.key_end.val.data, elem.data.val.data,
79ebb5bb 5552 timeout, expiration, GFP_KERNEL);
fe2811eb 5553 if (elem.priv == NULL)
7b225d0b 5554 goto err_parse_data;
fe2811eb
PM
5555
5556 ext = nft_set_elem_ext(set, elem.priv);
5557 if (flags)
5558 *nft_set_ext_flags(ext) = flags;
68e942e8
PM
5559 if (ulen > 0) {
5560 udata = nft_set_ext_userdata(ext);
5561 udata->len = ulen - 1;
5562 nla_memcpy(&udata->data, nla[NFTA_SET_ELEM_USERDATA], ulen);
5563 }
8aeff920
PNA
5564 if (obj) {
5565 *nft_set_ext_obj(ext) = obj;
5566 obj->use++;
5567 }
664899e8 5568 for (i = 0; i < num_exprs; i++)
563125a7 5569 nft_set_elem_expr_setup(ext, i, expr_array);
fe2811eb 5570
60319eb1
PNA
5571 trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set);
5572 if (trans == NULL)
7b225d0b 5573 goto err_trans;
60319eb1 5574
69086658 5575 ext->genmask = nft_genmask_cur(ctx->net) | NFT_SET_ELEM_BUSY_MASK;
c016c7e4
PNA
5576 err = set->ops->insert(ctx->net, set, &elem, &ext2);
5577 if (err) {
5578 if (err == -EEXIST) {
9744a6fc
PNA
5579 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA) ^
5580 nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) ||
5581 nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) ^
77a92189 5582 nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF))
7b225d0b 5583 goto err_element_clash;
8aeff920
PNA
5584 if ((nft_set_ext_exists(ext, NFT_SET_EXT_DATA) &&
5585 nft_set_ext_exists(ext2, NFT_SET_EXT_DATA) &&
5586 memcmp(nft_set_ext_data(ext),
5587 nft_set_ext_data(ext2), set->dlen) != 0) ||
5588 (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
5589 nft_set_ext_exists(ext2, NFT_SET_EXT_OBJREF) &&
5590 *nft_set_ext_obj(ext) != *nft_set_ext_obj(ext2)))
77a92189 5591 goto err_element_clash;
c016c7e4
PNA
5592 else if (!(nlmsg_flags & NLM_F_EXCL))
5593 err = 0;
8c2d45b2
PNA
5594 } else if (err == -ENOTEMPTY) {
5595 /* ENOTEMPTY reports overlapping between this element
5596 * and an existing one.
5597 */
5598 err = -EEXIST;
c016c7e4 5599 }
7b225d0b 5600 goto err_element_clash;
c016c7e4 5601 }
20a69341 5602
35d0ac90
PNA
5603 if (set->size &&
5604 !atomic_add_unless(&set->nelems, 1, set->size + set->ndeact)) {
5605 err = -ENFILE;
7b225d0b 5606 goto err_set_full;
35d0ac90
PNA
5607 }
5608
60319eb1 5609 nft_trans_elem(trans) = elem;
0854db2a 5610 nft_trans_commit_list_add_tail(ctx->net, trans);
20a69341
PM
5611 return 0;
5612
7b225d0b 5613err_set_full:
5cb82a38 5614 set->ops->remove(ctx->net, set, &elem);
7b225d0b 5615err_element_clash:
60319eb1 5616 kfree(trans);
7b225d0b 5617err_trans:
b91d9036
TY
5618 if (obj)
5619 obj->use--;
475beb9c
PNA
5620
5621 nf_tables_set_elem_destroy(ctx, set, elem.priv);
7b225d0b 5622err_parse_data:
20a69341 5623 if (nla[NFTA_SET_ELEM_DATA] != NULL)
fdb9c405 5624 nft_data_release(&elem.data.val, desc.type);
7b225d0b
PNA
5625err_parse_key_end:
5626 nft_data_release(&elem.key_end.val, NFT_DATA_VALUE);
5627err_parse_key:
20a1452c 5628 nft_data_release(&elem.key.val, NFT_DATA_VALUE);
40944452 5629err_set_elem_expr:
664899e8 5630 for (i = 0; i < num_exprs && expr_array[i]; i++)
8cfd9b0f
PNA
5631 nft_expr_destroy(ctx, expr_array[i]);
5632err_set_elem_expr_clone:
20a69341
PM
5633 return err;
5634}
5635
633c9a84
PNA
5636static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
5637 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
5638 const struct nlattr * const nla[],
5639 struct netlink_ext_ack *extack)
20a69341 5640{
0854db2a 5641 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
f2a6d766 5642 u8 genmask = nft_genmask_next(net);
20a69341
PM
5643 const struct nlattr *attr;
5644 struct nft_set *set;
5645 struct nft_ctx ctx;
a654de8f 5646 int rem, err;
20a69341 5647
7d5570ca
PNA
5648 if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
5649 return -EINVAL;
5650
36dd1bcc 5651 err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, extack,
6001a930 5652 genmask, NETLINK_CB(skb).portid);
20a69341
PM
5653 if (err < 0)
5654 return err;
5655
a3073c17
PNA
5656 set = nft_set_lookup_global(net, ctx.table, nla[NFTA_SET_ELEM_LIST_SET],
5657 nla[NFTA_SET_ELEM_LIST_SET_ID], genmask);
5658 if (IS_ERR(set))
5659 return PTR_ERR(set);
958bee14 5660
20a69341
PM
5661 if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
5662 return -EBUSY;
5663
5664 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
c016c7e4 5665 err = nft_add_set_elem(&ctx, set, attr, nlh->nlmsg_flags);
35d0ac90 5666 if (err < 0)
a654de8f 5667 return err;
20a69341 5668 }
a654de8f 5669
0854db2a 5670 if (nft_net->validate_state == NFT_VALIDATE_DO)
a654de8f
PNA
5671 return nft_table_validate(net, ctx.table);
5672
5673 return 0;
20a69341
PM
5674}
5675
59105446
PNA
5676/**
5677 * nft_data_hold - hold a nft_data item
5678 *
5679 * @data: struct nft_data to release
5680 * @type: type of data
5681 *
5682 * Hold a nft_data item. NFT_DATA_VALUE types can be silently discarded,
5683 * NFT_DATA_VERDICT bumps the reference to chains in case of NFT_JUMP and
5684 * NFT_GOTO verdicts. This function must be called on active data objects
5685 * from the second phase of the commit protocol.
5686 */
bb7b40ae 5687void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
59105446 5688{
d0e2c7de
PNA
5689 struct nft_chain *chain;
5690 struct nft_rule *rule;
5691
59105446
PNA
5692 if (type == NFT_DATA_VERDICT) {
5693 switch (data->verdict.code) {
5694 case NFT_JUMP:
5695 case NFT_GOTO:
d0e2c7de
PNA
5696 chain = data->verdict.chain;
5697 chain->use++;
5698
5699 if (!nft_chain_is_bound(chain))
5700 break;
5701
5702 chain->table->use++;
5703 list_for_each_entry(rule, &chain->rules, list)
5704 chain->use++;
5705
5706 nft_chain_add(chain->table, chain);
59105446
PNA
5707 break;
5708 }
5709 }
5710}
5711
5712static void nft_set_elem_activate(const struct net *net,
5713 const struct nft_set *set,
5714 struct nft_set_elem *elem)
5715{
5716 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
5717
5718 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
5719 nft_data_hold(nft_set_ext_data(ext), set->dtype);
5720 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
5721 (*nft_set_ext_obj(ext))->use++;
5722}
5723
5724static void nft_set_elem_deactivate(const struct net *net,
5725 const struct nft_set *set,
5726 struct nft_set_elem *elem)
5727{
5728 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
5729
5730 if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
5731 nft_data_release(nft_set_ext_data(ext), set->dtype);
5732 if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
5733 (*nft_set_ext_obj(ext))->use--;
5734}
5735
60319eb1 5736static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
20a69341
PM
5737 const struct nlattr *attr)
5738{
5739 struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
3971ca14 5740 struct nft_set_ext_tmpl tmpl;
20a69341 5741 struct nft_set_elem elem;
3971ca14 5742 struct nft_set_ext *ext;
60319eb1 5743 struct nft_trans *trans;
3971ca14
PNA
5744 u32 flags = 0;
5745 void *priv;
20a69341
PM
5746 int err;
5747
8cb08174
JB
5748 err = nla_parse_nested_deprecated(nla, NFTA_SET_ELEM_MAX, attr,
5749 nft_set_elem_policy, NULL);
20a69341 5750 if (err < 0)
20a1452c 5751 return err;
20a69341 5752
20a69341 5753 if (nla[NFTA_SET_ELEM_KEY] == NULL)
20a1452c 5754 return -EINVAL;
20a69341 5755
3971ca14
PNA
5756 nft_set_ext_prepare(&tmpl);
5757
5758 err = nft_setelem_parse_flags(set, nla[NFTA_SET_ELEM_FLAGS], &flags);
5759 if (err < 0)
5760 return err;
5761 if (flags != 0)
5762 nft_set_ext_add(&tmpl, NFT_SET_EXT_FLAGS);
5763
20a1452c
PNA
5764 err = nft_setelem_parse_key(ctx, set, &elem.key.val,
5765 nla[NFTA_SET_ELEM_KEY]);
20a69341 5766 if (err < 0)
20a1452c 5767 return err;
20a69341 5768
20a1452c 5769 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY, set->klen);
3971ca14 5770
7b225d0b
PNA
5771 if (nla[NFTA_SET_ELEM_KEY_END]) {
5772 err = nft_setelem_parse_key(ctx, set, &elem.key_end.val,
5773 nla[NFTA_SET_ELEM_KEY_END]);
5774 if (err < 0)
5775 return err;
5776
5777 nft_set_ext_add_length(&tmpl, NFT_SET_EXT_KEY_END, set->klen);
5778 }
5779
3971ca14 5780 err = -ENOMEM;
7b225d0b
PNA
5781 elem.priv = nft_set_elem_init(set, &tmpl, elem.key.val.data,
5782 elem.key_end.val.data, NULL, 0, 0,
5783 GFP_KERNEL);
3971ca14 5784 if (elem.priv == NULL)
20a1452c 5785 goto fail_elem;
3971ca14
PNA
5786
5787 ext = nft_set_elem_ext(set, elem.priv);
5788 if (flags)
5789 *nft_set_ext_flags(ext) = flags;
5790
60319eb1 5791 trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set);
20a1452c
PNA
5792 if (trans == NULL)
5793 goto fail_trans;
20a69341 5794
42a55769 5795 priv = set->ops->deactivate(ctx->net, set, &elem);
3971ca14 5796 if (priv == NULL) {
cc02e457 5797 err = -ENOENT;
20a1452c 5798 goto fail_ops;
cc02e457 5799 }
3971ca14
PNA
5800 kfree(elem.priv);
5801 elem.priv = priv;
cc02e457 5802
59105446
PNA
5803 nft_set_elem_deactivate(ctx->net, set, &elem);
5804
60319eb1 5805 nft_trans_elem(trans) = elem;
0854db2a 5806 nft_trans_commit_list_add_tail(ctx->net, trans);
0dc13625 5807 return 0;
cc02e457 5808
20a1452c 5809fail_ops:
cc02e457 5810 kfree(trans);
20a1452c 5811fail_trans:
3971ca14 5812 kfree(elem.priv);
20a1452c
PNA
5813fail_elem:
5814 nft_data_release(&elem.key.val, NFT_DATA_VALUE);
20a69341
PM
5815 return err;
5816}
5817
8411b644 5818static int nft_flush_set(const struct nft_ctx *ctx,
de70185d 5819 struct nft_set *set,
8411b644 5820 const struct nft_set_iter *iter,
de70185d 5821 struct nft_set_elem *elem)
8411b644
PNA
5822{
5823 struct nft_trans *trans;
5824 int err;
5825
5826 trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM,
5827 sizeof(struct nft_trans_elem), GFP_ATOMIC);
5828 if (!trans)
5829 return -ENOMEM;
5830
1ba1c414 5831 if (!set->ops->flush(ctx->net, set, elem->priv)) {
8411b644
PNA
5832 err = -ENOENT;
5833 goto err1;
5834 }
b2c11e4b 5835 set->ndeact++;
8411b644 5836
7acfda53 5837 nft_set_elem_deactivate(ctx->net, set, elem);
de70185d
PNA
5838 nft_trans_elem_set(trans) = set;
5839 nft_trans_elem(trans) = *elem;
0854db2a 5840 nft_trans_commit_list_add_tail(ctx->net, trans);
8411b644
PNA
5841
5842 return 0;
5843err1:
5844 kfree(trans);
5845 return err;
5846}
5847
633c9a84
PNA
5848static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
5849 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
5850 const struct nlattr * const nla[],
5851 struct netlink_ext_ack *extack)
20a69341 5852{
f2a6d766 5853 u8 genmask = nft_genmask_next(net);
20a69341
PM
5854 const struct nlattr *attr;
5855 struct nft_set *set;
5856 struct nft_ctx ctx;
60319eb1 5857 int rem, err = 0;
20a69341 5858
36dd1bcc 5859 err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, extack,
6001a930 5860 genmask, NETLINK_CB(skb).portid);
20a69341
PM
5861 if (err < 0)
5862 return err;
5863
cac20fcd 5864 set = nft_set_lookup(ctx.table, nla[NFTA_SET_ELEM_LIST_SET], genmask);
20a69341
PM
5865 if (IS_ERR(set))
5866 return PTR_ERR(set);
5867 if (!list_empty(&set->bindings) && set->flags & NFT_SET_CONSTANT)
5868 return -EBUSY;
5869
8411b644 5870 if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) {
baa2d42c
PNA
5871 struct nft_set_iter iter = {
5872 .genmask = genmask,
5873 .fn = nft_flush_set,
8411b644 5874 };
baa2d42c 5875 set->ops->walk(&ctx, set, &iter);
8411b644 5876
baa2d42c 5877 return iter.err;
8411b644
PNA
5878 }
5879
20a69341
PM
5880 nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
5881 err = nft_del_setelem(&ctx, set, attr);
5882 if (err < 0)
60319eb1 5883 break;
4fefee57 5884
3dd0673a 5885 set->ndeact++;
20a69341 5886 }
60319eb1 5887 return err;
20a69341
PM
5888}
5889
cfed7e1b
PM
5890void nft_set_gc_batch_release(struct rcu_head *rcu)
5891{
5892 struct nft_set_gc_batch *gcb;
5893 unsigned int i;
5894
5895 gcb = container_of(rcu, struct nft_set_gc_batch, head.rcu);
5896 for (i = 0; i < gcb->head.cnt; i++)
61f9e292 5897 nft_set_elem_destroy(gcb->head.set, gcb->elems[i], true);
cfed7e1b
PM
5898 kfree(gcb);
5899}
cfed7e1b
PM
5900
5901struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
5902 gfp_t gfp)
5903{
5904 struct nft_set_gc_batch *gcb;
5905
5906 gcb = kzalloc(sizeof(*gcb), gfp);
5907 if (gcb == NULL)
5908 return gcb;
5909 gcb->head.set = set;
5910 return gcb;
5911}
cfed7e1b 5912
e5009240
PNA
5913/*
5914 * Stateful objects
5915 */
5916
5917/**
5918 * nft_register_obj- register nf_tables stateful object type
3db86c39 5919 * @obj_type: object type
e5009240
PNA
5920 *
5921 * Registers the object type for use with nf_tables. Returns zero on
5922 * success or a negative errno code otherwise.
5923 */
5924int nft_register_obj(struct nft_object_type *obj_type)
5925{
5926 if (obj_type->type == NFT_OBJECT_UNSPEC)
5927 return -EINVAL;
5928
5929 nfnl_lock(NFNL_SUBSYS_NFTABLES);
5930 list_add_rcu(&obj_type->list, &nf_tables_objects);
5931 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
5932 return 0;
5933}
5934EXPORT_SYMBOL_GPL(nft_register_obj);
5935
5936/**
5937 * nft_unregister_obj - unregister nf_tables object type
3db86c39 5938 * @obj_type: object type
e5009240
PNA
5939 *
5940 * Unregisters the object type for use with nf_tables.
5941 */
5942void nft_unregister_obj(struct nft_object_type *obj_type)
5943{
5944 nfnl_lock(NFNL_SUBSYS_NFTABLES);
5945 list_del_rcu(&obj_type->list);
5946 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
5947}
5948EXPORT_SYMBOL_GPL(nft_unregister_obj);
5949
4d44175a
FW
5950struct nft_object *nft_obj_lookup(const struct net *net,
5951 const struct nft_table *table,
cac20fcd
PNA
5952 const struct nlattr *nla, u32 objtype,
5953 u8 genmask)
e5009240 5954{
4d44175a
FW
5955 struct nft_object_hash_key k = { .table = table };
5956 char search[NFT_OBJ_MAXNAMELEN];
5957 struct rhlist_head *tmp, *list;
e5009240
PNA
5958 struct nft_object *obj;
5959
872f6903 5960 nla_strscpy(search, nla, sizeof(search));
4d44175a
FW
5961 k.name = search;
5962
5963 WARN_ON_ONCE(!rcu_read_lock_held() &&
5964 !lockdep_commit_lock_is_held(net));
5965
5966 rcu_read_lock();
5967 list = rhltable_lookup(&nft_objname_ht, &k, nft_objname_ht_params);
5968 if (!list)
5969 goto out;
5970
5971 rhl_for_each_entry_rcu(obj, tmp, list, rhlhead) {
5972 if (objtype == obj->ops->type->type &&
5973 nft_active_genmask(obj, genmask)) {
5974 rcu_read_unlock();
e5009240 5975 return obj;
4d44175a 5976 }
e5009240 5977 }
4d44175a
FW
5978out:
5979 rcu_read_unlock();
e5009240
PNA
5980 return ERR_PTR(-ENOENT);
5981}
cac20fcd 5982EXPORT_SYMBOL_GPL(nft_obj_lookup);
e5009240 5983
cac20fcd
PNA
5984static struct nft_object *nft_obj_lookup_byhandle(const struct nft_table *table,
5985 const struct nlattr *nla,
5986 u32 objtype, u8 genmask)
3ecbfd65
HS
5987{
5988 struct nft_object *obj;
5989
5990 list_for_each_entry(obj, &table->objects, list) {
5991 if (be64_to_cpu(nla_get_be64(nla)) == obj->handle &&
5992 objtype == obj->ops->type->type &&
5993 nft_active_genmask(obj, genmask))
5994 return obj;
5995 }
5996 return ERR_PTR(-ENOENT);
5997}
5998
e5009240 5999static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
b2fbd044
LZ
6000 [NFTA_OBJ_TABLE] = { .type = NLA_STRING,
6001 .len = NFT_TABLE_MAXNAMELEN - 1 },
6002 [NFTA_OBJ_NAME] = { .type = NLA_STRING,
6003 .len = NFT_OBJ_MAXNAMELEN - 1 },
e5009240
PNA
6004 [NFTA_OBJ_TYPE] = { .type = NLA_U32 },
6005 [NFTA_OBJ_DATA] = { .type = NLA_NESTED },
3ecbfd65 6006 [NFTA_OBJ_HANDLE] = { .type = NLA_U64},
b131c964
JGG
6007 [NFTA_OBJ_USERDATA] = { .type = NLA_BINARY,
6008 .len = NFT_USERDATA_MAXLEN },
e5009240
PNA
6009};
6010
84fba055
FW
6011static struct nft_object *nft_obj_init(const struct nft_ctx *ctx,
6012 const struct nft_object_type *type,
e5009240
PNA
6013 const struct nlattr *attr)
6014{
5b4c6e38 6015 struct nlattr **tb;
dfc46034 6016 const struct nft_object_ops *ops;
e5009240 6017 struct nft_object *obj;
5b4c6e38
GS
6018 int err = -ENOMEM;
6019
6020 tb = kmalloc_array(type->maxattr + 1, sizeof(*tb), GFP_KERNEL);
6021 if (!tb)
6022 goto err1;
e5009240
PNA
6023
6024 if (attr) {
8cb08174
JB
6025 err = nla_parse_nested_deprecated(tb, type->maxattr, attr,
6026 type->policy, NULL);
e5009240 6027 if (err < 0)
5b4c6e38 6028 goto err2;
e5009240
PNA
6029 } else {
6030 memset(tb, 0, sizeof(tb[0]) * (type->maxattr + 1));
6031 }
6032
dfc46034
PBG
6033 if (type->select_ops) {
6034 ops = type->select_ops(ctx, (const struct nlattr * const *)tb);
6035 if (IS_ERR(ops)) {
6036 err = PTR_ERR(ops);
5b4c6e38 6037 goto err2;
dfc46034
PBG
6038 }
6039 } else {
6040 ops = type->ops;
6041 }
6042
e5009240 6043 err = -ENOMEM;
dfc46034 6044 obj = kzalloc(sizeof(*obj) + ops->size, GFP_KERNEL);
5b4c6e38
GS
6045 if (!obj)
6046 goto err2;
e5009240 6047
dfc46034 6048 err = ops->init(ctx, (const struct nlattr * const *)tb, obj);
e5009240 6049 if (err < 0)
5b4c6e38 6050 goto err3;
e5009240 6051
dfc46034
PBG
6052 obj->ops = ops;
6053
5b4c6e38 6054 kfree(tb);
e5009240 6055 return obj;
5b4c6e38 6056err3:
e5009240 6057 kfree(obj);
5b4c6e38
GS
6058err2:
6059 kfree(tb);
e5009240
PNA
6060err1:
6061 return ERR_PTR(err);
6062}
6063
6064static int nft_object_dump(struct sk_buff *skb, unsigned int attr,
43da04a5 6065 struct nft_object *obj, bool reset)
e5009240
PNA
6066{
6067 struct nlattr *nest;
6068
ae0be8de 6069 nest = nla_nest_start_noflag(skb, attr);
e5009240
PNA
6070 if (!nest)
6071 goto nla_put_failure;
dfc46034 6072 if (obj->ops->dump(skb, obj, reset) < 0)
e5009240
PNA
6073 goto nla_put_failure;
6074 nla_nest_end(skb, nest);
6075 return 0;
6076
6077nla_put_failure:
6078 return -1;
6079}
6080
6081static const struct nft_object_type *__nft_obj_type_get(u32 objtype)
6082{
6083 const struct nft_object_type *type;
6084
6085 list_for_each_entry(type, &nf_tables_objects, list) {
6086 if (objtype == type->type)
6087 return type;
6088 }
6089 return NULL;
6090}
6091
452238e8
FW
6092static const struct nft_object_type *
6093nft_obj_type_get(struct net *net, u32 objtype)
e5009240
PNA
6094{
6095 const struct nft_object_type *type;
6096
6097 type = __nft_obj_type_get(objtype);
6098 if (type != NULL && try_module_get(type->owner))
6099 return type;
6100
f102d66b 6101 lockdep_nfnl_nft_mutex_not_held();
e5009240
PNA
6102#ifdef CONFIG_MODULES
6103 if (type == NULL) {
eb014de4 6104 if (nft_request_module(net, "nft-obj-%u", objtype) == -EAGAIN)
e5009240
PNA
6105 return ERR_PTR(-EAGAIN);
6106 }
6107#endif
6108 return ERR_PTR(-ENOENT);
6109}
6110
d62d0ba9
FFM
6111static int nf_tables_updobj(const struct nft_ctx *ctx,
6112 const struct nft_object_type *type,
6113 const struct nlattr *attr,
6114 struct nft_object *obj)
6115{
6116 struct nft_object *newobj;
6117 struct nft_trans *trans;
6118 int err;
6119
6120 trans = nft_trans_alloc(ctx, NFT_MSG_NEWOBJ,
6121 sizeof(struct nft_trans_obj));
6122 if (!trans)
6123 return -ENOMEM;
6124
6125 newobj = nft_obj_init(ctx, type, attr);
6126 if (IS_ERR(newobj)) {
6127 err = PTR_ERR(newobj);
b74ae961 6128 goto err_free_trans;
d62d0ba9
FFM
6129 }
6130
6131 nft_trans_obj(trans) = obj;
6132 nft_trans_obj_update(trans) = true;
6133 nft_trans_obj_newobj(trans) = newobj;
0854db2a 6134 nft_trans_commit_list_add_tail(ctx->net, trans);
d62d0ba9
FFM
6135
6136 return 0;
b74ae961
DC
6137
6138err_free_trans:
d62d0ba9 6139 kfree(trans);
d62d0ba9
FFM
6140 return err;
6141}
6142
e5009240
PNA
6143static int nf_tables_newobj(struct net *net, struct sock *nlsk,
6144 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
6145 const struct nlattr * const nla[],
6146 struct netlink_ext_ack *extack)
e5009240
PNA
6147{
6148 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
6149 const struct nft_object_type *type;
6150 u8 genmask = nft_genmask_next(net);
6151 int family = nfmsg->nfgen_family;
e5009240
PNA
6152 struct nft_table *table;
6153 struct nft_object *obj;
6154 struct nft_ctx ctx;
6155 u32 objtype;
6156 int err;
6157
6158 if (!nla[NFTA_OBJ_TYPE] ||
6159 !nla[NFTA_OBJ_NAME] ||
6160 !nla[NFTA_OBJ_DATA])
6161 return -EINVAL;
6162
6001a930
PNA
6163 table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask,
6164 NETLINK_CB(skb).portid);
36dd1bcc
PNA
6165 if (IS_ERR(table)) {
6166 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]);
e5009240 6167 return PTR_ERR(table);
36dd1bcc 6168 }
e5009240
PNA
6169
6170 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
4d44175a 6171 obj = nft_obj_lookup(net, table, nla[NFTA_OBJ_NAME], objtype, genmask);
e5009240
PNA
6172 if (IS_ERR(obj)) {
6173 err = PTR_ERR(obj);
36dd1bcc
PNA
6174 if (err != -ENOENT) {
6175 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]);
e5009240 6176 return err;
36dd1bcc 6177 }
1a28ad74 6178 } else {
36dd1bcc
PNA
6179 if (nlh->nlmsg_flags & NLM_F_EXCL) {
6180 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]);
e5009240 6181 return -EEXIST;
36dd1bcc 6182 }
d62d0ba9
FFM
6183 if (nlh->nlmsg_flags & NLM_F_REPLACE)
6184 return -EOPNOTSUPP;
6185
fd57d0cb 6186 type = __nft_obj_type_get(objtype);
d62d0ba9
FFM
6187 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
6188
6189 return nf_tables_updobj(&ctx, type, nla[NFTA_OBJ_DATA], obj);
e5009240
PNA
6190 }
6191
98319cb9 6192 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
e5009240 6193
452238e8 6194 type = nft_obj_type_get(net, objtype);
e5009240
PNA
6195 if (IS_ERR(type))
6196 return PTR_ERR(type);
6197
84fba055 6198 obj = nft_obj_init(&ctx, type, nla[NFTA_OBJ_DATA]);
e5009240
PNA
6199 if (IS_ERR(obj)) {
6200 err = PTR_ERR(obj);
b131c964 6201 goto err_init;
e5009240 6202 }
d152159b 6203 obj->key.table = table;
3ecbfd65
HS
6204 obj->handle = nf_tables_alloc_handle(table);
6205
d152159b
FW
6206 obj->key.name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL);
6207 if (!obj->key.name) {
61509575 6208 err = -ENOMEM;
b131c964
JGG
6209 goto err_strdup;
6210 }
6211
6212 if (nla[NFTA_OBJ_USERDATA]) {
85db827a 6213 obj->udata = nla_memdup(nla[NFTA_OBJ_USERDATA], GFP_KERNEL);
b131c964
JGG
6214 if (obj->udata == NULL)
6215 goto err_userdata;
6216
85db827a 6217 obj->udlen = nla_len(nla[NFTA_OBJ_USERDATA]);
61509575 6218 }
e5009240
PNA
6219
6220 err = nft_trans_obj_add(&ctx, NFT_MSG_NEWOBJ, obj);
6221 if (err < 0)
b131c964 6222 goto err_trans;
e5009240 6223
4d44175a
FW
6224 err = rhltable_insert(&nft_objname_ht, &obj->rhlhead,
6225 nft_objname_ht_params);
6226 if (err < 0)
b131c964 6227 goto err_obj_ht;
4d44175a 6228
e5009240
PNA
6229 list_add_tail_rcu(&obj->list, &table->objects);
6230 table->use++;
6231 return 0;
b131c964 6232err_obj_ht:
4d44175a
FW
6233 /* queued in transaction log */
6234 INIT_LIST_HEAD(&obj->list);
6235 return err;
b131c964 6236err_trans:
d152159b 6237 kfree(obj->key.name);
b131c964
JGG
6238err_userdata:
6239 kfree(obj->udata);
6240err_strdup:
dfc46034 6241 if (obj->ops->destroy)
00bfb320 6242 obj->ops->destroy(&ctx, obj);
e5009240 6243 kfree(obj);
b131c964 6244err_init:
e5009240
PNA
6245 module_put(type->owner);
6246 return err;
6247}
6248
6249static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net,
6250 u32 portid, u32 seq, int event, u32 flags,
6251 int family, const struct nft_table *table,
43da04a5 6252 struct nft_object *obj, bool reset)
e5009240 6253{
e5009240
PNA
6254 struct nlmsghdr *nlh;
6255
dedb67c4 6256 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
19c28b13
PNA
6257 nlh = nfnl_msg_put(skb, portid, seq, event, flags, family,
6258 NFNETLINK_V0, nft_base_seq(net));
6259 if (!nlh)
e5009240
PNA
6260 goto nla_put_failure;
6261
e5009240 6262 if (nla_put_string(skb, NFTA_OBJ_TABLE, table->name) ||
d152159b 6263 nla_put_string(skb, NFTA_OBJ_NAME, obj->key.name) ||
dfc46034 6264 nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) ||
e5009240 6265 nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) ||
3ecbfd65
HS
6266 nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) ||
6267 nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle),
6268 NFTA_OBJ_PAD))
e5009240
PNA
6269 goto nla_put_failure;
6270
b131c964
JGG
6271 if (obj->udata &&
6272 nla_put(skb, NFTA_OBJ_USERDATA, obj->udlen, obj->udata))
6273 goto nla_put_failure;
6274
e5009240
PNA
6275 nlmsg_end(skb, nlh);
6276 return 0;
6277
6278nla_put_failure:
6279 nlmsg_trim(skb, nlh);
6280 return -1;
6281}
6282
a9fea2a3 6283struct nft_obj_filter {
e46abbcc 6284 char *table;
a9fea2a3
PNA
6285 u32 type;
6286};
6287
e5009240
PNA
6288static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
6289{
6290 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
e5009240 6291 const struct nft_table *table;
e5009240 6292 unsigned int idx = 0, s_idx = cb->args[0];
a9fea2a3 6293 struct nft_obj_filter *filter = cb->data;
e5009240
PNA
6294 struct net *net = sock_net(skb->sk);
6295 int family = nfmsg->nfgen_family;
0854db2a 6296 struct nftables_pernet *nft_net;
43da04a5
PNA
6297 struct nft_object *obj;
6298 bool reset = false;
6299
6300 if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
6301 reset = true;
e5009240
PNA
6302
6303 rcu_read_lock();
0854db2a
FW
6304 nft_net = net_generic(net, nf_tables_net_id);
6305 cb->seq = nft_net->base_seq;
e5009240 6306
0854db2a 6307 list_for_each_entry_rcu(table, &nft_net->tables, list) {
98319cb9 6308 if (family != NFPROTO_UNSPEC && family != table->family)
e5009240
PNA
6309 continue;
6310
36596dad
PNA
6311 list_for_each_entry_rcu(obj, &table->objects, list) {
6312 if (!nft_is_active(net, obj))
6313 goto cont;
6314 if (idx < s_idx)
6315 goto cont;
6316 if (idx > s_idx)
6317 memset(&cb->args[1], 0,
6318 sizeof(cb->args) - sizeof(cb->args[0]));
360cc79d 6319 if (filter && filter->table &&
36596dad
PNA
6320 strcmp(filter->table, table->name))
6321 goto cont;
6322 if (filter &&
6323 filter->type != NFT_OBJECT_UNSPEC &&
6324 obj->ops->type->type != filter->type)
6325 goto cont;
8e6cf365 6326 if (reset) {
68df2ed5 6327 char *buf = kasprintf(GFP_ATOMIC,
c520292f 6328 "%s:%u",
8e6cf365 6329 table->name,
0854db2a 6330 nft_net->base_seq);
8e6cf365
RGB
6331
6332 audit_log_nfcfg(buf,
6333 family,
6334 obj->handle,
14224039 6335 AUDIT_NFT_OP_OBJ_RESET,
68df2ed5 6336 GFP_ATOMIC);
8e6cf365
RGB
6337 kfree(buf);
6338 }
6339
36596dad
PNA
6340 if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid,
6341 cb->nlh->nlmsg_seq,
6342 NFT_MSG_NEWOBJ,
6343 NLM_F_MULTI | NLM_F_APPEND,
98319cb9 6344 table->family, table,
36596dad
PNA
6345 obj, reset) < 0)
6346 goto done;
e5009240 6347
36596dad 6348 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
e5009240 6349cont:
36596dad 6350 idx++;
e5009240
PNA
6351 }
6352 }
6353done:
6354 rcu_read_unlock();
6355
6356 cb->args[0] = idx;
6357 return skb->len;
6358}
6359
90fd131a 6360static int nf_tables_dump_obj_start(struct netlink_callback *cb)
a9fea2a3 6361{
90fd131a
FW
6362 const struct nlattr * const *nla = cb->data;
6363 struct nft_obj_filter *filter = NULL;
e46abbcc 6364
90fd131a
FW
6365 if (nla[NFTA_OBJ_TABLE] || nla[NFTA_OBJ_TYPE]) {
6366 filter = kzalloc(sizeof(*filter), GFP_ATOMIC);
6367 if (!filter)
6368 return -ENOMEM;
6369
6370 if (nla[NFTA_OBJ_TABLE]) {
6371 filter->table = nla_strdup(nla[NFTA_OBJ_TABLE], GFP_ATOMIC);
6372 if (!filter->table) {
6373 kfree(filter);
6374 return -ENOMEM;
6375 }
6376 }
6377
6378 if (nla[NFTA_OBJ_TYPE])
6379 filter->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
8bea728d 6380 }
a9fea2a3 6381
90fd131a 6382 cb->data = filter;
a9fea2a3
PNA
6383 return 0;
6384}
6385
90fd131a 6386static int nf_tables_dump_obj_done(struct netlink_callback *cb)
a9fea2a3 6387{
90fd131a 6388 struct nft_obj_filter *filter = cb->data;
a9fea2a3 6389
90fd131a
FW
6390 if (filter) {
6391 kfree(filter->table);
6392 kfree(filter);
e46abbcc 6393 }
a9fea2a3 6394
90fd131a 6395 return 0;
a9fea2a3
PNA
6396}
6397
d9adf22a 6398/* called with rcu_read_lock held */
e5009240
PNA
6399static int nf_tables_getobj(struct net *net, struct sock *nlsk,
6400 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
6401 const struct nlattr * const nla[],
6402 struct netlink_ext_ack *extack)
e5009240
PNA
6403{
6404 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
6405 u8 genmask = nft_genmask_cur(net);
6406 int family = nfmsg->nfgen_family;
e5009240
PNA
6407 const struct nft_table *table;
6408 struct nft_object *obj;
6409 struct sk_buff *skb2;
43da04a5 6410 bool reset = false;
e5009240
PNA
6411 u32 objtype;
6412 int err;
6413
6414 if (nlh->nlmsg_flags & NLM_F_DUMP) {
6415 struct netlink_dump_control c = {
90fd131a 6416 .start = nf_tables_dump_obj_start,
e5009240 6417 .dump = nf_tables_dump_obj,
a9fea2a3 6418 .done = nf_tables_dump_obj_done,
d9adf22a 6419 .module = THIS_MODULE,
90fd131a 6420 .data = (void *)nla,
e5009240 6421 };
a9fea2a3 6422
d9adf22a 6423 return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
e5009240
PNA
6424 }
6425
6426 if (!nla[NFTA_OBJ_NAME] ||
6427 !nla[NFTA_OBJ_TYPE])
6428 return -EINVAL;
6429
6001a930 6430 table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask, 0);
36dd1bcc
PNA
6431 if (IS_ERR(table)) {
6432 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]);
e5009240 6433 return PTR_ERR(table);
36dd1bcc 6434 }
e5009240
PNA
6435
6436 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
4d44175a 6437 obj = nft_obj_lookup(net, table, nla[NFTA_OBJ_NAME], objtype, genmask);
36dd1bcc
PNA
6438 if (IS_ERR(obj)) {
6439 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_NAME]);
e5009240 6440 return PTR_ERR(obj);
36dd1bcc 6441 }
e5009240 6442
d9adf22a 6443 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
e5009240
PNA
6444 if (!skb2)
6445 return -ENOMEM;
6446
43da04a5
PNA
6447 if (NFNL_MSG_TYPE(nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
6448 reset = true;
6449
8e6cf365 6450 if (reset) {
0854db2a
FW
6451 const struct nftables_pernet *nft_net;
6452 char *buf;
6453
6454 nft_net = net_generic(net, nf_tables_net_id);
6455 buf = kasprintf(GFP_ATOMIC, "%s:%u", table->name, nft_net->base_seq);
8e6cf365
RGB
6456
6457 audit_log_nfcfg(buf,
6458 family,
6459 obj->handle,
14224039 6460 AUDIT_NFT_OP_OBJ_RESET,
68df2ed5 6461 GFP_ATOMIC);
8e6cf365
RGB
6462 kfree(buf);
6463 }
6464
e5009240
PNA
6465 err = nf_tables_fill_obj_info(skb2, net, NETLINK_CB(skb).portid,
6466 nlh->nlmsg_seq, NFT_MSG_NEWOBJ, 0,
43da04a5 6467 family, table, obj, reset);
e5009240 6468 if (err < 0)
ee921183 6469 goto err_fill_obj_info;
e5009240 6470
ee921183
PNA
6471 return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
6472
6473err_fill_obj_info:
e5009240
PNA
6474 kfree_skb(skb2);
6475 return err;
e5009240
PNA
6476}
6477
00bfb320 6478static void nft_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj)
e5009240 6479{
dfc46034 6480 if (obj->ops->destroy)
00bfb320 6481 obj->ops->destroy(ctx, obj);
e5009240 6482
dfc46034 6483 module_put(obj->ops->type->owner);
d152159b 6484 kfree(obj->key.name);
bc7a7082 6485 kfree(obj->udata);
e5009240
PNA
6486 kfree(obj);
6487}
6488
6489static int nf_tables_delobj(struct net *net, struct sock *nlsk,
04ba724b
PNA
6490 struct sk_buff *skb, const struct nlmsghdr *nlh,
6491 const struct nlattr * const nla[],
6492 struct netlink_ext_ack *extack)
e5009240
PNA
6493{
6494 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
6495 u8 genmask = nft_genmask_next(net);
6496 int family = nfmsg->nfgen_family;
36dd1bcc 6497 const struct nlattr *attr;
e5009240
PNA
6498 struct nft_table *table;
6499 struct nft_object *obj;
6500 struct nft_ctx ctx;
6501 u32 objtype;
6502
6503 if (!nla[NFTA_OBJ_TYPE] ||
3ecbfd65 6504 (!nla[NFTA_OBJ_NAME] && !nla[NFTA_OBJ_HANDLE]))
e5009240
PNA
6505 return -EINVAL;
6506
6001a930
PNA
6507 table = nft_table_lookup(net, nla[NFTA_OBJ_TABLE], family, genmask,
6508 NETLINK_CB(skb).portid);
36dd1bcc
PNA
6509 if (IS_ERR(table)) {
6510 NL_SET_BAD_ATTR(extack, nla[NFTA_OBJ_TABLE]);
e5009240 6511 return PTR_ERR(table);
36dd1bcc 6512 }
e5009240
PNA
6513
6514 objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
36dd1bcc
PNA
6515 if (nla[NFTA_OBJ_HANDLE]) {
6516 attr = nla[NFTA_OBJ_HANDLE];
6517 obj = nft_obj_lookup_byhandle(table, attr, objtype, genmask);
6518 } else {
6519 attr = nla[NFTA_OBJ_NAME];
4d44175a 6520 obj = nft_obj_lookup(net, table, attr, objtype, genmask);
36dd1bcc
PNA
6521 }
6522
6523 if (IS_ERR(obj)) {
6524 NL_SET_BAD_ATTR(extack, attr);
e5009240 6525 return PTR_ERR(obj);
36dd1bcc
PNA
6526 }
6527 if (obj->use > 0) {
6528 NL_SET_BAD_ATTR(extack, attr);
e5009240 6529 return -EBUSY;
36dd1bcc 6530 }
e5009240 6531
98319cb9 6532 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
e5009240
PNA
6533
6534 return nft_delobj(&ctx, obj);
6535}
6536
d152159b 6537void nft_obj_notify(struct net *net, const struct nft_table *table,
25e94a99
PNA
6538 struct nft_object *obj, u32 portid, u32 seq, int event,
6539 int family, int report, gfp_t gfp)
e5009240 6540{
0854db2a 6541 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
e5009240
PNA
6542 struct sk_buff *skb;
6543 int err;
c520292f 6544 char *buf = kasprintf(gfp, "%s:%u",
0854db2a 6545 table->name, nft_net->base_seq);
8e6cf365
RGB
6546
6547 audit_log_nfcfg(buf,
6548 family,
6549 obj->handle,
6550 event == NFT_MSG_NEWOBJ ?
c520292f
RGB
6551 AUDIT_NFT_OP_OBJ_REGISTER :
6552 AUDIT_NFT_OP_OBJ_UNREGISTER,
68df2ed5 6553 gfp);
8e6cf365 6554 kfree(buf);
e5009240 6555
2599e989
PNA
6556 if (!report &&
6557 !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
25e94a99 6558 return;
e5009240 6559
2599e989 6560 skb = nlmsg_new(NLMSG_GOODSIZE, gfp);
e5009240
PNA
6561 if (skb == NULL)
6562 goto err;
6563
2599e989
PNA
6564 err = nf_tables_fill_obj_info(skb, net, portid, seq, event, 0, family,
6565 table, obj, false);
e5009240
PNA
6566 if (err < 0) {
6567 kfree_skb(skb);
6568 goto err;
6569 }
6570
0854db2a 6571 nft_notify_enqueue(skb, report, &nft_net->notify_list);
25e94a99 6572 return;
e5009240 6573err:
25e94a99 6574 nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS);
e5009240 6575}
2599e989
PNA
6576EXPORT_SYMBOL_GPL(nft_obj_notify);
6577
25e94a99
PNA
6578static void nf_tables_obj_notify(const struct nft_ctx *ctx,
6579 struct nft_object *obj, int event)
2599e989 6580{
25e94a99 6581 nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event,
36596dad 6582 ctx->family, ctx->report, GFP_KERNEL);
2599e989 6583}
e5009240 6584
3b49e2e9
PNA
6585/*
6586 * Flow tables
6587 */
6588void nft_register_flowtable_type(struct nf_flowtable_type *type)
6589{
6590 nfnl_lock(NFNL_SUBSYS_NFTABLES);
6591 list_add_tail_rcu(&type->list, &nf_tables_flowtables);
6592 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
6593}
6594EXPORT_SYMBOL_GPL(nft_register_flowtable_type);
6595
6596void nft_unregister_flowtable_type(struct nf_flowtable_type *type)
6597{
6598 nfnl_lock(NFNL_SUBSYS_NFTABLES);
6599 list_del_rcu(&type->list);
6600 nfnl_unlock(NFNL_SUBSYS_NFTABLES);
6601}
6602EXPORT_SYMBOL_GPL(nft_unregister_flowtable_type);
6603
6604static const struct nla_policy nft_flowtable_policy[NFTA_FLOWTABLE_MAX + 1] = {
6605 [NFTA_FLOWTABLE_TABLE] = { .type = NLA_STRING,
6606 .len = NFT_NAME_MAXLEN - 1 },
6607 [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING,
6608 .len = NFT_NAME_MAXLEN - 1 },
6609 [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED },
3ecbfd65 6610 [NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 },
8bb69f3b 6611 [NFTA_FLOWTABLE_FLAGS] = { .type = NLA_U32 },
3b49e2e9
PNA
6612};
6613
cac20fcd
PNA
6614struct nft_flowtable *nft_flowtable_lookup(const struct nft_table *table,
6615 const struct nlattr *nla, u8 genmask)
3b49e2e9
PNA
6616{
6617 struct nft_flowtable *flowtable;
6618
d9adf22a 6619 list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
3b49e2e9
PNA
6620 if (!nla_strcmp(nla, flowtable->name) &&
6621 nft_active_genmask(flowtable, genmask))
6622 return flowtable;
6623 }
6624 return ERR_PTR(-ENOENT);
6625}
cac20fcd 6626EXPORT_SYMBOL_GPL(nft_flowtable_lookup);
3b49e2e9 6627
9b05b6e1
LGL
6628void nf_tables_deactivate_flowtable(const struct nft_ctx *ctx,
6629 struct nft_flowtable *flowtable,
6630 enum nft_trans_phase phase)
6631{
6632 switch (phase) {
6633 case NFT_TRANS_PREPARE:
6634 case NFT_TRANS_ABORT:
6635 case NFT_TRANS_RELEASE:
6636 flowtable->use--;
954d8297 6637 fallthrough;
9b05b6e1
LGL
6638 default:
6639 return;
6640 }
6641}
6642EXPORT_SYMBOL_GPL(nf_tables_deactivate_flowtable);
6643
ae0662f8 6644static struct nft_flowtable *
cac20fcd
PNA
6645nft_flowtable_lookup_byhandle(const struct nft_table *table,
6646 const struct nlattr *nla, u8 genmask)
3ecbfd65
HS
6647{
6648 struct nft_flowtable *flowtable;
6649
6650 list_for_each_entry(flowtable, &table->flowtables, list) {
6651 if (be64_to_cpu(nla_get_be64(nla)) == flowtable->handle &&
6652 nft_active_genmask(flowtable, genmask))
6653 return flowtable;
6654 }
6655 return ERR_PTR(-ENOENT);
6656}
6657
d9246a53
PNA
6658struct nft_flowtable_hook {
6659 u32 num;
6660 int priority;
6661 struct list_head list;
6662};
6663
3b49e2e9
PNA
6664static const struct nla_policy nft_flowtable_hook_policy[NFTA_FLOWTABLE_HOOK_MAX + 1] = {
6665 [NFTA_FLOWTABLE_HOOK_NUM] = { .type = NLA_U32 },
6666 [NFTA_FLOWTABLE_HOOK_PRIORITY] = { .type = NLA_U32 },
6667 [NFTA_FLOWTABLE_HOOK_DEVS] = { .type = NLA_NESTED },
6668};
6669
d9246a53
PNA
6670static int nft_flowtable_parse_hook(const struct nft_ctx *ctx,
6671 const struct nlattr *attr,
6672 struct nft_flowtable_hook *flowtable_hook,
5b6743fb 6673 struct nft_flowtable *flowtable, bool add)
3b49e2e9 6674{
3b49e2e9 6675 struct nlattr *tb[NFTA_FLOWTABLE_HOOK_MAX + 1];
3f0465a9 6676 struct nft_hook *hook;
3b49e2e9 6677 int hooknum, priority;
3f0465a9 6678 int err;
3b49e2e9 6679
d9246a53
PNA
6680 INIT_LIST_HEAD(&flowtable_hook->list);
6681
8cb08174
JB
6682 err = nla_parse_nested_deprecated(tb, NFTA_FLOWTABLE_HOOK_MAX, attr,
6683 nft_flowtable_hook_policy, NULL);
3b49e2e9
PNA
6684 if (err < 0)
6685 return err;
6686
5b6743fb
PNA
6687 if (add) {
6688 if (!tb[NFTA_FLOWTABLE_HOOK_NUM] ||
6689 !tb[NFTA_FLOWTABLE_HOOK_PRIORITY])
6690 return -EINVAL;
3b49e2e9 6691
5b6743fb
PNA
6692 hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM]));
6693 if (hooknum != NF_NETDEV_INGRESS)
6694 return -EOPNOTSUPP;
6695
6696 priority = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY]));
6697
6698 flowtable_hook->priority = priority;
6699 flowtable_hook->num = hooknum;
6700 } else {
6701 if (tb[NFTA_FLOWTABLE_HOOK_NUM]) {
6702 hooknum = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_NUM]));
6703 if (hooknum != flowtable->hooknum)
6704 return -EOPNOTSUPP;
6705 }
6706
6707 if (tb[NFTA_FLOWTABLE_HOOK_PRIORITY]) {
6708 priority = ntohl(nla_get_be32(tb[NFTA_FLOWTABLE_HOOK_PRIORITY]));
6709 if (priority != flowtable->data.priority)
6710 return -EOPNOTSUPP;
6711 }
3b49e2e9 6712
5b6743fb
PNA
6713 flowtable_hook->priority = flowtable->data.priority;
6714 flowtable_hook->num = flowtable->hooknum;
6715 }
3b49e2e9 6716
05abe445
PNA
6717 if (tb[NFTA_FLOWTABLE_HOOK_DEVS]) {
6718 err = nf_tables_parse_netdev_hooks(ctx->net,
6719 tb[NFTA_FLOWTABLE_HOOK_DEVS],
6720 &flowtable_hook->list);
6721 if (err < 0)
6722 return err;
6723 }
3b49e2e9 6724
d9246a53 6725 list_for_each_entry(hook, &flowtable_hook->list, list) {
3f0465a9 6726 hook->ops.pf = NFPROTO_NETDEV;
5b6743fb
PNA
6727 hook->ops.hooknum = flowtable_hook->num;
6728 hook->ops.priority = flowtable_hook->priority;
6729 hook->ops.priv = &flowtable->data;
6730 hook->ops.hook = flowtable->data.type->hook;
3b49e2e9
PNA
6731 }
6732
3b49e2e9
PNA
6733 return err;
6734}
6735
98319cb9 6736static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family)
3b49e2e9
PNA
6737{
6738 const struct nf_flowtable_type *type;
6739
6740 list_for_each_entry(type, &nf_tables_flowtables, list) {
98319cb9 6741 if (family == type->family)
3b49e2e9
PNA
6742 return type;
6743 }
6744 return NULL;
6745}
6746
452238e8
FW
6747static const struct nf_flowtable_type *
6748nft_flowtable_type_get(struct net *net, u8 family)
3b49e2e9
PNA
6749{
6750 const struct nf_flowtable_type *type;
6751
98319cb9 6752 type = __nft_flowtable_type_get(family);
3b49e2e9
PNA
6753 if (type != NULL && try_module_get(type->owner))
6754 return type;
6755
f102d66b 6756 lockdep_nfnl_nft_mutex_not_held();
3b49e2e9
PNA
6757#ifdef CONFIG_MODULES
6758 if (type == NULL) {
eb014de4 6759 if (nft_request_module(net, "nf-flowtable-%u", family) == -EAGAIN)
3b49e2e9
PNA
6760 return ERR_PTR(-EAGAIN);
6761 }
6762#endif
6763 return ERR_PTR(-ENOENT);
6764}
6765
5acab914 6766/* Only called from error and netdev event paths. */
ff4bf2f4
PNA
6767static void nft_unregister_flowtable_hook(struct net *net,
6768 struct nft_flowtable *flowtable,
6769 struct nft_hook *hook)
6770{
6771 nf_unregister_net_hook(net, &hook->ops);
6772 flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
6773 FLOW_BLOCK_UNBIND);
6774}
6775
3b49e2e9 6776static void nft_unregister_flowtable_net_hooks(struct net *net,
f9382669 6777 struct list_head *hook_list)
3b49e2e9 6778{
3f0465a9 6779 struct nft_hook *hook;
3b49e2e9 6780
f9382669 6781 list_for_each_entry(hook, hook_list, list)
5acab914 6782 nf_unregister_net_hook(net, &hook->ops);
3f0465a9
PNA
6783}
6784
6785static int nft_register_flowtable_net_hooks(struct net *net,
6786 struct nft_table *table,
f9382669 6787 struct list_head *hook_list,
3f0465a9
PNA
6788 struct nft_flowtable *flowtable)
6789{
6790 struct nft_hook *hook, *hook2, *next;
6791 struct nft_flowtable *ft;
6792 int err, i = 0;
6793
f9382669 6794 list_for_each_entry(hook, hook_list, list) {
3f0465a9 6795 list_for_each_entry(ft, &table->flowtables, list) {
86fe2c19
PNA
6796 if (!nft_is_active_next(net, ft))
6797 continue;
6798
3f0465a9
PNA
6799 list_for_each_entry(hook2, &ft->hook_list, list) {
6800 if (hook->ops.dev == hook2->ops.dev &&
6801 hook->ops.pf == hook2->ops.pf) {
77a92189 6802 err = -EEXIST;
3f0465a9
PNA
6803 goto err_unregister_net_hooks;
6804 }
6805 }
6806 }
3b49e2e9 6807
d7c03a9f 6808 err = flowtable->data.type->setup(&flowtable->data,
6809 hook->ops.dev,
6810 FLOW_BLOCK_BIND);
3f0465a9
PNA
6811 if (err < 0)
6812 goto err_unregister_net_hooks;
6813
d7c03a9f 6814 err = nf_register_net_hook(net, &hook->ops);
6815 if (err < 0) {
6816 flowtable->data.type->setup(&flowtable->data,
6817 hook->ops.dev,
6818 FLOW_BLOCK_UNBIND);
6819 goto err_unregister_net_hooks;
6820 }
6821
3f0465a9 6822 i++;
3b49e2e9 6823 }
3f0465a9
PNA
6824
6825 return 0;
6826
6827err_unregister_net_hooks:
f9382669 6828 list_for_each_entry_safe(hook, next, hook_list, list) {
3f0465a9
PNA
6829 if (i-- <= 0)
6830 break;
6831
ff4bf2f4 6832 nft_unregister_flowtable_hook(net, flowtable, hook);
3f0465a9
PNA
6833 list_del_rcu(&hook->list);
6834 kfree_rcu(hook, rcu);
6835 }
6836
6837 return err;
3b49e2e9
PNA
6838}
6839
389a2cbc
PNA
6840static void nft_flowtable_hooks_destroy(struct list_head *hook_list)
6841{
6842 struct nft_hook *hook, *next;
6843
6844 list_for_each_entry_safe(hook, next, hook_list, list) {
6845 list_del_rcu(&hook->list);
6846 kfree_rcu(hook, rcu);
6847 }
6848}
6849
78d9f48f
PNA
6850static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh,
6851 struct nft_flowtable *flowtable)
6852{
6853 const struct nlattr * const *nla = ctx->nla;
6854 struct nft_flowtable_hook flowtable_hook;
6855 struct nft_hook *hook, *next;
6856 struct nft_trans *trans;
6857 bool unregister = false;
7b35582c 6858 u32 flags;
78d9f48f
PNA
6859 int err;
6860
6861 err = nft_flowtable_parse_hook(ctx, nla[NFTA_FLOWTABLE_HOOK],
5b6743fb 6862 &flowtable_hook, flowtable, false);
78d9f48f
PNA
6863 if (err < 0)
6864 return err;
6865
6866 list_for_each_entry_safe(hook, next, &flowtable_hook.list, list) {
6867 if (nft_hook_list_find(&flowtable->hook_list, hook)) {
6868 list_del(&hook->list);
6869 kfree(hook);
6870 }
6871 }
6872
7b35582c
PNA
6873 if (nla[NFTA_FLOWTABLE_FLAGS]) {
6874 flags = ntohl(nla_get_be32(nla[NFTA_FLOWTABLE_FLAGS]));
6875 if (flags & ~NFT_FLOWTABLE_MASK)
6876 return -EOPNOTSUPP;
6877 if ((flowtable->data.flags & NFT_FLOWTABLE_HW_OFFLOAD) ^
6878 (flags & NFT_FLOWTABLE_HW_OFFLOAD))
6879 return -EOPNOTSUPP;
6880 } else {
6881 flags = flowtable->data.flags;
6882 }
6883
78d9f48f
PNA
6884 err = nft_register_flowtable_net_hooks(ctx->net, ctx->table,
6885 &flowtable_hook.list, flowtable);
6886 if (err < 0)
6887 goto err_flowtable_update_hook;
6888
6889 trans = nft_trans_alloc(ctx, NFT_MSG_NEWFLOWTABLE,
6890 sizeof(struct nft_trans_flowtable));
6891 if (!trans) {
6892 unregister = true;
6893 err = -ENOMEM;
6894 goto err_flowtable_update_hook;
6895 }
6896
7b35582c 6897 nft_trans_flowtable_flags(trans) = flags;
78d9f48f
PNA
6898 nft_trans_flowtable(trans) = flowtable;
6899 nft_trans_flowtable_update(trans) = true;
6900 INIT_LIST_HEAD(&nft_trans_flowtable_hooks(trans));
6901 list_splice(&flowtable_hook.list, &nft_trans_flowtable_hooks(trans));
6902
0854db2a 6903 nft_trans_commit_list_add_tail(ctx->net, trans);
78d9f48f
PNA
6904
6905 return 0;
6906
6907err_flowtable_update_hook:
6908 list_for_each_entry_safe(hook, next, &flowtable_hook.list, list) {
6909 if (unregister)
6910 nft_unregister_flowtable_hook(ctx->net, flowtable, hook);
6911 list_del_rcu(&hook->list);
6912 kfree_rcu(hook, rcu);
6913 }
6914
6915 return err;
6916
6917}
6918
3b49e2e9
PNA
6919static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
6920 struct sk_buff *skb,
6921 const struct nlmsghdr *nlh,
6922 const struct nlattr * const nla[],
6923 struct netlink_ext_ack *extack)
6924{
6925 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
d9246a53 6926 struct nft_flowtable_hook flowtable_hook;
3b49e2e9
PNA
6927 const struct nf_flowtable_type *type;
6928 u8 genmask = nft_genmask_next(net);
6929 int family = nfmsg->nfgen_family;
3f0465a9
PNA
6930 struct nft_flowtable *flowtable;
6931 struct nft_hook *hook, *next;
3b49e2e9
PNA
6932 struct nft_table *table;
6933 struct nft_ctx ctx;
3f0465a9 6934 int err;
3b49e2e9
PNA
6935
6936 if (!nla[NFTA_FLOWTABLE_TABLE] ||
6937 !nla[NFTA_FLOWTABLE_NAME] ||
6938 !nla[NFTA_FLOWTABLE_HOOK])
6939 return -EINVAL;
6940
cac20fcd 6941 table = nft_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], family,
6001a930 6942 genmask, NETLINK_CB(skb).portid);
36dd1bcc
PNA
6943 if (IS_ERR(table)) {
6944 NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_TABLE]);
3b49e2e9 6945 return PTR_ERR(table);
36dd1bcc 6946 }
3b49e2e9 6947
cac20fcd
PNA
6948 flowtable = nft_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME],
6949 genmask);
3b49e2e9
PNA
6950 if (IS_ERR(flowtable)) {
6951 err = PTR_ERR(flowtable);
36dd1bcc
PNA
6952 if (err != -ENOENT) {
6953 NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_NAME]);
3b49e2e9 6954 return err;
36dd1bcc 6955 }
3b49e2e9 6956 } else {
36dd1bcc
PNA
6957 if (nlh->nlmsg_flags & NLM_F_EXCL) {
6958 NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_NAME]);
3b49e2e9 6959 return -EEXIST;
36dd1bcc 6960 }
3b49e2e9 6961
78d9f48f
PNA
6962 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
6963
6964 return nft_flowtable_update(&ctx, nlh, flowtable);
3b49e2e9
PNA
6965 }
6966
98319cb9 6967 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
3b49e2e9
PNA
6968
6969 flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL);
6970 if (!flowtable)
6971 return -ENOMEM;
6972
6973 flowtable->table = table;
3ecbfd65 6974 flowtable->handle = nf_tables_alloc_handle(table);
3f0465a9 6975 INIT_LIST_HEAD(&flowtable->hook_list);
3ecbfd65 6976
3b49e2e9
PNA
6977 flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL);
6978 if (!flowtable->name) {
6979 err = -ENOMEM;
6980 goto err1;
6981 }
6982
452238e8 6983 type = nft_flowtable_type_get(net, family);
3b49e2e9
PNA
6984 if (IS_ERR(type)) {
6985 err = PTR_ERR(type);
6986 goto err2;
6987 }
6988
8bb69f3b
PNA
6989 if (nla[NFTA_FLOWTABLE_FLAGS]) {
6990 flowtable->data.flags =
6991 ntohl(nla_get_be32(nla[NFTA_FLOWTABLE_FLAGS]));
7e6136f1
PNA
6992 if (flowtable->data.flags & ~NFT_FLOWTABLE_MASK) {
6993 err = -EOPNOTSUPP;
8bb69f3b 6994 goto err3;
7e6136f1 6995 }
8bb69f3b
PNA
6996 }
6997
6998 write_pnet(&flowtable->data.net, net);
3b49e2e9 6999 flowtable->data.type = type;
a268de77 7000 err = type->init(&flowtable->data);
3b49e2e9
PNA
7001 if (err < 0)
7002 goto err3;
7003
d9246a53 7004 err = nft_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK],
5b6743fb 7005 &flowtable_hook, flowtable, true);
3b49e2e9 7006 if (err < 0)
a268de77 7007 goto err4;
3b49e2e9 7008
d9246a53
PNA
7009 list_splice(&flowtable_hook.list, &flowtable->hook_list);
7010 flowtable->data.priority = flowtable_hook.priority;
7011 flowtable->hooknum = flowtable_hook.num;
7012
f9382669
PNA
7013 err = nft_register_flowtable_net_hooks(ctx.net, table,
7014 &flowtable->hook_list,
7015 flowtable);
2d285f26 7016 if (err < 0) {
389a2cbc 7017 nft_flowtable_hooks_destroy(&flowtable->hook_list);
3f0465a9 7018 goto err4;
2d285f26 7019 }
3b49e2e9
PNA
7020
7021 err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable);
7022 if (err < 0)
3f0465a9 7023 goto err5;
3b49e2e9
PNA
7024
7025 list_add_tail_rcu(&flowtable->list, &table->flowtables);
7026 table->use++;
7027
7028 return 0;
a268de77 7029err5:
3f0465a9 7030 list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
ff4bf2f4 7031 nft_unregister_flowtable_hook(net, flowtable, hook);
3f0465a9
PNA
7032 list_del_rcu(&hook->list);
7033 kfree_rcu(hook, rcu);
7034 }
a268de77
FF
7035err4:
7036 flowtable->data.type->free(&flowtable->data);
3b49e2e9
PNA
7037err3:
7038 module_put(type->owner);
7039err2:
7040 kfree(flowtable->name);
7041err1:
7042 kfree(flowtable);
7043 return err;
7044}
7045
3003055f
PNA
7046static void nft_flowtable_hook_release(struct nft_flowtable_hook *flowtable_hook)
7047{
7048 struct nft_hook *this, *next;
7049
7050 list_for_each_entry_safe(this, next, &flowtable_hook->list, list) {
7051 list_del(&this->list);
7052 kfree(this);
7053 }
7054}
7055
abadb2f8
PNA
7056static int nft_delflowtable_hook(struct nft_ctx *ctx,
7057 struct nft_flowtable *flowtable)
7058{
7059 const struct nlattr * const *nla = ctx->nla;
7060 struct nft_flowtable_hook flowtable_hook;
3003055f 7061 struct nft_hook *this, *hook;
abadb2f8
PNA
7062 struct nft_trans *trans;
7063 int err;
7064
7065 err = nft_flowtable_parse_hook(ctx, nla[NFTA_FLOWTABLE_HOOK],
5b6743fb 7066 &flowtable_hook, flowtable, false);
abadb2f8
PNA
7067 if (err < 0)
7068 return err;
7069
3003055f 7070 list_for_each_entry(this, &flowtable_hook.list, list) {
abadb2f8
PNA
7071 hook = nft_hook_list_find(&flowtable->hook_list, this);
7072 if (!hook) {
7073 err = -ENOENT;
7074 goto err_flowtable_del_hook;
7075 }
7076 hook->inactive = true;
abadb2f8
PNA
7077 }
7078
7079 trans = nft_trans_alloc(ctx, NFT_MSG_DELFLOWTABLE,
7080 sizeof(struct nft_trans_flowtable));
3003055f
PNA
7081 if (!trans) {
7082 err = -ENOMEM;
7083 goto err_flowtable_del_hook;
7084 }
abadb2f8
PNA
7085
7086 nft_trans_flowtable(trans) = flowtable;
7087 nft_trans_flowtable_update(trans) = true;
7088 INIT_LIST_HEAD(&nft_trans_flowtable_hooks(trans));
3003055f 7089 nft_flowtable_hook_release(&flowtable_hook);
abadb2f8 7090
0854db2a 7091 nft_trans_commit_list_add_tail(ctx->net, trans);
abadb2f8
PNA
7092
7093 return 0;
7094
7095err_flowtable_del_hook:
3003055f
PNA
7096 list_for_each_entry(this, &flowtable_hook.list, list) {
7097 hook = nft_hook_list_find(&flowtable->hook_list, this);
7098 if (!hook)
7099 break;
7100
abadb2f8 7101 hook->inactive = false;
3003055f
PNA
7102 }
7103 nft_flowtable_hook_release(&flowtable_hook);
abadb2f8
PNA
7104
7105 return err;
7106}
7107
3b49e2e9
PNA
7108static int nf_tables_delflowtable(struct net *net, struct sock *nlsk,
7109 struct sk_buff *skb,
7110 const struct nlmsghdr *nlh,
7111 const struct nlattr * const nla[],
7112 struct netlink_ext_ack *extack)
7113{
7114 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7115 u8 genmask = nft_genmask_next(net);
7116 int family = nfmsg->nfgen_family;
7117 struct nft_flowtable *flowtable;
36dd1bcc 7118 const struct nlattr *attr;
3b49e2e9
PNA
7119 struct nft_table *table;
7120 struct nft_ctx ctx;
7121
e603ea4b
PNA
7122 if (!nla[NFTA_FLOWTABLE_TABLE] ||
7123 (!nla[NFTA_FLOWTABLE_NAME] &&
7124 !nla[NFTA_FLOWTABLE_HANDLE]))
7125 return -EINVAL;
7126
cac20fcd 7127 table = nft_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], family,
6001a930 7128 genmask, NETLINK_CB(skb).portid);
36dd1bcc
PNA
7129 if (IS_ERR(table)) {
7130 NL_SET_BAD_ATTR(extack, nla[NFTA_FLOWTABLE_TABLE]);
3b49e2e9 7131 return PTR_ERR(table);
36dd1bcc 7132 }
3b49e2e9 7133
36dd1bcc
PNA
7134 if (nla[NFTA_FLOWTABLE_HANDLE]) {
7135 attr = nla[NFTA_FLOWTABLE_HANDLE];
7136 flowtable = nft_flowtable_lookup_byhandle(table, attr, genmask);
7137 } else {
7138 attr = nla[NFTA_FLOWTABLE_NAME];
7139 flowtable = nft_flowtable_lookup(table, attr, genmask);
7140 }
7141
7142 if (IS_ERR(flowtable)) {
7143 NL_SET_BAD_ATTR(extack, attr);
7144 return PTR_ERR(flowtable);
7145 }
abadb2f8
PNA
7146
7147 nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
7148
7149 if (nla[NFTA_FLOWTABLE_HOOK])
7150 return nft_delflowtable_hook(&ctx, flowtable);
7151
36dd1bcc
PNA
7152 if (flowtable->use > 0) {
7153 NL_SET_BAD_ATTR(extack, attr);
3b49e2e9 7154 return -EBUSY;
36dd1bcc 7155 }
3b49e2e9 7156
3b49e2e9
PNA
7157 return nft_delflowtable(&ctx, flowtable);
7158}
7159
7160static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net,
7161 u32 portid, u32 seq, int event,
7162 u32 flags, int family,
c42d8bda
PNA
7163 struct nft_flowtable *flowtable,
7164 struct list_head *hook_list)
3b49e2e9
PNA
7165{
7166 struct nlattr *nest, *nest_devs;
3f0465a9 7167 struct nft_hook *hook;
3b49e2e9 7168 struct nlmsghdr *nlh;
3b49e2e9
PNA
7169
7170 event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
19c28b13
PNA
7171 nlh = nfnl_msg_put(skb, portid, seq, event, flags, family,
7172 NFNETLINK_V0, nft_base_seq(net));
7173 if (!nlh)
3b49e2e9
PNA
7174 goto nla_put_failure;
7175
3b49e2e9
PNA
7176 if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) ||
7177 nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) ||
3ecbfd65
HS
7178 nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) ||
7179 nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle),
8bb69f3b
PNA
7180 NFTA_FLOWTABLE_PAD) ||
7181 nla_put_be32(skb, NFTA_FLOWTABLE_FLAGS, htonl(flowtable->data.flags)))
3b49e2e9
PNA
7182 goto nla_put_failure;
7183
ae0be8de 7184 nest = nla_nest_start_noflag(skb, NFTA_FLOWTABLE_HOOK);
eb895086
KL
7185 if (!nest)
7186 goto nla_put_failure;
3b49e2e9 7187 if (nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_NUM, htonl(flowtable->hooknum)) ||
71a8a63b 7188 nla_put_be32(skb, NFTA_FLOWTABLE_HOOK_PRIORITY, htonl(flowtable->data.priority)))
3b49e2e9
PNA
7189 goto nla_put_failure;
7190
ae0be8de 7191 nest_devs = nla_nest_start_noflag(skb, NFTA_FLOWTABLE_HOOK_DEVS);
3b49e2e9
PNA
7192 if (!nest_devs)
7193 goto nla_put_failure;
7194
c42d8bda 7195 list_for_each_entry_rcu(hook, hook_list, list) {
3f0465a9 7196 if (nla_put_string(skb, NFTA_DEVICE_NAME, hook->ops.dev->name))
3b49e2e9
PNA
7197 goto nla_put_failure;
7198 }
7199 nla_nest_end(skb, nest_devs);
7200 nla_nest_end(skb, nest);
7201
7202 nlmsg_end(skb, nlh);
7203 return 0;
7204
7205nla_put_failure:
7206 nlmsg_trim(skb, nlh);
7207 return -1;
7208}
7209
7210struct nft_flowtable_filter {
7211 char *table;
7212};
7213
7214static int nf_tables_dump_flowtable(struct sk_buff *skb,
7215 struct netlink_callback *cb)
7216{
7217 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
7218 struct nft_flowtable_filter *filter = cb->data;
7219 unsigned int idx = 0, s_idx = cb->args[0];
7220 struct net *net = sock_net(skb->sk);
7221 int family = nfmsg->nfgen_family;
7222 struct nft_flowtable *flowtable;
0854db2a 7223 struct nftables_pernet *nft_net;
3b49e2e9
PNA
7224 const struct nft_table *table;
7225
7226 rcu_read_lock();
0854db2a
FW
7227 nft_net = net_generic(net, nf_tables_net_id);
7228 cb->seq = nft_net->base_seq;
3b49e2e9 7229
0854db2a 7230 list_for_each_entry_rcu(table, &nft_net->tables, list) {
98319cb9 7231 if (family != NFPROTO_UNSPEC && family != table->family)
3b49e2e9
PNA
7232 continue;
7233
36596dad
PNA
7234 list_for_each_entry_rcu(flowtable, &table->flowtables, list) {
7235 if (!nft_is_active(net, flowtable))
7236 goto cont;
7237 if (idx < s_idx)
7238 goto cont;
7239 if (idx > s_idx)
7240 memset(&cb->args[1], 0,
7241 sizeof(cb->args) - sizeof(cb->args[0]));
360cc79d 7242 if (filter && filter->table &&
36596dad
PNA
7243 strcmp(filter->table, table->name))
7244 goto cont;
3b49e2e9 7245
36596dad
PNA
7246 if (nf_tables_fill_flowtable_info(skb, net, NETLINK_CB(cb->skb).portid,
7247 cb->nlh->nlmsg_seq,
7248 NFT_MSG_NEWFLOWTABLE,
7249 NLM_F_MULTI | NLM_F_APPEND,
c42d8bda
PNA
7250 table->family,
7251 flowtable,
7252 &flowtable->hook_list) < 0)
36596dad 7253 goto done;
3b49e2e9 7254
36596dad 7255 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
3b49e2e9 7256cont:
36596dad 7257 idx++;
3b49e2e9
PNA
7258 }
7259 }
7260done:
7261 rcu_read_unlock();
7262
7263 cb->args[0] = idx;
7264 return skb->len;
7265}
7266
90fd131a 7267static int nf_tables_dump_flowtable_start(struct netlink_callback *cb)
3b49e2e9 7268{
90fd131a
FW
7269 const struct nlattr * const *nla = cb->data;
7270 struct nft_flowtable_filter *filter = NULL;
3b49e2e9 7271
90fd131a
FW
7272 if (nla[NFTA_FLOWTABLE_TABLE]) {
7273 filter = kzalloc(sizeof(*filter), GFP_ATOMIC);
7274 if (!filter)
7275 return -ENOMEM;
3b49e2e9 7276
90fd131a
FW
7277 filter->table = nla_strdup(nla[NFTA_FLOWTABLE_TABLE],
7278 GFP_ATOMIC);
7279 if (!filter->table) {
7280 kfree(filter);
7281 return -ENOMEM;
7282 }
7283 }
3b49e2e9 7284
90fd131a 7285 cb->data = filter;
3b49e2e9
PNA
7286 return 0;
7287}
7288
90fd131a 7289static int nf_tables_dump_flowtable_done(struct netlink_callback *cb)
3b49e2e9 7290{
90fd131a 7291 struct nft_flowtable_filter *filter = cb->data;
3b49e2e9 7292
3b49e2e9 7293 if (!filter)
90fd131a 7294 return 0;
3b49e2e9 7295
90fd131a
FW
7296 kfree(filter->table);
7297 kfree(filter);
7298
7299 return 0;
3b49e2e9
PNA
7300}
7301
d9adf22a 7302/* called with rcu_read_lock held */
3b49e2e9
PNA
7303static int nf_tables_getflowtable(struct net *net, struct sock *nlsk,
7304 struct sk_buff *skb,
7305 const struct nlmsghdr *nlh,
7306 const struct nlattr * const nla[],
7307 struct netlink_ext_ack *extack)
7308{
7309 const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
7310 u8 genmask = nft_genmask_cur(net);
7311 int family = nfmsg->nfgen_family;
7312 struct nft_flowtable *flowtable;
3b49e2e9
PNA
7313 const struct nft_table *table;
7314 struct sk_buff *skb2;
7315 int err;
7316
7317 if (nlh->nlmsg_flags & NLM_F_DUMP) {
7318 struct netlink_dump_control c = {
90fd131a 7319 .start = nf_tables_dump_flowtable_start,
3b49e2e9
PNA
7320 .dump = nf_tables_dump_flowtable,
7321 .done = nf_tables_dump_flowtable_done,
d9adf22a 7322 .module = THIS_MODULE,
90fd131a 7323 .data = (void *)nla,
3b49e2e9
PNA
7324 };
7325
d9adf22a 7326 return nft_netlink_dump_start_rcu(nlsk, skb, nlh, &c);
3b49e2e9
PNA
7327 }
7328
7329 if (!nla[NFTA_FLOWTABLE_NAME])
7330 return -EINVAL;
7331
cac20fcd 7332 table = nft_table_lookup(net, nla[NFTA_FLOWTABLE_TABLE], family,
6001a930 7333 genmask, 0);
3b49e2e9
PNA
7334 if (IS_ERR(table))
7335 return PTR_ERR(table);
7336
cac20fcd
PNA
7337 flowtable = nft_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME],
7338 genmask);
03a0120f 7339 if (IS_ERR(flowtable))
3b49e2e9
PNA
7340 return PTR_ERR(flowtable);
7341
d9adf22a 7342 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
3b49e2e9
PNA
7343 if (!skb2)
7344 return -ENOMEM;
7345
7346 err = nf_tables_fill_flowtable_info(skb2, net, NETLINK_CB(skb).portid,
7347 nlh->nlmsg_seq,
7348 NFT_MSG_NEWFLOWTABLE, 0, family,
c42d8bda 7349 flowtable, &flowtable->hook_list);
3b49e2e9 7350 if (err < 0)
ee921183 7351 goto err_fill_flowtable_info;
3b49e2e9 7352
ee921183
PNA
7353 return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
7354
7355err_fill_flowtable_info:
3b49e2e9
PNA
7356 kfree_skb(skb2);
7357 return err;
7358}
7359
7360static void nf_tables_flowtable_notify(struct nft_ctx *ctx,
7361 struct nft_flowtable *flowtable,
c42d8bda 7362 struct list_head *hook_list,
3b49e2e9
PNA
7363 int event)
7364{
0854db2a 7365 struct nftables_pernet *nft_net = net_generic(ctx->net, nf_tables_net_id);
3b49e2e9
PNA
7366 struct sk_buff *skb;
7367 int err;
7368
dceababa 7369 if (!ctx->report &&
3b49e2e9
PNA
7370 !nfnetlink_has_listeners(ctx->net, NFNLGRP_NFTABLES))
7371 return;
7372
7373 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
7374 if (skb == NULL)
7375 goto err;
7376
7377 err = nf_tables_fill_flowtable_info(skb, ctx->net, ctx->portid,
7378 ctx->seq, event, 0,
c42d8bda 7379 ctx->family, flowtable, hook_list);
3b49e2e9
PNA
7380 if (err < 0) {
7381 kfree_skb(skb);
7382 goto err;
7383 }
7384
0854db2a 7385 nft_notify_enqueue(skb, ctx->report, &nft_net->notify_list);
3b49e2e9
PNA
7386 return;
7387err:
7388 nfnetlink_set_err(ctx->net, ctx->portid, NFNLGRP_NFTABLES, -ENOBUFS);
7389}
7390
3b49e2e9
PNA
7391static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
7392{
3f0465a9
PNA
7393 struct nft_hook *hook, *next;
7394
5acab914 7395 flowtable->data.type->free(&flowtable->data);
3f0465a9 7396 list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
5acab914
PNA
7397 flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
7398 FLOW_BLOCK_UNBIND);
3f0465a9
PNA
7399 list_del_rcu(&hook->list);
7400 kfree(hook);
7401 }
3b49e2e9 7402 kfree(flowtable->name);
3b49e2e9 7403 module_put(flowtable->data.type->owner);
a12486eb 7404 kfree(flowtable);
3b49e2e9
PNA
7405}
7406
84d7fce6
PNA
7407static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
7408 u32 portid, u32 seq)
7409{
0854db2a 7410 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
84d7fce6 7411 struct nlmsghdr *nlh;
784b4e61 7412 char buf[TASK_COMM_LEN];
dedb67c4 7413 int event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_NEWGEN);
84d7fce6 7414
19c28b13
PNA
7415 nlh = nfnl_msg_put(skb, portid, seq, event, 0, AF_UNSPEC,
7416 NFNETLINK_V0, nft_base_seq(net));
7417 if (!nlh)
84d7fce6
PNA
7418 goto nla_put_failure;
7419
0854db2a 7420 if (nla_put_be32(skb, NFTA_GEN_ID, htonl(nft_net->base_seq)) ||
784b4e61
PS
7421 nla_put_be32(skb, NFTA_GEN_PROC_PID, htonl(task_pid_nr(current))) ||
7422 nla_put_string(skb, NFTA_GEN_PROC_NAME, get_task_comm(buf, current)))
84d7fce6
PNA
7423 goto nla_put_failure;
7424
053c095a
JB
7425 nlmsg_end(skb, nlh);
7426 return 0;
84d7fce6
PNA
7427
7428nla_put_failure:
7429 nlmsg_trim(skb, nlh);
7430 return -EMSGSIZE;
7431}
7432
3b49e2e9
PNA
7433static void nft_flowtable_event(unsigned long event, struct net_device *dev,
7434 struct nft_flowtable *flowtable)
7435{
3f0465a9 7436 struct nft_hook *hook;
3b49e2e9 7437
3f0465a9
PNA
7438 list_for_each_entry(hook, &flowtable->hook_list, list) {
7439 if (hook->ops.dev != dev)
3b49e2e9
PNA
7440 continue;
7441
5acab914 7442 /* flow_offload_netdev_event() cleans up entries for us. */
ff4bf2f4 7443 nft_unregister_flowtable_hook(dev_net(dev), flowtable, hook);
3f0465a9
PNA
7444 list_del_rcu(&hook->list);
7445 kfree_rcu(hook, rcu);
3b49e2e9
PNA
7446 break;
7447 }
7448}
7449
7450static int nf_tables_flowtable_event(struct notifier_block *this,
7451 unsigned long event, void *ptr)
7452{
7453 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
7454 struct nft_flowtable *flowtable;
0854db2a 7455 struct nftables_pernet *nft_net;
3b49e2e9 7456 struct nft_table *table;
0a2cf5ee 7457 struct net *net;
3b49e2e9
PNA
7458
7459 if (event != NETDEV_UNREGISTER)
7460 return 0;
7461
6a48de01 7462 net = dev_net(dev);
0854db2a
FW
7463 nft_net = net_generic(net, nf_tables_net_id);
7464 mutex_lock(&nft_net->commit_mutex);
7465 list_for_each_entry(table, &nft_net->tables, list) {
36596dad
PNA
7466 list_for_each_entry(flowtable, &table->flowtables, list) {
7467 nft_flowtable_event(event, dev, flowtable);
3b49e2e9
PNA
7468 }
7469 }
0854db2a 7470 mutex_unlock(&nft_net->commit_mutex);
6a48de01 7471
3b49e2e9
PNA
7472 return NOTIFY_DONE;
7473}
7474
7475static struct notifier_block nf_tables_flowtable_notifier = {
7476 .notifier_call = nf_tables_flowtable_event,
7477};
7478
25e94a99
PNA
7479static void nf_tables_gen_notify(struct net *net, struct sk_buff *skb,
7480 int event)
84d7fce6
PNA
7481{
7482 struct nlmsghdr *nlh = nlmsg_hdr(skb);
7483 struct sk_buff *skb2;
7484 int err;
7485
dceababa 7486 if (!nlmsg_report(nlh) &&
84d7fce6 7487 !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
25e94a99 7488 return;
84d7fce6 7489
84d7fce6
PNA
7490 skb2 = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
7491 if (skb2 == NULL)
7492 goto err;
7493
7494 err = nf_tables_fill_gen_info(skb2, net, NETLINK_CB(skb).portid,
7495 nlh->nlmsg_seq);
7496 if (err < 0) {
7497 kfree_skb(skb2);
7498 goto err;
7499 }
7500
25e94a99
PNA
7501 nfnetlink_send(skb2, net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
7502 nlmsg_report(nlh), GFP_KERNEL);
7503 return;
84d7fce6 7504err:
25e94a99
PNA
7505 nfnetlink_set_err(net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
7506 -ENOBUFS);
84d7fce6
PNA
7507}
7508
7b8002a1
PNA
7509static int nf_tables_getgen(struct net *net, struct sock *nlsk,
7510 struct sk_buff *skb, const struct nlmsghdr *nlh,
04ba724b
PNA
7511 const struct nlattr * const nla[],
7512 struct netlink_ext_ack *extack)
84d7fce6 7513{
84d7fce6
PNA
7514 struct sk_buff *skb2;
7515 int err;
7516
d9adf22a 7517 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
84d7fce6
PNA
7518 if (skb2 == NULL)
7519 return -ENOMEM;
7520
7521 err = nf_tables_fill_gen_info(skb2, net, NETLINK_CB(skb).portid,
7522 nlh->nlmsg_seq);
7523 if (err < 0)
ee921183 7524 goto err_fill_gen_info;
84d7fce6 7525
ee921183
PNA
7526 return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
7527
7528err_fill_gen_info:
84d7fce6
PNA
7529 kfree_skb(skb2);
7530 return err;
7531}
7532
96518518
PM
7533static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
7534 [NFT_MSG_NEWTABLE] = {
55dd6f93 7535 .call_batch = nf_tables_newtable,
96518518
PM
7536 .attr_count = NFTA_TABLE_MAX,
7537 .policy = nft_table_policy,
7538 },
7539 [NFT_MSG_GETTABLE] = {
d9adf22a 7540 .call_rcu = nf_tables_gettable,
96518518
PM
7541 .attr_count = NFTA_TABLE_MAX,
7542 .policy = nft_table_policy,
7543 },
7544 [NFT_MSG_DELTABLE] = {
55dd6f93 7545 .call_batch = nf_tables_deltable,
96518518
PM
7546 .attr_count = NFTA_TABLE_MAX,
7547 .policy = nft_table_policy,
7548 },
7549 [NFT_MSG_NEWCHAIN] = {
91c7b38d 7550 .call_batch = nf_tables_newchain,
96518518
PM
7551 .attr_count = NFTA_CHAIN_MAX,
7552 .policy = nft_chain_policy,
7553 },
7554 [NFT_MSG_GETCHAIN] = {
d9adf22a 7555 .call_rcu = nf_tables_getchain,
96518518
PM
7556 .attr_count = NFTA_CHAIN_MAX,
7557 .policy = nft_chain_policy,
7558 },
7559 [NFT_MSG_DELCHAIN] = {
91c7b38d 7560 .call_batch = nf_tables_delchain,
96518518
PM
7561 .attr_count = NFTA_CHAIN_MAX,
7562 .policy = nft_chain_policy,
7563 },
7564 [NFT_MSG_NEWRULE] = {
0628b123 7565 .call_batch = nf_tables_newrule,
96518518
PM
7566 .attr_count = NFTA_RULE_MAX,
7567 .policy = nft_rule_policy,
7568 },
7569 [NFT_MSG_GETRULE] = {
d9adf22a 7570 .call_rcu = nf_tables_getrule,
96518518
PM
7571 .attr_count = NFTA_RULE_MAX,
7572 .policy = nft_rule_policy,
7573 },
7574 [NFT_MSG_DELRULE] = {
0628b123 7575 .call_batch = nf_tables_delrule,
96518518
PM
7576 .attr_count = NFTA_RULE_MAX,
7577 .policy = nft_rule_policy,
7578 },
20a69341 7579 [NFT_MSG_NEWSET] = {
958bee14 7580 .call_batch = nf_tables_newset,
20a69341
PM
7581 .attr_count = NFTA_SET_MAX,
7582 .policy = nft_set_policy,
7583 },
7584 [NFT_MSG_GETSET] = {
d9adf22a 7585 .call_rcu = nf_tables_getset,
20a69341
PM
7586 .attr_count = NFTA_SET_MAX,
7587 .policy = nft_set_policy,
7588 },
7589 [NFT_MSG_DELSET] = {
958bee14 7590 .call_batch = nf_tables_delset,
20a69341
PM
7591 .attr_count = NFTA_SET_MAX,
7592 .policy = nft_set_policy,
7593 },
7594 [NFT_MSG_NEWSETELEM] = {
958bee14 7595 .call_batch = nf_tables_newsetelem,
20a69341
PM
7596 .attr_count = NFTA_SET_ELEM_LIST_MAX,
7597 .policy = nft_set_elem_list_policy,
7598 },
7599 [NFT_MSG_GETSETELEM] = {
d9adf22a 7600 .call_rcu = nf_tables_getsetelem,
20a69341
PM
7601 .attr_count = NFTA_SET_ELEM_LIST_MAX,
7602 .policy = nft_set_elem_list_policy,
7603 },
7604 [NFT_MSG_DELSETELEM] = {
958bee14 7605 .call_batch = nf_tables_delsetelem,
20a69341
PM
7606 .attr_count = NFTA_SET_ELEM_LIST_MAX,
7607 .policy = nft_set_elem_list_policy,
7608 },
84d7fce6 7609 [NFT_MSG_GETGEN] = {
d9adf22a 7610 .call_rcu = nf_tables_getgen,
84d7fce6 7611 },
e5009240
PNA
7612 [NFT_MSG_NEWOBJ] = {
7613 .call_batch = nf_tables_newobj,
7614 .attr_count = NFTA_OBJ_MAX,
7615 .policy = nft_obj_policy,
7616 },
7617 [NFT_MSG_GETOBJ] = {
d9adf22a 7618 .call_rcu = nf_tables_getobj,
e5009240
PNA
7619 .attr_count = NFTA_OBJ_MAX,
7620 .policy = nft_obj_policy,
7621 },
7622 [NFT_MSG_DELOBJ] = {
7623 .call_batch = nf_tables_delobj,
7624 .attr_count = NFTA_OBJ_MAX,
7625 .policy = nft_obj_policy,
7626 },
43da04a5 7627 [NFT_MSG_GETOBJ_RESET] = {
d9adf22a 7628 .call_rcu = nf_tables_getobj,
43da04a5
PNA
7629 .attr_count = NFTA_OBJ_MAX,
7630 .policy = nft_obj_policy,
7631 },
3b49e2e9
PNA
7632 [NFT_MSG_NEWFLOWTABLE] = {
7633 .call_batch = nf_tables_newflowtable,
7634 .attr_count = NFTA_FLOWTABLE_MAX,
7635 .policy = nft_flowtable_policy,
7636 },
7637 [NFT_MSG_GETFLOWTABLE] = {
d9adf22a 7638 .call_rcu = nf_tables_getflowtable,
3b49e2e9
PNA
7639 .attr_count = NFTA_FLOWTABLE_MAX,
7640 .policy = nft_flowtable_policy,
7641 },
7642 [NFT_MSG_DELFLOWTABLE] = {
7643 .call_batch = nf_tables_delflowtable,
7644 .attr_count = NFTA_FLOWTABLE_MAX,
7645 .policy = nft_flowtable_policy,
7646 },
96518518
PM
7647};
7648
a654de8f
PNA
7649static int nf_tables_validate(struct net *net)
7650{
0854db2a 7651 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
a654de8f
PNA
7652 struct nft_table *table;
7653
0854db2a 7654 switch (nft_net->validate_state) {
a654de8f
PNA
7655 case NFT_VALIDATE_SKIP:
7656 break;
7657 case NFT_VALIDATE_NEED:
7658 nft_validate_state_update(net, NFT_VALIDATE_DO);
954d8297 7659 fallthrough;
a654de8f 7660 case NFT_VALIDATE_DO:
0854db2a 7661 list_for_each_entry(table, &nft_net->tables, list) {
a654de8f
PNA
7662 if (nft_table_validate(net, table) < 0)
7663 return -EAGAIN;
7664 }
7665 break;
7666 }
7667
7668 return 0;
7669}
7670
66293c46
FW
7671/* a drop policy has to be deferred until all rules have been activated,
7672 * otherwise a large ruleset that contains a drop-policy base chain will
7673 * cause all packets to get dropped until the full transaction has been
7674 * processed.
7675 *
7676 * We defer the drop policy until the transaction has been finalized.
7677 */
7678static void nft_chain_commit_drop_policy(struct nft_trans *trans)
7679{
7680 struct nft_base_chain *basechain;
7681
7682 if (nft_trans_chain_policy(trans) != NF_DROP)
7683 return;
7684
7685 if (!nft_is_base_chain(trans->ctx.chain))
7686 return;
7687
7688 basechain = nft_base_chain(trans->ctx.chain);
7689 basechain->policy = NF_DROP;
7690}
7691
91c7b38d
PNA
7692static void nft_chain_commit_update(struct nft_trans *trans)
7693{
7694 struct nft_base_chain *basechain;
7695
1b2470e5
FW
7696 if (nft_trans_chain_name(trans)) {
7697 rhltable_remove(&trans->ctx.table->chains_ht,
7698 &trans->ctx.chain->rhlhead,
7699 nft_chain_ht_params);
d71efb59 7700 swap(trans->ctx.chain->name, nft_trans_chain_name(trans));
1b2470e5
FW
7701 rhltable_insert_key(&trans->ctx.table->chains_ht,
7702 trans->ctx.chain->name,
7703 &trans->ctx.chain->rhlhead,
7704 nft_chain_ht_params);
7705 }
91c7b38d 7706
f323d954 7707 if (!nft_is_base_chain(trans->ctx.chain))
91c7b38d
PNA
7708 return;
7709
53315ac6
FW
7710 nft_chain_stats_replace(trans);
7711
91c7b38d 7712 basechain = nft_base_chain(trans->ctx.chain);
91c7b38d
PNA
7713
7714 switch (nft_trans_chain_policy(trans)) {
7715 case NF_DROP:
7716 case NF_ACCEPT:
7717 basechain->policy = nft_trans_chain_policy(trans);
7718 break;
7719 }
7720}
7721
d62d0ba9
FFM
7722static void nft_obj_commit_update(struct nft_trans *trans)
7723{
7724 struct nft_object *newobj;
7725 struct nft_object *obj;
7726
7727 obj = nft_trans_obj(trans);
7728 newobj = nft_trans_obj_newobj(trans);
7729
9fedd894
FFM
7730 if (obj->ops->update)
7731 obj->ops->update(obj, newobj);
d62d0ba9
FFM
7732
7733 kfree(newobj);
7734}
7735
2f99aa31 7736static void nft_commit_release(struct nft_trans *trans)
c7c32e72 7737{
c7c32e72
PNA
7738 switch (trans->msg_type) {
7739 case NFT_MSG_DELTABLE:
7740 nf_tables_table_destroy(&trans->ctx);
7741 break;
9f8aac0b 7742 case NFT_MSG_NEWCHAIN:
53315ac6 7743 free_percpu(nft_trans_chain_stats(trans));
9f8aac0b
FW
7744 kfree(nft_trans_chain_name(trans));
7745 break;
c7c32e72 7746 case NFT_MSG_DELCHAIN:
43a605f2 7747 nf_tables_chain_destroy(&trans->ctx);
c7c32e72
PNA
7748 break;
7749 case NFT_MSG_DELRULE:
7750 nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
7751 break;
7752 case NFT_MSG_DELSET:
0c2a85ed 7753 nft_set_destroy(&trans->ctx, nft_trans_set(trans));
c7c32e72 7754 break;
61edafbb 7755 case NFT_MSG_DELSETELEM:
3453c927
PNA
7756 nf_tables_set_elem_destroy(&trans->ctx,
7757 nft_trans_elem_set(trans),
59105446 7758 nft_trans_elem(trans).priv);
61edafbb 7759 break;
e5009240 7760 case NFT_MSG_DELOBJ:
00bfb320 7761 nft_obj_destroy(&trans->ctx, nft_trans_obj(trans));
e5009240 7762 break;
3b49e2e9 7763 case NFT_MSG_DELFLOWTABLE:
abadb2f8
PNA
7764 if (nft_trans_flowtable_update(trans))
7765 nft_flowtable_hooks_destroy(&nft_trans_flowtable_hooks(trans));
7766 else
7767 nf_tables_flowtable_destroy(nft_trans_flowtable(trans));
3b49e2e9 7768 break;
c7c32e72 7769 }
0935d558
FW
7770
7771 if (trans->put_net)
7772 put_net(trans->ctx.net);
7773
c7c32e72
PNA
7774 kfree(trans);
7775}
7776
0935d558 7777static void nf_tables_trans_destroy_work(struct work_struct *w)
2f99aa31
FW
7778{
7779 struct nft_trans *trans, *next;
0935d558
FW
7780 LIST_HEAD(head);
7781
7782 spin_lock(&nf_tables_destroy_list_lock);
7783 list_splice_init(&nf_tables_destroy_list, &head);
7784 spin_unlock(&nf_tables_destroy_list_lock);
2f99aa31 7785
0935d558 7786 if (list_empty(&head))
2f99aa31
FW
7787 return;
7788
7789 synchronize_rcu();
7790
0935d558 7791 list_for_each_entry_safe(trans, next, &head, list) {
2f99aa31
FW
7792 list_del(&trans->list);
7793 nft_commit_release(trans);
7794 }
7795}
7796
ffe8923f
FW
7797void nf_tables_trans_destroy_flush_work(void)
7798{
7799 flush_work(&trans_destroy_work);
7800}
7801EXPORT_SYMBOL_GPL(nf_tables_trans_destroy_flush_work);
7802
0cbc06b3
FW
7803static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *chain)
7804{
7805 struct nft_rule *rule;
7806 unsigned int alloc = 0;
7807 int i;
7808
7809 /* already handled or inactive chain? */
7810 if (chain->rules_next || !nft_is_active_next(net, chain))
7811 return 0;
7812
7813 rule = list_entry(&chain->rules, struct nft_rule, list);
7814 i = 0;
7815
7816 list_for_each_entry_continue(rule, &chain->rules, list) {
7817 if (nft_is_active_next(net, rule))
7818 alloc++;
7819 }
7820
7821 chain->rules_next = nf_tables_chain_alloc_rules(chain, alloc);
7822 if (!chain->rules_next)
7823 return -ENOMEM;
7824
7825 list_for_each_entry_continue(rule, &chain->rules, list) {
7826 if (nft_is_active_next(net, rule))
7827 chain->rules_next[i++] = rule;
7828 }
7829
7830 chain->rules_next[i] = NULL;
7831 return 0;
7832}
7833
7834static void nf_tables_commit_chain_prepare_cancel(struct net *net)
7835{
0854db2a 7836 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
0cbc06b3
FW
7837 struct nft_trans *trans, *next;
7838
0854db2a 7839 list_for_each_entry_safe(trans, next, &nft_net->commit_list, list) {
0cbc06b3
FW
7840 struct nft_chain *chain = trans->ctx.chain;
7841
7842 if (trans->msg_type == NFT_MSG_NEWRULE ||
7843 trans->msg_type == NFT_MSG_DELRULE) {
7844 kvfree(chain->rules_next);
7845 chain->rules_next = NULL;
7846 }
7847 }
7848}
7849
7850static void __nf_tables_commit_chain_free_rules_old(struct rcu_head *h)
7851{
7852 struct nft_rules_old *o = container_of(h, struct nft_rules_old, h);
7853
7854 kvfree(o->start);
7855}
7856
7857static void nf_tables_commit_chain_free_rules_old(struct nft_rule **rules)
7858{
7859 struct nft_rule **r = rules;
7860 struct nft_rules_old *old;
7861
7862 while (*r)
7863 r++;
7864
7865 r++; /* rcu_head is after end marker */
7866 old = (void *) r;
7867 old->start = rules;
7868
7869 call_rcu(&old->h, __nf_tables_commit_chain_free_rules_old);
7870}
7871
0fb39bbe 7872static void nf_tables_commit_chain(struct net *net, struct nft_chain *chain)
0cbc06b3
FW
7873{
7874 struct nft_rule **g0, **g1;
7875 bool next_genbit;
7876
7877 next_genbit = nft_gencursor_next(net);
7878
7879 g0 = rcu_dereference_protected(chain->rules_gen_0,
f102d66b 7880 lockdep_commit_lock_is_held(net));
0cbc06b3 7881 g1 = rcu_dereference_protected(chain->rules_gen_1,
f102d66b 7882 lockdep_commit_lock_is_held(net));
0cbc06b3
FW
7883
7884 /* No changes to this chain? */
7885 if (chain->rules_next == NULL) {
7886 /* chain had no change in last or next generation */
7887 if (g0 == g1)
7888 return;
7889 /*
7890 * chain had no change in this generation; make sure next
7891 * one uses same rules as current generation.
7892 */
7893 if (next_genbit) {
7894 rcu_assign_pointer(chain->rules_gen_1, g0);
7895 nf_tables_commit_chain_free_rules_old(g1);
7896 } else {
7897 rcu_assign_pointer(chain->rules_gen_0, g1);
7898 nf_tables_commit_chain_free_rules_old(g0);
7899 }
7900
7901 return;
7902 }
7903
7904 if (next_genbit)
7905 rcu_assign_pointer(chain->rules_gen_1, chain->rules_next);
7906 else
7907 rcu_assign_pointer(chain->rules_gen_0, chain->rules_next);
7908
7909 chain->rules_next = NULL;
7910
7911 if (g0 == g1)
7912 return;
7913
7914 if (next_genbit)
7915 nf_tables_commit_chain_free_rules_old(g1);
7916 else
7917 nf_tables_commit_chain_free_rules_old(g0);
7918}
7919
d152159b
FW
7920static void nft_obj_del(struct nft_object *obj)
7921{
4d44175a 7922 rhltable_remove(&nft_objname_ht, &obj->rhlhead, nft_objname_ht_params);
d152159b
FW
7923 list_del_rcu(&obj->list);
7924}
7925
d0e2c7de 7926void nft_chain_del(struct nft_chain *chain)
1b2470e5
FW
7927{
7928 struct nft_table *table = chain->table;
7929
7930 WARN_ON_ONCE(rhltable_remove(&table->chains_ht, &chain->rhlhead,
7931 nft_chain_ht_params));
7932 list_del_rcu(&chain->list);
7933}
7934
abadb2f8
PNA
7935static void nft_flowtable_hooks_del(struct nft_flowtable *flowtable,
7936 struct list_head *hook_list)
7937{
7938 struct nft_hook *hook, *next;
7939
7940 list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
7941 if (hook->inactive)
7942 list_move(&hook->list, hook_list);
7943 }
7944}
7945
eb014de4
PNA
7946static void nf_tables_module_autoload_cleanup(struct net *net)
7947{
0854db2a 7948 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
eb014de4
PNA
7949 struct nft_module_request *req, *next;
7950
0854db2a
FW
7951 WARN_ON_ONCE(!list_empty(&nft_net->commit_list));
7952 list_for_each_entry_safe(req, next, &nft_net->module_list, list) {
eb014de4
PNA
7953 WARN_ON_ONCE(!req->done);
7954 list_del(&req->list);
7955 kfree(req);
7956 }
7957}
7958
0935d558
FW
7959static void nf_tables_commit_release(struct net *net)
7960{
0854db2a 7961 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
0935d558
FW
7962 struct nft_trans *trans;
7963
7964 /* all side effects have to be made visible.
7965 * For example, if a chain named 'foo' has been deleted, a
7966 * new transaction must not find it anymore.
7967 *
7968 * Memory reclaim happens asynchronously from work queue
7969 * to prevent expensive synchronize_rcu() in commit phase.
7970 */
0854db2a 7971 if (list_empty(&nft_net->commit_list)) {
eb014de4 7972 nf_tables_module_autoload_cleanup(net);
0854db2a 7973 mutex_unlock(&nft_net->commit_mutex);
0935d558
FW
7974 return;
7975 }
7976
0854db2a 7977 trans = list_last_entry(&nft_net->commit_list,
0935d558
FW
7978 struct nft_trans, list);
7979 get_net(trans->ctx.net);
7980 WARN_ON_ONCE(trans->put_net);
7981
7982 trans->put_net = true;
7983 spin_lock(&nf_tables_destroy_list_lock);
0854db2a 7984 list_splice_tail_init(&nft_net->commit_list, &nf_tables_destroy_list);
0935d558
FW
7985 spin_unlock(&nf_tables_destroy_list_lock);
7986
eb014de4 7987 nf_tables_module_autoload_cleanup(net);
0935d558 7988 schedule_work(&trans_destroy_work);
ffe8923f 7989
0854db2a 7990 mutex_unlock(&nft_net->commit_mutex);
0935d558
FW
7991}
7992
67cc570e
PNA
7993static void nft_commit_notify(struct net *net, u32 portid)
7994{
0854db2a 7995 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
67cc570e
PNA
7996 struct sk_buff *batch_skb = NULL, *nskb, *skb;
7997 unsigned char *data;
7998 int len;
7999
0854db2a 8000 list_for_each_entry_safe(skb, nskb, &nft_net->notify_list, list) {
67cc570e
PNA
8001 if (!batch_skb) {
8002new_batch:
8003 batch_skb = skb;
8004 len = NLMSG_GOODSIZE - skb->len;
8005 list_del(&skb->list);
8006 continue;
8007 }
8008 len -= skb->len;
8009 if (len > 0 && NFT_CB(skb).report == NFT_CB(batch_skb).report) {
8010 data = skb_put(batch_skb, skb->len);
8011 memcpy(data, skb->data, skb->len);
8012 list_del(&skb->list);
8013 kfree_skb(skb);
8014 continue;
8015 }
8016 nfnetlink_send(batch_skb, net, portid, NFNLGRP_NFTABLES,
8017 NFT_CB(batch_skb).report, GFP_KERNEL);
8018 goto new_batch;
8019 }
8020
8021 if (batch_skb) {
8022 nfnetlink_send(batch_skb, net, portid, NFNLGRP_NFTABLES,
8023 NFT_CB(batch_skb).report, GFP_KERNEL);
8024 }
8025
0854db2a 8026 WARN_ON_ONCE(!list_empty(&nft_net->notify_list));
67cc570e
PNA
8027}
8028
c520292f
RGB
8029static int nf_tables_commit_audit_alloc(struct list_head *adl,
8030 struct nft_table *table)
8031{
8032 struct nft_audit_data *adp;
8033
8034 list_for_each_entry(adp, adl, list) {
8035 if (adp->table == table)
8036 return 0;
8037 }
8038 adp = kzalloc(sizeof(*adp), GFP_KERNEL);
8039 if (!adp)
8040 return -ENOMEM;
8041 adp->table = table;
8042 list_add(&adp->list, adl);
8043 return 0;
8044}
8045
8046static void nf_tables_commit_audit_collect(struct list_head *adl,
8047 struct nft_table *table, u32 op)
8048{
8049 struct nft_audit_data *adp;
8050
8051 list_for_each_entry(adp, adl, list) {
8052 if (adp->table == table)
8053 goto found;
8054 }
dadf33c9 8055 WARN_ONCE(1, "table=%s not expected in commit list", table->name);
c520292f
RGB
8056 return;
8057found:
8058 adp->entries++;
8059 if (!adp->op || adp->op > op)
8060 adp->op = op;
8061}
8062
8063#define AUNFTABLENAMELEN (NFT_TABLE_MAXNAMELEN + 22)
8064
8065static void nf_tables_commit_audit_log(struct list_head *adl, u32 generation)
8066{
8067 struct nft_audit_data *adp, *adn;
8068 char aubuf[AUNFTABLENAMELEN];
8069
8070 list_for_each_entry_safe(adp, adn, adl, list) {
8071 snprintf(aubuf, AUNFTABLENAMELEN, "%s:%u", adp->table->name,
8072 generation);
8073 audit_log_nfcfg(aubuf, adp->table->family, adp->entries,
8074 nft2audit_op[adp->op], GFP_KERNEL);
8075 list_del(&adp->list);
8076 kfree(adp);
8077 }
8078}
8079
5913beaf 8080static int nf_tables_commit(struct net *net, struct sk_buff *skb)
37082f93 8081{
0854db2a 8082 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
37082f93 8083 struct nft_trans *trans, *next;
a3716e70 8084 struct nft_trans_elem *te;
0cbc06b3
FW
8085 struct nft_chain *chain;
8086 struct nft_table *table;
c520292f 8087 LIST_HEAD(adl);
c9626a2c 8088 int err;
37082f93 8089
0854db2a
FW
8090 if (list_empty(&nft_net->commit_list)) {
8091 mutex_unlock(&nft_net->commit_mutex);
b8b27498
FW
8092 return 0;
8093 }
8094
a654de8f
PNA
8095 /* 0. Validate ruleset, otherwise roll back for error reporting. */
8096 if (nf_tables_validate(net) < 0)
8097 return -EAGAIN;
8098
c9626a2c
PNA
8099 err = nft_flow_rule_offload_commit(net);
8100 if (err < 0)
8101 return err;
8102
0cbc06b3 8103 /* 1. Allocate space for next generation rules_gen_X[] */
0854db2a 8104 list_for_each_entry_safe(trans, next, &nft_net->commit_list, list) {
0cbc06b3 8105 int ret;
37082f93 8106
c520292f
RGB
8107 ret = nf_tables_commit_audit_alloc(&adl, trans->ctx.table);
8108 if (ret) {
8109 nf_tables_commit_chain_prepare_cancel(net);
8110 return ret;
8111 }
0cbc06b3
FW
8112 if (trans->msg_type == NFT_MSG_NEWRULE ||
8113 trans->msg_type == NFT_MSG_DELRULE) {
8114 chain = trans->ctx.chain;
8115
8116 ret = nf_tables_commit_chain_prepare(net, chain);
8117 if (ret < 0) {
8118 nf_tables_commit_chain_prepare_cancel(net);
8119 return ret;
8120 }
8121 }
8122 }
37082f93 8123
0cbc06b3 8124 /* step 2. Make rules_gen_X visible to packet path */
0854db2a 8125 list_for_each_entry(table, &nft_net->tables, list) {
0fb39bbe
FW
8126 list_for_each_entry(chain, &table->chains, list)
8127 nf_tables_commit_chain(net, chain);
0cbc06b3
FW
8128 }
8129
8130 /*
8131 * Bump generation counter, invalidate any dump in progress.
8132 * Cannot fail after this point.
37082f93 8133 */
0854db2a
FW
8134 while (++nft_net->base_seq == 0)
8135 ;
0cbc06b3
FW
8136
8137 /* step 3. Start new generation, rules_gen_X now in use. */
8138 net->nft.gencursor = nft_gencursor_next(net);
37082f93 8139
0854db2a 8140 list_for_each_entry_safe(trans, next, &nft_net->commit_list, list) {
c520292f
RGB
8141 nf_tables_commit_audit_collect(&adl, trans->ctx.table,
8142 trans->msg_type);
b380e5c7 8143 switch (trans->msg_type) {
55dd6f93
PNA
8144 case NFT_MSG_NEWTABLE:
8145 if (nft_trans_table_update(trans)) {
0ce7cf41
PNA
8146 if (nft_trans_table_state(trans) == NFT_TABLE_STATE_DORMANT)
8147 nf_tables_table_disable(net, trans->ctx.table);
8148
8149 trans->ctx.table->flags = nft_trans_table_flags(trans);
55dd6f93 8150 } else {
f2a6d766 8151 nft_clear(net, trans->ctx.table);
55dd6f93 8152 }
35151d84 8153 nf_tables_table_notify(&trans->ctx, NFT_MSG_NEWTABLE);
55dd6f93
PNA
8154 nft_trans_destroy(trans);
8155 break;
8156 case NFT_MSG_DELTABLE:
f2a6d766 8157 list_del_rcu(&trans->ctx.table->list);
35151d84 8158 nf_tables_table_notify(&trans->ctx, NFT_MSG_DELTABLE);
55dd6f93 8159 break;
91c7b38d 8160 case NFT_MSG_NEWCHAIN:
9f8aac0b 8161 if (nft_trans_chain_update(trans)) {
91c7b38d 8162 nft_chain_commit_update(trans);
9f8aac0b
FW
8163 nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
8164 /* trans destroyed after rcu grace period */
8165 } else {
66293c46 8166 nft_chain_commit_drop_policy(trans);
664b0f8c 8167 nft_clear(net, trans->ctx.chain);
9f8aac0b
FW
8168 nf_tables_chain_notify(&trans->ctx, NFT_MSG_NEWCHAIN);
8169 nft_trans_destroy(trans);
8170 }
91c7b38d
PNA
8171 break;
8172 case NFT_MSG_DELCHAIN:
1b2470e5 8173 nft_chain_del(trans->ctx.chain);
35151d84 8174 nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
c974a3a3
PNA
8175 nf_tables_unregister_hook(trans->ctx.net,
8176 trans->ctx.table,
8177 trans->ctx.chain);
91c7b38d 8178 break;
b380e5c7 8179 case NFT_MSG_NEWRULE:
889f7ee7 8180 nft_clear(trans->ctx.net, nft_trans_rule(trans));
35151d84 8181 nf_tables_rule_notify(&trans->ctx,
37082f93 8182 nft_trans_rule(trans),
35151d84 8183 NFT_MSG_NEWRULE);
37082f93 8184 nft_trans_destroy(trans);
b380e5c7
PNA
8185 break;
8186 case NFT_MSG_DELRULE:
8187 list_del_rcu(&nft_trans_rule(trans)->list);
35151d84
PNA
8188 nf_tables_rule_notify(&trans->ctx,
8189 nft_trans_rule(trans),
8190 NFT_MSG_DELRULE);
f6ac8585
PNA
8191 nft_rule_expr_deactivate(&trans->ctx,
8192 nft_trans_rule(trans),
8193 NFT_TRANS_COMMIT);
b380e5c7 8194 break;
958bee14 8195 case NFT_MSG_NEWSET:
37a9cc52 8196 nft_clear(net, nft_trans_set(trans));
4fefee57
PNA
8197 /* This avoids hitting -EBUSY when deleting the table
8198 * from the transaction.
8199 */
408070d6 8200 if (nft_set_is_anonymous(nft_trans_set(trans)) &&
4fefee57
PNA
8201 !list_empty(&nft_trans_set(trans)->bindings))
8202 trans->ctx.table->use--;
8203
958bee14 8204 nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
31f8441c 8205 NFT_MSG_NEWSET, GFP_KERNEL);
958bee14
PNA
8206 nft_trans_destroy(trans);
8207 break;
8208 case NFT_MSG_DELSET:
37a9cc52 8209 list_del_rcu(&nft_trans_set(trans)->list);
958bee14 8210 nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
31f8441c 8211 NFT_MSG_DELSET, GFP_KERNEL);
958bee14 8212 break;
60319eb1 8213 case NFT_MSG_NEWSETELEM:
cc02e457
PM
8214 te = (struct nft_trans_elem *)trans->data;
8215
42a55769 8216 te->set->ops->activate(net, te->set, &te->elem);
cc02e457
PM
8217 nf_tables_setelem_notify(&trans->ctx, te->set,
8218 &te->elem,
60319eb1
PNA
8219 NFT_MSG_NEWSETELEM, 0);
8220 nft_trans_destroy(trans);
8221 break;
8222 case NFT_MSG_DELSETELEM:
a3716e70 8223 te = (struct nft_trans_elem *)trans->data;
fe2811eb 8224
a3716e70
PNA
8225 nf_tables_setelem_notify(&trans->ctx, te->set,
8226 &te->elem,
60319eb1 8227 NFT_MSG_DELSETELEM, 0);
5cb82a38 8228 te->set->ops->remove(net, te->set, &te->elem);
3dd0673a
PM
8229 atomic_dec(&te->set->nelems);
8230 te->set->ndeact--;
60319eb1 8231 break;
e5009240 8232 case NFT_MSG_NEWOBJ:
d62d0ba9
FFM
8233 if (nft_trans_obj_update(trans)) {
8234 nft_obj_commit_update(trans);
8235 nf_tables_obj_notify(&trans->ctx,
8236 nft_trans_obj(trans),
8237 NFT_MSG_NEWOBJ);
8238 } else {
8239 nft_clear(net, nft_trans_obj(trans));
8240 nf_tables_obj_notify(&trans->ctx,
8241 nft_trans_obj(trans),
8242 NFT_MSG_NEWOBJ);
8243 nft_trans_destroy(trans);
8244 }
e5009240
PNA
8245 break;
8246 case NFT_MSG_DELOBJ:
d152159b 8247 nft_obj_del(nft_trans_obj(trans));
e5009240
PNA
8248 nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans),
8249 NFT_MSG_DELOBJ);
8250 break;
3b49e2e9 8251 case NFT_MSG_NEWFLOWTABLE:
78d9f48f 8252 if (nft_trans_flowtable_update(trans)) {
7b35582c
PNA
8253 nft_trans_flowtable(trans)->data.flags =
8254 nft_trans_flowtable_flags(trans);
78d9f48f
PNA
8255 nf_tables_flowtable_notify(&trans->ctx,
8256 nft_trans_flowtable(trans),
8257 &nft_trans_flowtable_hooks(trans),
8258 NFT_MSG_NEWFLOWTABLE);
8259 list_splice(&nft_trans_flowtable_hooks(trans),
8260 &nft_trans_flowtable(trans)->hook_list);
8261 } else {
8262 nft_clear(net, nft_trans_flowtable(trans));
8263 nf_tables_flowtable_notify(&trans->ctx,
8264 nft_trans_flowtable(trans),
8265 &nft_trans_flowtable(trans)->hook_list,
8266 NFT_MSG_NEWFLOWTABLE);
8267 }
3b49e2e9
PNA
8268 nft_trans_destroy(trans);
8269 break;
8270 case NFT_MSG_DELFLOWTABLE:
abadb2f8
PNA
8271 if (nft_trans_flowtable_update(trans)) {
8272 nft_flowtable_hooks_del(nft_trans_flowtable(trans),
8273 &nft_trans_flowtable_hooks(trans));
8274 nf_tables_flowtable_notify(&trans->ctx,
8275 nft_trans_flowtable(trans),
8276 &nft_trans_flowtable_hooks(trans),
8277 NFT_MSG_DELFLOWTABLE);
8278 nft_unregister_flowtable_net_hooks(net,
8279 &nft_trans_flowtable_hooks(trans));
8280 } else {
8281 list_del_rcu(&nft_trans_flowtable(trans)->list);
8282 nf_tables_flowtable_notify(&trans->ctx,
8283 nft_trans_flowtable(trans),
8284 &nft_trans_flowtable(trans)->hook_list,
8285 NFT_MSG_DELFLOWTABLE);
8286 nft_unregister_flowtable_net_hooks(net,
8287 &nft_trans_flowtable(trans)->hook_list);
8288 }
3b49e2e9 8289 break;
37082f93 8290 }
37082f93
PNA
8291 }
8292
67cc570e 8293 nft_commit_notify(net, NETLINK_CB(skb).portid);
84d7fce6 8294 nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
0854db2a 8295 nf_tables_commit_audit_log(&adl, nft_net->base_seq);
0935d558 8296 nf_tables_commit_release(net);
37082f93
PNA
8297
8298 return 0;
8299}
8300
eb014de4
PNA
8301static void nf_tables_module_autoload(struct net *net)
8302{
0854db2a 8303 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
eb014de4
PNA
8304 struct nft_module_request *req, *next;
8305 LIST_HEAD(module_list);
8306
0854db2a
FW
8307 list_splice_init(&nft_net->module_list, &module_list);
8308 mutex_unlock(&nft_net->commit_mutex);
eb014de4 8309 list_for_each_entry_safe(req, next, &module_list, list) {
1d305ba4
FW
8310 request_module("%s", req->module);
8311 req->done = true;
eb014de4 8312 }
0854db2a
FW
8313 mutex_lock(&nft_net->commit_mutex);
8314 list_splice(&module_list, &nft_net->module_list);
eb014de4
PNA
8315}
8316
b326dd37 8317static void nf_tables_abort_release(struct nft_trans *trans)
c7c32e72 8318{
c7c32e72
PNA
8319 switch (trans->msg_type) {
8320 case NFT_MSG_NEWTABLE:
8321 nf_tables_table_destroy(&trans->ctx);
8322 break;
8323 case NFT_MSG_NEWCHAIN:
43a605f2 8324 nf_tables_chain_destroy(&trans->ctx);
c7c32e72
PNA
8325 break;
8326 case NFT_MSG_NEWRULE:
8327 nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
8328 break;
8329 case NFT_MSG_NEWSET:
0c2a85ed 8330 nft_set_destroy(&trans->ctx, nft_trans_set(trans));
c7c32e72 8331 break;
61edafbb
PM
8332 case NFT_MSG_NEWSETELEM:
8333 nft_set_elem_destroy(nft_trans_elem_set(trans),
61f9e292 8334 nft_trans_elem(trans).priv, true);
61edafbb 8335 break;
e5009240 8336 case NFT_MSG_NEWOBJ:
00bfb320 8337 nft_obj_destroy(&trans->ctx, nft_trans_obj(trans));
e5009240 8338 break;
3b49e2e9 8339 case NFT_MSG_NEWFLOWTABLE:
78d9f48f
PNA
8340 if (nft_trans_flowtable_update(trans))
8341 nft_flowtable_hooks_destroy(&nft_trans_flowtable_hooks(trans));
8342 else
8343 nf_tables_flowtable_destroy(nft_trans_flowtable(trans));
3b49e2e9 8344 break;
c7c32e72
PNA
8345 }
8346 kfree(trans);
8347}
8348
c0391b6a 8349static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
37082f93 8350{
0854db2a 8351 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
37082f93 8352 struct nft_trans *trans, *next;
02263db0 8353 struct nft_trans_elem *te;
abadb2f8 8354 struct nft_hook *hook;
37082f93 8355
c0391b6a
PNA
8356 if (action == NFNL_ABORT_VALIDATE &&
8357 nf_tables_validate(net) < 0)
8358 return -EAGAIN;
8359
0854db2a 8360 list_for_each_entry_safe_reverse(trans, next, &nft_net->commit_list,
a907e36d 8361 list) {
b380e5c7 8362 switch (trans->msg_type) {
55dd6f93
PNA
8363 case NFT_MSG_NEWTABLE:
8364 if (nft_trans_table_update(trans)) {
0ce7cf41
PNA
8365 if (nft_trans_table_state(trans) == NFT_TABLE_STATE_WAKEUP)
8366 nf_tables_table_disable(net, trans->ctx.table);
8367
55dd6f93
PNA
8368 nft_trans_destroy(trans);
8369 } else {
e688a7f8 8370 list_del_rcu(&trans->ctx.table->list);
55dd6f93
PNA
8371 }
8372 break;
8373 case NFT_MSG_DELTABLE:
f2a6d766 8374 nft_clear(trans->ctx.net, trans->ctx.table);
55dd6f93
PNA
8375 nft_trans_destroy(trans);
8376 break;
91c7b38d
PNA
8377 case NFT_MSG_NEWCHAIN:
8378 if (nft_trans_chain_update(trans)) {
982f4051 8379 free_percpu(nft_trans_chain_stats(trans));
9f8aac0b 8380 kfree(nft_trans_chain_name(trans));
91c7b38d
PNA
8381 nft_trans_destroy(trans);
8382 } else {
d0e2c7de
PNA
8383 if (nft_chain_is_bound(trans->ctx.chain)) {
8384 nft_trans_destroy(trans);
8385 break;
8386 }
4fefee57 8387 trans->ctx.table->use--;
1b2470e5 8388 nft_chain_del(trans->ctx.chain);
c974a3a3
PNA
8389 nf_tables_unregister_hook(trans->ctx.net,
8390 trans->ctx.table,
8391 trans->ctx.chain);
91c7b38d
PNA
8392 }
8393 break;
8394 case NFT_MSG_DELCHAIN:
4fefee57 8395 trans->ctx.table->use++;
664b0f8c 8396 nft_clear(trans->ctx.net, trans->ctx.chain);
91c7b38d
PNA
8397 nft_trans_destroy(trans);
8398 break;
b380e5c7 8399 case NFT_MSG_NEWRULE:
4fefee57 8400 trans->ctx.chain->use--;
b380e5c7 8401 list_del_rcu(&nft_trans_rule(trans)->list);
f6ac8585
PNA
8402 nft_rule_expr_deactivate(&trans->ctx,
8403 nft_trans_rule(trans),
8404 NFT_TRANS_ABORT);
b380e5c7
PNA
8405 break;
8406 case NFT_MSG_DELRULE:
4fefee57 8407 trans->ctx.chain->use++;
889f7ee7 8408 nft_clear(trans->ctx.net, nft_trans_rule(trans));
bb7b40ae 8409 nft_rule_expr_activate(&trans->ctx, nft_trans_rule(trans));
37082f93 8410 nft_trans_destroy(trans);
b380e5c7 8411 break;
958bee14 8412 case NFT_MSG_NEWSET:
4fefee57 8413 trans->ctx.table->use--;
6a0a8d10 8414 if (nft_trans_set_bound(trans)) {
40ba1d9b
PNA
8415 nft_trans_destroy(trans);
8416 break;
8417 }
8418 list_del_rcu(&nft_trans_set(trans)->list);
958bee14
PNA
8419 break;
8420 case NFT_MSG_DELSET:
4fefee57 8421 trans->ctx.table->use++;
37a9cc52 8422 nft_clear(trans->ctx.net, nft_trans_set(trans));
958bee14
PNA
8423 nft_trans_destroy(trans);
8424 break;
60319eb1 8425 case NFT_MSG_NEWSETELEM:
6a0a8d10 8426 if (nft_trans_elem_set_bound(trans)) {
40ba1d9b
PNA
8427 nft_trans_destroy(trans);
8428 break;
8429 }
02263db0 8430 te = (struct nft_trans_elem *)trans->data;
5cb82a38 8431 te->set->ops->remove(net, te->set, &te->elem);
3dd0673a 8432 atomic_dec(&te->set->nelems);
60319eb1
PNA
8433 break;
8434 case NFT_MSG_DELSETELEM:
cc02e457
PM
8435 te = (struct nft_trans_elem *)trans->data;
8436
59105446 8437 nft_set_elem_activate(net, te->set, &te->elem);
42a55769 8438 te->set->ops->activate(net, te->set, &te->elem);
3dd0673a 8439 te->set->ndeact--;
cc02e457 8440
e5009240
PNA
8441 nft_trans_destroy(trans);
8442 break;
8443 case NFT_MSG_NEWOBJ:
d62d0ba9
FFM
8444 if (nft_trans_obj_update(trans)) {
8445 kfree(nft_trans_obj_newobj(trans));
8446 nft_trans_destroy(trans);
8447 } else {
8448 trans->ctx.table->use--;
8449 nft_obj_del(nft_trans_obj(trans));
8450 }
e5009240
PNA
8451 break;
8452 case NFT_MSG_DELOBJ:
8453 trans->ctx.table->use++;
8454 nft_clear(trans->ctx.net, nft_trans_obj(trans));
60319eb1
PNA
8455 nft_trans_destroy(trans);
8456 break;
3b49e2e9 8457 case NFT_MSG_NEWFLOWTABLE:
78d9f48f
PNA
8458 if (nft_trans_flowtable_update(trans)) {
8459 nft_unregister_flowtable_net_hooks(net,
8460 &nft_trans_flowtable_hooks(trans));
8461 } else {
8462 trans->ctx.table->use--;
8463 list_del_rcu(&nft_trans_flowtable(trans)->list);
8464 nft_unregister_flowtable_net_hooks(net,
8465 &nft_trans_flowtable(trans)->hook_list);
8466 }
3b49e2e9
PNA
8467 break;
8468 case NFT_MSG_DELFLOWTABLE:
abadb2f8
PNA
8469 if (nft_trans_flowtable_update(trans)) {
8470 list_for_each_entry(hook, &nft_trans_flowtable(trans)->hook_list, list)
8471 hook->inactive = false;
8472 } else {
8473 trans->ctx.table->use++;
8474 nft_clear(trans->ctx.net, nft_trans_flowtable(trans));
8475 }
3b49e2e9
PNA
8476 nft_trans_destroy(trans);
8477 break;
37082f93 8478 }
37082f93
PNA
8479 }
8480
b326dd37
PNA
8481 synchronize_rcu();
8482
a1cee076 8483 list_for_each_entry_safe_reverse(trans, next,
0854db2a 8484 &nft_net->commit_list, list) {
c7c32e72 8485 list_del(&trans->list);
b326dd37 8486 nf_tables_abort_release(trans);
37082f93
PNA
8487 }
8488
c0391b6a 8489 if (action == NFNL_ABORT_AUTOLOAD)
eb014de4
PNA
8490 nf_tables_module_autoload(net);
8491 else
8492 nf_tables_module_autoload_cleanup(net);
8493
37082f93
PNA
8494 return 0;
8495}
8496
a654de8f
PNA
8497static void nf_tables_cleanup(struct net *net)
8498{
8499 nft_validate_state_update(net, NFT_VALIDATE_SKIP);
8500}
8501
c0391b6a
PNA
8502static int nf_tables_abort(struct net *net, struct sk_buff *skb,
8503 enum nfnl_abort_action action)
71ad00c5 8504{
0854db2a 8505 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
c0391b6a 8506 int ret = __nf_tables_abort(net, action);
f102d66b 8507
0854db2a 8508 mutex_unlock(&nft_net->commit_mutex);
f102d66b
FW
8509
8510 return ret;
71ad00c5
FW
8511}
8512
74e8bcd2
PNA
8513static bool nf_tables_valid_genid(struct net *net, u32 genid)
8514{
0854db2a 8515 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
f102d66b
FW
8516 bool genid_ok;
8517
0854db2a 8518 mutex_lock(&nft_net->commit_mutex);
f102d66b 8519
0854db2a 8520 genid_ok = genid == 0 || nft_net->base_seq == genid;
f102d66b 8521 if (!genid_ok)
0854db2a 8522 mutex_unlock(&nft_net->commit_mutex);
f102d66b
FW
8523
8524 /* else, commit mutex has to be released by commit or abort function */
8525 return genid_ok;
74e8bcd2
PNA
8526}
8527
96518518
PM
8528static const struct nfnetlink_subsystem nf_tables_subsys = {
8529 .name = "nf_tables",
8530 .subsys_id = NFNL_SUBSYS_NFTABLES,
8531 .cb_count = NFT_MSG_MAX,
8532 .cb = nf_tables_cb,
0628b123
PNA
8533 .commit = nf_tables_commit,
8534 .abort = nf_tables_abort,
a654de8f 8535 .cleanup = nf_tables_cleanup,
74e8bcd2 8536 .valid_genid = nf_tables_valid_genid,
be2ab5b4 8537 .owner = THIS_MODULE,
96518518
PM
8538};
8539
7210e4e3 8540int nft_chain_validate_dependency(const struct nft_chain *chain,
32537e91 8541 enum nft_chain_types type)
7210e4e3
PNA
8542{
8543 const struct nft_base_chain *basechain;
8544
f323d954 8545 if (nft_is_base_chain(chain)) {
7210e4e3
PNA
8546 basechain = nft_base_chain(chain);
8547 if (basechain->type->type != type)
8548 return -EOPNOTSUPP;
8549 }
8550 return 0;
8551}
8552EXPORT_SYMBOL_GPL(nft_chain_validate_dependency);
8553
75e8d06d
PNA
8554int nft_chain_validate_hooks(const struct nft_chain *chain,
8555 unsigned int hook_flags)
8556{
8557 struct nft_base_chain *basechain;
8558
f323d954 8559 if (nft_is_base_chain(chain)) {
75e8d06d
PNA
8560 basechain = nft_base_chain(chain);
8561
c974a3a3 8562 if ((1 << basechain->ops.hooknum) & hook_flags)
75e8d06d
PNA
8563 return 0;
8564
8565 return -EOPNOTSUPP;
8566 }
8567
8568 return 0;
8569}
8570EXPORT_SYMBOL_GPL(nft_chain_validate_hooks);
8571
20a69341
PM
8572/*
8573 * Loop detection - walk through the ruleset beginning at the destination chain
8574 * of a new jump until either the source chain is reached (loop) or all
8575 * reachable chains have been traversed.
8576 *
8577 * The loop check is performed whenever a new jump verdict is added to an
8578 * expression or verdict map or a verdict map is bound to a new chain.
8579 */
8580
8581static int nf_tables_check_loops(const struct nft_ctx *ctx,
8582 const struct nft_chain *chain);
8583
8584static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx,
de70185d 8585 struct nft_set *set,
20a69341 8586 const struct nft_set_iter *iter,
de70185d 8587 struct nft_set_elem *elem)
20a69341 8588{
fe2811eb
PM
8589 const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
8590 const struct nft_data *data;
8591
8592 if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
8593 *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
62f9c8b4
PNA
8594 return 0;
8595
fe2811eb 8596 data = nft_set_ext_data(ext);
1ca2e170 8597 switch (data->verdict.code) {
20a69341
PM
8598 case NFT_JUMP:
8599 case NFT_GOTO:
1ca2e170 8600 return nf_tables_check_loops(ctx, data->verdict.chain);
20a69341
PM
8601 default:
8602 return 0;
8603 }
8604}
8605
8606static int nf_tables_check_loops(const struct nft_ctx *ctx,
8607 const struct nft_chain *chain)
8608{
8609 const struct nft_rule *rule;
8610 const struct nft_expr *expr, *last;
de70185d 8611 struct nft_set *set;
20a69341
PM
8612 struct nft_set_binding *binding;
8613 struct nft_set_iter iter;
20a69341
PM
8614
8615 if (ctx->chain == chain)
8616 return -ELOOP;
8617
8618 list_for_each_entry(rule, &chain->rules, list) {
8619 nft_rule_for_each_expr(expr, last, rule) {
a654de8f
PNA
8620 struct nft_immediate_expr *priv;
8621 const struct nft_data *data;
0ca743a5
PNA
8622 int err;
8623
a654de8f 8624 if (strcmp(expr->ops->type->name, "immediate"))
20a69341
PM
8625 continue;
8626
a654de8f
PNA
8627 priv = nft_expr_priv(expr);
8628 if (priv->dreg != NFT_REG_VERDICT)
0ca743a5 8629 continue;
20a69341 8630
a654de8f 8631 data = &priv->data;
1ca2e170 8632 switch (data->verdict.code) {
20a69341
PM
8633 case NFT_JUMP:
8634 case NFT_GOTO:
1ca2e170
PM
8635 err = nf_tables_check_loops(ctx,
8636 data->verdict.chain);
20a69341
PM
8637 if (err < 0)
8638 return err;
c2168e6b 8639 break;
20a69341
PM
8640 default:
8641 break;
8642 }
8643 }
8644 }
8645
8646 list_for_each_entry(set, &ctx->table->sets, list) {
37a9cc52
PNA
8647 if (!nft_is_active_next(ctx->net, set))
8648 continue;
20a69341
PM
8649 if (!(set->flags & NFT_SET_MAP) ||
8650 set->dtype != NFT_DATA_VERDICT)
8651 continue;
8652
8653 list_for_each_entry(binding, &set->bindings, list) {
11113e19
PM
8654 if (!(binding->flags & NFT_SET_MAP) ||
8655 binding->chain != chain)
20a69341
PM
8656 continue;
8657
8588ac09 8658 iter.genmask = nft_genmask_next(ctx->net);
20a69341
PM
8659 iter.skip = 0;
8660 iter.count = 0;
8661 iter.err = 0;
8662 iter.fn = nf_tables_loop_check_setelem;
8663
8664 set->ops->walk(ctx, set, &iter);
8665 if (iter.err < 0)
8666 return iter.err;
8667 }
8668 }
8669
8670 return 0;
8671}
8672
36b701fa
LGL
8673/**
8674 * nft_parse_u32_check - fetch u32 attribute and check for maximum value
8675 *
8676 * @attr: netlink attribute to fetch value from
8677 * @max: maximum value to be stored in dest
8678 * @dest: pointer to the variable
8679 *
8680 * Parse, check and store a given u32 netlink attribute into variable.
8681 * This function returns -ERANGE if the value goes over maximum value.
8682 * Otherwise a 0 is returned and the attribute value is stored in the
8683 * destination variable.
8684 */
f1d505bb 8685int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest)
36b701fa 8686{
09525a09 8687 u32 val;
36b701fa
LGL
8688
8689 val = ntohl(nla_get_be32(attr));
8690 if (val > max)
8691 return -ERANGE;
8692
8693 *dest = val;
8694 return 0;
8695}
8696EXPORT_SYMBOL_GPL(nft_parse_u32_check);
8697
08a01c11 8698static unsigned int nft_parse_register(const struct nlattr *attr)
b1c96ed3 8699{
49499c3e
PM
8700 unsigned int reg;
8701
8702 reg = ntohl(nla_get_be32(attr));
8703 switch (reg) {
8704 case NFT_REG_VERDICT...NFT_REG_4:
8705 return reg * NFT_REG_SIZE / NFT_REG32_SIZE;
8706 default:
8707 return reg + NFT_REG_SIZE / NFT_REG32_SIZE - NFT_REG32_00;
8708 }
b1c96ed3 8709}
b1c96ed3 8710
49499c3e
PM
8711/**
8712 * nft_dump_register - dump a register value to a netlink attribute
8713 *
8714 * @skb: socket buffer
8715 * @attr: attribute number
8716 * @reg: register number
8717 *
8718 * Construct a netlink attribute containing the register number. For
8719 * compatibility reasons, register numbers being a multiple of 4 are
8720 * translated to the corresponding 128 bit register numbers.
8721 */
b1c96ed3
PM
8722int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg)
8723{
49499c3e
PM
8724 if (reg % (NFT_REG_SIZE / NFT_REG32_SIZE) == 0)
8725 reg = reg / (NFT_REG_SIZE / NFT_REG32_SIZE);
8726 else
8727 reg = reg - NFT_REG_SIZE / NFT_REG32_SIZE + NFT_REG32_00;
8728
b1c96ed3
PM
8729 return nla_put_be32(skb, attr, htonl(reg));
8730}
8731EXPORT_SYMBOL_GPL(nft_dump_register);
8732
4f16d25c 8733static int nft_validate_register_load(enum nft_registers reg, unsigned int len)
96518518 8734{
49499c3e 8735 if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE)
96518518 8736 return -EINVAL;
d07db988
PM
8737 if (len == 0)
8738 return -EINVAL;
c593642c 8739 if (reg * NFT_REG32_SIZE + len > sizeof_field(struct nft_regs, data))
d07db988 8740 return -ERANGE;
49499c3e 8741
96518518
PM
8742 return 0;
8743}
4f16d25c
PNA
8744
8745int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len)
8746{
8747 u32 reg;
8748 int err;
8749
8750 reg = nft_parse_register(attr);
8751 err = nft_validate_register_load(reg, len);
8752 if (err < 0)
8753 return err;
8754
8755 *sreg = reg;
8756 return 0;
8757}
8758EXPORT_SYMBOL_GPL(nft_parse_register_load);
96518518 8759
345023b0
PNA
8760static int nft_validate_register_store(const struct nft_ctx *ctx,
8761 enum nft_registers reg,
8762 const struct nft_data *data,
8763 enum nft_data_types type,
8764 unsigned int len)
96518518 8765{
20a69341
PM
8766 int err;
8767
96518518
PM
8768 switch (reg) {
8769 case NFT_REG_VERDICT:
58f40ab6 8770 if (type != NFT_DATA_VERDICT)
96518518 8771 return -EINVAL;
20a69341 8772
58f40ab6 8773 if (data != NULL &&
1ca2e170
PM
8774 (data->verdict.code == NFT_GOTO ||
8775 data->verdict.code == NFT_JUMP)) {
8776 err = nf_tables_check_loops(ctx, data->verdict.chain);
20a69341
PM
8777 if (err < 0)
8778 return err;
20a69341
PM
8779 }
8780
96518518
PM
8781 return 0;
8782 default:
49499c3e 8783 if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE)
27e6d201 8784 return -EINVAL;
45d9bcda
PM
8785 if (len == 0)
8786 return -EINVAL;
49499c3e 8787 if (reg * NFT_REG32_SIZE + len >
c593642c 8788 sizeof_field(struct nft_regs, data))
45d9bcda 8789 return -ERANGE;
27e6d201 8790
96518518
PM
8791 if (data != NULL && type != NFT_DATA_VALUE)
8792 return -EINVAL;
8793 return 0;
8794 }
8795}
345023b0
PNA
8796
8797int nft_parse_register_store(const struct nft_ctx *ctx,
8798 const struct nlattr *attr, u8 *dreg,
8799 const struct nft_data *data,
8800 enum nft_data_types type, unsigned int len)
8801{
8802 int err;
8803 u32 reg;
8804
8805 reg = nft_parse_register(attr);
8806 err = nft_validate_register_store(ctx, reg, data, type, len);
8807 if (err < 0)
8808 return err;
8809
8810 *dreg = reg;
8811 return 0;
8812}
8813EXPORT_SYMBOL_GPL(nft_parse_register_store);
96518518
PM
8814
8815static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = {
8816 [NFTA_VERDICT_CODE] = { .type = NLA_U32 },
8817 [NFTA_VERDICT_CHAIN] = { .type = NLA_STRING,
8818 .len = NFT_CHAIN_MAXNAMELEN - 1 },
51d70f18 8819 [NFTA_VERDICT_CHAIN_ID] = { .type = NLA_U32 },
96518518
PM
8820};
8821
8822static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
8823 struct nft_data_desc *desc, const struct nlattr *nla)
8824{
664b0f8c 8825 u8 genmask = nft_genmask_next(ctx->net);
96518518
PM
8826 struct nlattr *tb[NFTA_VERDICT_MAX + 1];
8827 struct nft_chain *chain;
8828 int err;
8829
8cb08174
JB
8830 err = nla_parse_nested_deprecated(tb, NFTA_VERDICT_MAX, nla,
8831 nft_verdict_policy, NULL);
96518518
PM
8832 if (err < 0)
8833 return err;
8834
8835 if (!tb[NFTA_VERDICT_CODE])
8836 return -EINVAL;
1ca2e170 8837 data->verdict.code = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE]));
96518518 8838
1ca2e170 8839 switch (data->verdict.code) {
e0abdadc 8840 default:
1ca2e170 8841 switch (data->verdict.code & NF_VERDICT_MASK) {
e0abdadc
PM
8842 case NF_ACCEPT:
8843 case NF_DROP:
8844 case NF_QUEUE:
8845 break;
8846 default:
8847 return -EINVAL;
8848 }
954d8297 8849 fallthrough;
96518518
PM
8850 case NFT_CONTINUE:
8851 case NFT_BREAK:
8852 case NFT_RETURN:
96518518
PM
8853 break;
8854 case NFT_JUMP:
8855 case NFT_GOTO:
51d70f18
PNA
8856 if (tb[NFTA_VERDICT_CHAIN]) {
8857 chain = nft_chain_lookup(ctx->net, ctx->table,
8858 tb[NFTA_VERDICT_CHAIN],
8859 genmask);
8860 } else if (tb[NFTA_VERDICT_CHAIN_ID]) {
8861 chain = nft_chain_lookup_byid(ctx->net,
8862 tb[NFTA_VERDICT_CHAIN_ID]);
8863 if (IS_ERR(chain))
8864 return PTR_ERR(chain);
8865 } else {
96518518 8866 return -EINVAL;
51d70f18
PNA
8867 }
8868
96518518
PM
8869 if (IS_ERR(chain))
8870 return PTR_ERR(chain);
f323d954 8871 if (nft_is_base_chain(chain))
96518518
PM
8872 return -EOPNOTSUPP;
8873
96518518 8874 chain->use++;
1ca2e170 8875 data->verdict.chain = chain;
96518518 8876 break;
96518518
PM
8877 }
8878
4c4ed074 8879 desc->len = sizeof(data->verdict);
96518518
PM
8880 desc->type = NFT_DATA_VERDICT;
8881 return 0;
8882}
8883
8884static void nft_verdict_uninit(const struct nft_data *data)
8885{
d0e2c7de
PNA
8886 struct nft_chain *chain;
8887 struct nft_rule *rule;
8888
1ca2e170 8889 switch (data->verdict.code) {
96518518
PM
8890 case NFT_JUMP:
8891 case NFT_GOTO:
d0e2c7de
PNA
8892 chain = data->verdict.chain;
8893 chain->use--;
8894
8895 if (!nft_chain_is_bound(chain))
8896 break;
8897
8898 chain->table->use--;
8899 list_for_each_entry(rule, &chain->rules, list)
8900 chain->use--;
8901
8902 nft_chain_del(chain);
96518518
PM
8903 break;
8904 }
8905}
8906
33d5a7b1 8907int nft_verdict_dump(struct sk_buff *skb, int type, const struct nft_verdict *v)
96518518
PM
8908{
8909 struct nlattr *nest;
8910
ae0be8de 8911 nest = nla_nest_start_noflag(skb, type);
96518518
PM
8912 if (!nest)
8913 goto nla_put_failure;
8914
33d5a7b1 8915 if (nla_put_be32(skb, NFTA_VERDICT_CODE, htonl(v->code)))
96518518
PM
8916 goto nla_put_failure;
8917
33d5a7b1 8918 switch (v->code) {
96518518
PM
8919 case NFT_JUMP:
8920 case NFT_GOTO:
1ca2e170 8921 if (nla_put_string(skb, NFTA_VERDICT_CHAIN,
33d5a7b1 8922 v->chain->name))
96518518
PM
8923 goto nla_put_failure;
8924 }
8925 nla_nest_end(skb, nest);
8926 return 0;
8927
8928nla_put_failure:
8929 return -1;
8930}
8931
d0a11fc3
PM
8932static int nft_value_init(const struct nft_ctx *ctx,
8933 struct nft_data *data, unsigned int size,
96518518
PM
8934 struct nft_data_desc *desc, const struct nlattr *nla)
8935{
8936 unsigned int len;
8937
8938 len = nla_len(nla);
8939 if (len == 0)
8940 return -EINVAL;
d0a11fc3 8941 if (len > size)
96518518
PM
8942 return -EOVERFLOW;
8943
d0a11fc3 8944 nla_memcpy(data->data, nla, len);
96518518
PM
8945 desc->type = NFT_DATA_VALUE;
8946 desc->len = len;
8947 return 0;
8948}
8949
8950static int nft_value_dump(struct sk_buff *skb, const struct nft_data *data,
8951 unsigned int len)
8952{
8953 return nla_put(skb, NFTA_DATA_VALUE, len, data->data);
8954}
8955
8956static const struct nla_policy nft_data_policy[NFTA_DATA_MAX + 1] = {
d0a11fc3 8957 [NFTA_DATA_VALUE] = { .type = NLA_BINARY },
96518518
PM
8958 [NFTA_DATA_VERDICT] = { .type = NLA_NESTED },
8959};
8960
8961/**
8962 * nft_data_init - parse nf_tables data netlink attributes
8963 *
8964 * @ctx: context of the expression using the data
8965 * @data: destination struct nft_data
d0a11fc3 8966 * @size: maximum data length
96518518
PM
8967 * @desc: data description
8968 * @nla: netlink attribute containing data
8969 *
8970 * Parse the netlink data attributes and initialize a struct nft_data.
8971 * The type and length of data are returned in the data description.
8972 *
8973 * The caller can indicate that it only wants to accept data of type
8974 * NFT_DATA_VALUE by passing NULL for the ctx argument.
8975 */
d0a11fc3
PM
8976int nft_data_init(const struct nft_ctx *ctx,
8977 struct nft_data *data, unsigned int size,
96518518
PM
8978 struct nft_data_desc *desc, const struct nlattr *nla)
8979{
8980 struct nlattr *tb[NFTA_DATA_MAX + 1];
8981 int err;
8982
8cb08174
JB
8983 err = nla_parse_nested_deprecated(tb, NFTA_DATA_MAX, nla,
8984 nft_data_policy, NULL);
96518518
PM
8985 if (err < 0)
8986 return err;
8987
8988 if (tb[NFTA_DATA_VALUE])
d0a11fc3
PM
8989 return nft_value_init(ctx, data, size, desc,
8990 tb[NFTA_DATA_VALUE]);
96518518
PM
8991 if (tb[NFTA_DATA_VERDICT] && ctx != NULL)
8992 return nft_verdict_init(ctx, data, desc, tb[NFTA_DATA_VERDICT]);
8993 return -EINVAL;
8994}
8995EXPORT_SYMBOL_GPL(nft_data_init);
8996
8997/**
59105446 8998 * nft_data_release - release a nft_data item
96518518
PM
8999 *
9000 * @data: struct nft_data to release
9001 * @type: type of data
9002 *
9003 * Release a nft_data item. NFT_DATA_VALUE types can be silently discarded,
9004 * all others need to be released by calling this function.
9005 */
59105446 9006void nft_data_release(const struct nft_data *data, enum nft_data_types type)
96518518 9007{
960bd2c2 9008 if (type < NFT_DATA_VERDICT)
96518518 9009 return;
960bd2c2 9010 switch (type) {
96518518
PM
9011 case NFT_DATA_VERDICT:
9012 return nft_verdict_uninit(data);
9013 default:
9014 WARN_ON(1);
9015 }
9016}
59105446 9017EXPORT_SYMBOL_GPL(nft_data_release);
96518518
PM
9018
9019int nft_data_dump(struct sk_buff *skb, int attr, const struct nft_data *data,
9020 enum nft_data_types type, unsigned int len)
9021{
9022 struct nlattr *nest;
9023 int err;
9024
ae0be8de 9025 nest = nla_nest_start_noflag(skb, attr);
96518518
PM
9026 if (nest == NULL)
9027 return -1;
9028
9029 switch (type) {
9030 case NFT_DATA_VALUE:
9031 err = nft_value_dump(skb, data, len);
9032 break;
9033 case NFT_DATA_VERDICT:
33d5a7b1 9034 err = nft_verdict_dump(skb, NFTA_DATA_VERDICT, &data->verdict);
96518518
PM
9035 break;
9036 default:
9037 err = -EINVAL;
9038 WARN_ON(1);
9039 }
9040
9041 nla_nest_end(skb, nest);
9042 return err;
9043}
9044EXPORT_SYMBOL_GPL(nft_data_dump);
9045
5ebe0b0e
PNA
9046int __nft_release_basechain(struct nft_ctx *ctx)
9047{
9048 struct nft_rule *rule, *nr;
9049
fa5950e4
FW
9050 if (WARN_ON(!nft_is_base_chain(ctx->chain)))
9051 return 0;
5ebe0b0e 9052
c974a3a3 9053 nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain);
5ebe0b0e
PNA
9054 list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
9055 list_del(&rule->list);
9056 ctx->chain->use--;
bb7b40ae 9057 nf_tables_rule_release(ctx, rule);
5ebe0b0e 9058 }
1b2470e5 9059 nft_chain_del(ctx->chain);
5ebe0b0e 9060 ctx->table->use--;
43a605f2 9061 nf_tables_chain_destroy(ctx);
5ebe0b0e
PNA
9062
9063 return 0;
9064}
9065EXPORT_SYMBOL_GPL(__nft_release_basechain);
9066
00dfe9be
PNA
9067static void __nft_release_hook(struct net *net, struct nft_table *table)
9068{
9069 struct nft_chain *chain;
9070
9071 list_for_each_entry(chain, &table->chains, list)
9072 nf_tables_unregister_hook(net, table, chain);
9073}
9074
767d1216
PNA
9075static void __nft_release_hooks(struct net *net)
9076{
0854db2a 9077 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
767d1216 9078 struct nft_table *table;
767d1216 9079
0854db2a 9080 list_for_each_entry(table, &nft_net->tables, list) {
2888b080
PNA
9081 if (nft_table_has_owner(table))
9082 continue;
9083
00dfe9be 9084 __nft_release_hook(net, table);
2888b080 9085 }
767d1216
PNA
9086}
9087
fd020332 9088static void __nft_release_table(struct net *net, struct nft_table *table)
df05ef87 9089{
3b49e2e9 9090 struct nft_flowtable *flowtable, *nf;
df05ef87 9091 struct nft_chain *chain, *nc;
e5009240 9092 struct nft_object *obj, *ne;
df05ef87
PNA
9093 struct nft_rule *rule, *nr;
9094 struct nft_set *set, *ns;
9095 struct nft_ctx ctx = {
9096 .net = net,
43a605f2 9097 .family = NFPROTO_NETDEV,
df05ef87
PNA
9098 };
9099
fd020332
PNA
9100 ctx.family = table->family;
9101 ctx.table = table;
9102 list_for_each_entry(chain, &table->chains, list) {
9103 ctx.chain = chain;
9104 list_for_each_entry_safe(rule, nr, &chain->rules, list) {
9105 list_del(&rule->list);
9106 chain->use--;
9107 nf_tables_rule_release(&ctx, rule);
df05ef87 9108 }
df05ef87 9109 }
fd020332
PNA
9110 list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) {
9111 list_del(&flowtable->list);
9112 table->use--;
9113 nf_tables_flowtable_destroy(flowtable);
9114 }
9115 list_for_each_entry_safe(set, ns, &table->sets, list) {
9116 list_del(&set->list);
9117 table->use--;
9118 nft_set_destroy(&ctx, set);
9119 }
9120 list_for_each_entry_safe(obj, ne, &table->objects, list) {
9121 nft_obj_del(obj);
9122 table->use--;
9123 nft_obj_destroy(&ctx, obj);
9124 }
9125 list_for_each_entry_safe(chain, nc, &table->chains, list) {
9126 ctx.chain = chain;
9127 nft_chain_del(chain);
9128 table->use--;
9129 nf_tables_chain_destroy(&ctx);
9130 }
9131 list_del(&table->list);
9132 nf_tables_table_destroy(&ctx);
9133}
9134
bd1777b3 9135static void __nft_release_tables(struct net *net)
fd020332 9136{
0854db2a 9137 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
fd020332
PNA
9138 struct nft_table *table, *nt;
9139
0854db2a 9140 list_for_each_entry_safe(table, nt, &nft_net->tables, list) {
bd1777b3 9141 if (nft_table_has_owner(table))
6001a930
PNA
9142 continue;
9143
fd020332 9144 __nft_release_table(net, table);
6001a930
PNA
9145 }
9146}
9147
9148static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
9149 void *ptr)
9150{
0854db2a 9151 struct nftables_pernet *nft_net;
6001a930
PNA
9152 struct netlink_notify *n = ptr;
9153 struct nft_table *table, *nt;
9154 struct net *net = n->net;
9155 bool release = false;
9156
9157 if (event != NETLINK_URELEASE || n->protocol != NETLINK_NETFILTER)
9158 return NOTIFY_DONE;
9159
0854db2a
FW
9160 nft_net = net_generic(net, nf_tables_net_id);
9161 mutex_lock(&nft_net->commit_mutex);
9162 list_for_each_entry(table, &nft_net->tables, list) {
6001a930
PNA
9163 if (nft_table_has_owner(table) &&
9164 n->portid == table->nlpid) {
9165 __nft_release_hook(net, table);
9166 release = true;
9167 }
9168 }
9169 if (release) {
9170 synchronize_rcu();
0854db2a 9171 list_for_each_entry_safe(table, nt, &nft_net->tables, list) {
6001a930
PNA
9172 if (nft_table_has_owner(table) &&
9173 n->portid == table->nlpid)
9174 __nft_release_table(net, table);
9175 }
9176 }
0854db2a 9177 mutex_unlock(&nft_net->commit_mutex);
6001a930
PNA
9178
9179 return NOTIFY_DONE;
df05ef87
PNA
9180}
9181
6001a930
PNA
9182static struct notifier_block nft_nl_notifier = {
9183 .notifier_call = nft_rcv_nl_event,
9184};
9185
dd4cbef7
PNA
9186static int __net_init nf_tables_init_net(struct net *net)
9187{
0854db2a
FW
9188 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
9189
9190 INIT_LIST_HEAD(&nft_net->tables);
9191 INIT_LIST_HEAD(&nft_net->commit_list);
9192 INIT_LIST_HEAD(&nft_net->module_list);
9193 INIT_LIST_HEAD(&nft_net->notify_list);
9194 mutex_init(&nft_net->commit_mutex);
9195 nft_net->base_seq = 1;
9196 nft_net->validate_state = NFT_VALIDATE_SKIP;
a654de8f 9197
dd4cbef7
PNA
9198 return 0;
9199}
9200
767d1216
PNA
9201static void __net_exit nf_tables_pre_exit_net(struct net *net)
9202{
9203 __nft_release_hooks(net);
9204}
9205
dd4cbef7
PNA
9206static void __net_exit nf_tables_exit_net(struct net *net)
9207{
0854db2a
FW
9208 struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
9209
9210 mutex_lock(&nft_net->commit_mutex);
9211 if (!list_empty(&nft_net->commit_list))
c0391b6a 9212 __nf_tables_abort(net, NFNL_ABORT_NONE);
bd1777b3 9213 __nft_release_tables(net);
0854db2a
FW
9214 mutex_unlock(&nft_net->commit_mutex);
9215 WARN_ON_ONCE(!list_empty(&nft_net->tables));
9216 WARN_ON_ONCE(!list_empty(&nft_net->module_list));
9217 WARN_ON_ONCE(!list_empty(&nft_net->notify_list));
dd4cbef7
PNA
9218}
9219
99633ab2 9220static struct pernet_operations nf_tables_net_ops = {
767d1216
PNA
9221 .init = nf_tables_init_net,
9222 .pre_exit = nf_tables_pre_exit_net,
9223 .exit = nf_tables_exit_net,
0854db2a
FW
9224 .id = &nf_tables_net_id,
9225 .size = sizeof(struct nftables_pernet),
99633ab2
PNA
9226};
9227
96518518
PM
9228static int __init nf_tables_module_init(void)
9229{
9230 int err;
9231
d209df3e
FW
9232 err = register_pernet_subsys(&nf_tables_net_ops);
9233 if (err < 0)
9234 return err;
9235
9236 err = nft_chain_filter_init();
9237 if (err < 0)
6001a930 9238 goto err_chain_filter;
02c7b25e 9239
96518518
PM
9240 err = nf_tables_core_module_init();
9241 if (err < 0)
6001a930 9242 goto err_core_module;
96518518 9243
d209df3e 9244 err = register_netdevice_notifier(&nf_tables_flowtable_notifier);
96518518 9245 if (err < 0)
6001a930 9246 goto err_netdev_notifier;
96518518 9247
4d44175a
FW
9248 err = rhltable_init(&nft_objname_ht, &nft_objname_ht_params);
9249 if (err < 0)
6001a930 9250 goto err_rht_objname;
4d44175a 9251
06d392cb 9252 err = nft_offload_init();
9253 if (err < 0)
6001a930
PNA
9254 goto err_offload;
9255
9256 err = netlink_register_notifier(&nft_nl_notifier);
9257 if (err < 0)
9258 goto err_netlink_notifier;
06d392cb 9259
d209df3e
FW
9260 /* must be last */
9261 err = nfnetlink_subsys_register(&nf_tables_subsys);
9262 if (err < 0)
6001a930 9263 goto err_nfnl_subsys;
3b49e2e9 9264
c1deb065 9265 nft_chain_route_init();
3474a2c6 9266
d209df3e 9267 return err;
6001a930
PNA
9268
9269err_nfnl_subsys:
9270 netlink_unregister_notifier(&nft_nl_notifier);
9271err_netlink_notifier:
06d392cb 9272 nft_offload_exit();
6001a930 9273err_offload:
4d44175a 9274 rhltable_destroy(&nft_objname_ht);
6001a930 9275err_rht_objname:
d209df3e 9276 unregister_netdevice_notifier(&nf_tables_flowtable_notifier);
6001a930 9277err_netdev_notifier:
96518518 9278 nf_tables_core_module_exit();
6001a930 9279err_core_module:
d209df3e 9280 nft_chain_filter_fini();
6001a930 9281err_chain_filter:
d209df3e 9282 unregister_pernet_subsys(&nf_tables_net_ops);
96518518
PM
9283 return err;
9284}
9285
9286static void __exit nf_tables_module_exit(void)
9287{
9288 nfnetlink_subsys_unregister(&nf_tables_subsys);
6001a930 9289 netlink_unregister_notifier(&nft_nl_notifier);
06d392cb 9290 nft_offload_exit();
3b49e2e9 9291 unregister_netdevice_notifier(&nf_tables_flowtable_notifier);
0a2cf5ee 9292 nft_chain_filter_fini();
c1deb065 9293 nft_chain_route_fini();
71ad00c5 9294 unregister_pernet_subsys(&nf_tables_net_ops);
0935d558 9295 cancel_work_sync(&trans_destroy_work);
1b1bc49c 9296 rcu_barrier();
4d44175a 9297 rhltable_destroy(&nft_objname_ht);
96518518 9298 nf_tables_core_module_exit();
96518518
PM
9299}
9300
9301module_init(nf_tables_module_init);
9302module_exit(nf_tables_module_exit);
9303
9304MODULE_LICENSE("GPL");
9305MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
9306MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFTABLES);